CHERI: Avoid traps on nullptr

The CHERI-RISC-V `CAndPerm` and `CSetBoundsExact` instructions trap on untagged
inputs, so avoid passing `nullptr` to primitives that become those instructions.
This commit is contained in:
Nathaniel Wesley Filardo
2021-11-11 14:44:36 +00:00
committed by Nathaniel Wesley Filardo
parent 13a4b0471e
commit 3a509d41f0
2 changed files with 47 additions and 0 deletions

View File

@@ -21,6 +21,38 @@ namespace snmalloc
static constexpr uint64_t aal_features =
(Base::aal_features & ~IntegerPointers) | StrictProvenance;
enum AalCheriFeatures : uint64_t
{
/**
* This CHERI flavor traps if the capability input to a bounds-setting
* instruction has its tag clear, rather than just leaving the output
* untagged.
*
* For example, CHERI-RISC-V's CSetBoundsExact traps in contrast to
* Morello's SCBNDSE.
*/
SetBoundsTrapsUntagged = (1 << 0),
/**
* This CHERI flavor traps if the capability input to a
* permissions-masking instruction has its tag clear, rather than just
* leaving the output untagged.
*
* For example, CHERI-RISC-V's CAndPerms traps in contrast to Morello's
* CLRPERM.
*/
AndPermsTrapsUntagged = (1 << 0),
};
/**
* Specify "features" of the particular CHERI machine we're running on.
*/
static constexpr uint64_t aal_cheri_features =
/* CHERI-RISC-V prefers to trap on untagged inputs. Morello does not. */
(Base::aal_name == RISCV ?
SetBoundsTrapsUntagged | AndPermsTrapsUntagged :
0);
/**
* On CHERI-aware compilers, ptraddr_t is an integral type that is wide
* enough to hold any address that may be contained within a memory
@@ -45,6 +77,14 @@ namespace snmalloc
"capptr_bound must preserve non-spatial CapPtr dimensions");
SNMALLOC_ASSERT(__builtin_cheri_tag_get(a.unsafe_ptr()));
if constexpr (aal_cheri_features & SetBoundsTrapsUntagged)
{
if (a == nullptr)
{
return nullptr;
}
}
void* pb = __builtin_cheri_bounds_set_exact(a.unsafe_ptr(), size);
return CapPtr<T, BOut>(static_cast<T*>(pb));
}

View File

@@ -57,6 +57,13 @@ namespace snmalloc
static SNMALLOC_FAST_PATH CapPtr<T, capptr::user_address_control_type<B>>
capptr_to_user_address_control(CapPtr<T, B> p)
{
if constexpr (Aal::aal_cheri_features & Aal::AndPermsTrapsUntagged)
{
if (p == nullptr)
{
return nullptr;
}
}
return CapPtr<T, capptr::user_address_control_type<B>>(
__builtin_cheri_perms_and(
p.unsafe_ptr(),