1From f27c12d491955c94583512603bf32c4568f20929 Mon Sep 17 00:00:00 2001 2From: Michael Walz <code@serpedon.de> 3Date: Tue, 2 Feb 2021 00:50:29 +0100 4Subject: [PATCH] Store a copy of each serialized shared_ptr within the archive 5 to prevent the shared_ptr to be freed to early. (#667) 6 7The archives use the memory address pointed by the shared_ptr as a 8unique id which must not be reused during lifetime of the archive. 9Therefore, the archives stores a copy of it. 10This problem was also reported as CVE-2020-11105. 11 12[Retrieved from: 13https://github.com/USCiLab/cereal/commit/f27c12d491955c94583512603bf32c4568f20929] 14Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> 15--- 16 include/cereal/cereal.hpp | 13 +++++++++++-- 17 include/cereal/types/memory.hpp | 2 +- 18 2 files changed, 12 insertions(+), 3 deletions(-) 19 20diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp 21index 99bed9d6..f0d15e8b 100644 22--- a/include/cereal/cereal.hpp 23+++ b/include/cereal/cereal.hpp 24@@ -369,12 +369,17 @@ namespace cereal 25 point to the same data. 26 27 @internal 28- @param addr The address (see shared_ptr get()) pointed to by the shared pointer 29+ @param sharedPointer The shared pointer itself (the adress is taked via get()). 30+ The archive takes a copy to prevent the memory location to be freed 31+ as long as the address is used as id. This is needed to prevent CVE-2020-11105. 32 @return A key that uniquely identifies the pointer */ 33- inline std::uint32_t registerSharedPointer( void const * addr ) 34+ inline std::uint32_t registerSharedPointer(const std::shared_ptr<const void>& sharedPointer) 35 { 36+ void const * addr = sharedPointer.get(); 37+ 38 // Handle null pointers by just returning 0 39 if(addr == 0) return 0; 40+ itsSharedPointerStorage.push_back(sharedPointer); 41 42 auto id = itsSharedPointerMap.find( addr ); 43 if( id == itsSharedPointerMap.end() ) 44@@ -645,6 +650,10 @@ namespace cereal 45 //! Maps from addresses to pointer ids 46 std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap; 47 48+ //! Copy of shared pointers used in #itsSharedPointerMap to make sure they are kept alive 49+ // during lifetime of itsSharedPointerMap to prevent CVE-2020-11105. 50+ std::vector<std::shared_ptr<const void>> itsSharedPointerStorage; 51+ 52 //! The id to be given to the next pointer 53 std::uint32_t itsCurrentPointerId; 54 55diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp 56index 59e9da9b..cac1f334 100644 57--- a/include/cereal/types/memory.hpp 58+++ b/include/cereal/types/memory.hpp 59@@ -263,7 +263,7 @@ namespace cereal 60 { 61 auto & ptr = wrapper.ptr; 62 63- uint32_t id = ar.registerSharedPointer( ptr.get() ); 64+ uint32_t id = ar.registerSharedPointer( ptr ); 65 ar( CEREAL_NVP_("id", id) ); 66 67 if( id & detail::msb_32bit ) 68