From c5b65d07b8079b22eec9f78bec197ea7a0fd15f2 Mon Sep 17 00:00:00 2001 From: Nathaniel Filardo Date: Tue, 23 Mar 2021 18:49:50 +0000 Subject: [PATCH] FreeObject: hide harder from the compiler, tweak types On CHERI, the compiler will always issue a warning for `reinterpret_cast(ptraddr_t)` and similar expressions, and of course, if the compiler can see far enough into the types, the presence of `if constexpr` will not save us. Therefore, lift the conditional out to two definitions of `FreeObject::encode` using `std::enable_if_t` to gate which is used. --- src/mem/freelist.h | 58 +++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/mem/freelist.h b/src/mem/freelist.h index c0770d7..5feed0c 100644 --- a/src/mem/freelist.h +++ b/src/mem/freelist.h @@ -68,29 +68,45 @@ namespace snmalloc { FreeObject* reference; - public: - static inline FreeObject* - encode(uint16_t local_key, FreeObject* next_object) - { -#ifdef CHECK_CLIENT - if constexpr (aal_supports) - { - // Simple involutional encoding. The bottom half of each word is - // multiplied by a function of both global and local keys (the latter, - // in practice, being the address of the previous list entry) and the - // resulting word's top part is XORed into the pointer value before it - // is stored. - auto next = address_cast(next_object); - constexpr address_t MASK = bits::one_at_bit(PRESERVE_BOTTOM_BITS) - 1; - // Mix in local_key - address_t key = (local_key + 1) * global_key; - next ^= (((next & MASK) + 1) * key) & - ~(bits::one_at_bit(PRESERVE_BOTTOM_BITS) - 1); - next_object = reinterpret_cast(next); - } + /** + * On architectures which use IntegerPointers, we can obfuscate our free + * lists and use this to drive some probabilistic checks for integrity. + * + * There are two definitions of encode() below, which use std::enable_if_t + * to gate on do_encode. + */ +#ifndef CHECK_CLIENT + static constexpr bool do_encode = false; #else - UNUSED(local_key); + static constexpr bool do_encode = aal_supports; #endif + + public: +#ifdef CHECK_CLIENT + template + static std::enable_if_t + encode(uint16_t local_key, T* next_object) + { + // Simple involutional encoding. The bottom half of each word is + // multiplied by a function of both global and local keys (the latter, + // in practice, being the address of the previous list entry) and the + // resulting word's top part is XORed into the pointer value before it + // is stored. + auto next = address_cast(next_object); + constexpr address_t MASK = bits::one_at_bit(PRESERVE_BOTTOM_BITS) - 1; + // Mix in local_key + address_t key = (local_key + 1) * global_key; + next ^= (((next & MASK) + 1) * key) & + ~(bits::one_at_bit(PRESERVE_BOTTOM_BITS) - 1); + return reinterpret_cast(next); + } +#endif + + template + static std::enable_if_t + encode(uint16_t local_key, T* next_object) + { + UNUSED(local_key); return next_object; }