From d76f5fdd28a6a53c5913293c1e518b601a37800d Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Mon, 16 Aug 2021 19:06:19 +0100 Subject: [PATCH] NFC: CapPtr: Introduce "Tame"/"Wild" split This is just the changes to the taxonomy, no use of it in the tree yet --- src/ds/ptrwrap.h | 89 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/src/ds/ptrwrap.h b/src/ds/ptrwrap.h index 359d4e9..b08745e 100644 --- a/src/ds/ptrwrap.h +++ b/src/ds/ptrwrap.h @@ -69,30 +69,67 @@ namespace snmalloc Full }; + /** + * Distinguish pointers proximate provenance: pointers given to us by + * clients can be arbitrarily malformed while pointers from the kernel or + * internally can be presumed well-formed. See the Backend's + * capptr_domesticate(). + */ + enum class Wildness + { + /** + * The purported "pointer" here may just be a pile of bits. On CHERI + * architectures, for example, it may not have a set tag or may be out + * of bounds. + */ + Wild, + /** + * Either this pointer has provenance from the kernel or it has been + * checked by capptr_dewild. + */ + Tame + }; } // namespace dimension /** * The aggregate type of a bound: a Cartesian product of the individual * dimensions, above. */ - template + template< + dimension::Spatial S, + dimension::AddressSpaceControl AS, + dimension::Wildness W> struct bound { static constexpr enum dimension::Spatial spatial = S; static constexpr enum dimension::AddressSpaceControl address_space_control = AS; + static constexpr enum dimension::Wildness wildness = W; /** * Set just the spatial component of the bounds */ template - using with_spatial = bound; + using with_spatial = bound; /** * Set just the address space control component of the bounds */ template - using with_address_space_control = bound; + using with_address_space_control = bound; + + /** + * Set just the wild component of the bounds + */ + template + using with_wildness = bound; + + /* The dimensions here are not used completely orthogonally */ + static_assert( + !(W == dimension::Wildness::Wild) || + (S == dimension::Spatial::Alloc && + AS == dimension::AddressSpaceControl::User), + "Wild pointers must be annotated as tightly bounded"); }; // clang-format off @@ -105,9 +142,10 @@ namespace snmalloc */ template concept ConceptBound = - ConceptSame && + ConceptSame && ConceptSame; + const dimension::AddressSpaceControl> && + ConceptSame; #endif // clang-format on @@ -121,8 +159,10 @@ namespace snmalloc * Internal access to a Chunk of memory. These flow between the ASM and * the slab allocators, for example. */ - using Chunk = - bound; + using Chunk = bound< + dimension::Spatial::Chunk, + dimension::AddressSpaceControl::Full, + dimension::Wildness::Tame>; /** * User access to an entire Chunk. Used as an ephemeral state when @@ -141,6 +181,12 @@ namespace snmalloc */ using Alloc = AllocFull::with_address_space_control< dimension::AddressSpaceControl::User>; + + /** + * A wild (i.e., putative) CBAllocExport pointer handed back by the + * client. See capptr_from_client() and capptr_domesticate(). + */ + using AllocWild = Alloc::with_wildness; } // namespace bounds } // namespace capptr @@ -158,6 +204,11 @@ namespace snmalloc return false; } + if (BI::wildness != BO::wildness) + { + return false; + } + switch (BI::spatial) { using namespace capptr::dimension; @@ -246,6 +297,9 @@ namespace snmalloc SNMALLOC_FAST_PATH T* operator->() const { + static_assert( + bounds::wildness != capptr::dimension::Wildness::Wild, + "Trying to dereference a Wild pointer"); return this->unsafe_capptr; } @@ -278,6 +332,9 @@ namespace snmalloc template using Alloc = CapPtr; + template + using AllocWild = CapPtr; + } // namespace capptr static_assert(sizeof(capptr::Chunk) == sizeof(void*)); @@ -296,7 +353,8 @@ namespace snmalloc /** * With all the bounds and constraints in place, it's safe to extract a void - * pointer (to reveal to the client). Roughly dual to capptr_from_client(). + * pointer (to reveal to the client). Roughly dual to capptr_from_client(), + * but we stop oursevles from revealing anything not known to be domesticated. */ inline SNMALLOC_FAST_PATH void* capptr_reveal(capptr::Alloc p) { @@ -313,6 +371,21 @@ namespace snmalloc return capptr::Alloc(p); } + /** + * It's safe to mark any CapPtr as Wild. + */ + template + static inline SNMALLOC_FAST_PATH CapPtr< + T, + typename B::template with_wildness> + capptr_rewild(CapPtr p) + { + return CapPtr< + T, + typename B::template with_wildness>( + p.unsafe_capptr); + } + /** * * Wrap a std::atomic with bounds annotation and speak in terms of