| From f27c12d491955c94583512603bf32c4568f20929 Mon Sep 17 00:00:00 2001 |
| From: Michael Walz <code@serpedon.de> |
| Date: Tue, 2 Feb 2021 00:50:29 +0100 |
| Subject: [PATCH] Store a copy of each serialized shared_ptr within the archive |
| to prevent the shared_ptr to be freed to early. (#667) |
| |
| The archives use the memory address pointed by the shared_ptr as a |
| unique id which must not be reused during lifetime of the archive. |
| Therefore, the archives stores a copy of it. |
| This problem was also reported as CVE-2020-11105. |
| |
| [Retrieved from: |
| https://github.com/USCiLab/cereal/commit/f27c12d491955c94583512603bf32c4568f20929] |
| Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> |
| --- |
| include/cereal/cereal.hpp | 13 +++++++++++-- |
| include/cereal/types/memory.hpp | 2 +- |
| 2 files changed, 12 insertions(+), 3 deletions(-) |
| |
| diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp |
| index 99bed9d6..f0d15e8b 100644 |
| --- a/include/cereal/cereal.hpp |
| +++ b/include/cereal/cereal.hpp |
| @@ -369,12 +369,17 @@ namespace cereal |
| point to the same data. |
| |
| @internal |
| - @param addr The address (see shared_ptr get()) pointed to by the shared pointer |
| + @param sharedPointer The shared pointer itself (the adress is taked via get()). |
| + The archive takes a copy to prevent the memory location to be freed |
| + as long as the address is used as id. This is needed to prevent CVE-2020-11105. |
| @return A key that uniquely identifies the pointer */ |
| - inline std::uint32_t registerSharedPointer( void const * addr ) |
| + inline std::uint32_t registerSharedPointer(const std::shared_ptr<const void>& sharedPointer) |
| { |
| + void const * addr = sharedPointer.get(); |
| + |
| // Handle null pointers by just returning 0 |
| if(addr == 0) return 0; |
| + itsSharedPointerStorage.push_back(sharedPointer); |
| |
| auto id = itsSharedPointerMap.find( addr ); |
| if( id == itsSharedPointerMap.end() ) |
| @@ -645,6 +650,10 @@ namespace cereal |
| //! Maps from addresses to pointer ids |
| std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap; |
| |
| + //! Copy of shared pointers used in #itsSharedPointerMap to make sure they are kept alive |
| + // during lifetime of itsSharedPointerMap to prevent CVE-2020-11105. |
| + std::vector<std::shared_ptr<const void>> itsSharedPointerStorage; |
| + |
| //! The id to be given to the next pointer |
| std::uint32_t itsCurrentPointerId; |
| |
| diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp |
| index 59e9da9b..cac1f334 100644 |
| --- a/include/cereal/types/memory.hpp |
| +++ b/include/cereal/types/memory.hpp |
| @@ -263,7 +263,7 @@ namespace cereal |
| { |
| auto & ptr = wrapper.ptr; |
| |
| - uint32_t id = ar.registerSharedPointer( ptr.get() ); |
| + uint32_t id = ar.registerSharedPointer( ptr ); |
| ar( CEREAL_NVP_("id", id) ); |
| |
| if( id & detail::msb_32bit ) |