Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions sdk/core/allocator/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,8 @@ class MState
*/
[[nodiscard]] __always_inline auto hazard_list_begin()
{
auto *lockWord{SHARED_OBJECT(uint32_t, allocator_epoch)};
auto *lockWord{SHARED_OBJECT_WITH_DATA_PERMISSIONS(
uint32_t, allocator_epoch, true, true)};
uint32_t epoch = *lockWord >> 16;
Debug::Invariant(
(epoch & 1) == 0,
Expand Down Expand Up @@ -1276,9 +1277,14 @@ class MState
bool hazard_pointer_check(Capability<void> allocation)
{
// It is now safe to walk the hazard list.
Capability<void *> hazards =
const_cast<void **>(SHARED_OBJECT_WITH_PERMISSIONS(
void *, allocator_hazard_pointers, true, false, true, false));
Capability<void *> hazards = const_cast<void **>(
SHARED_OBJECT_WITH_PERMISSIONS(void *,
allocator_hazard_pointers,
true,
false,
true,
false,
false));
size_t pointers = hazards.length() / sizeof(void *);
for (size_t i = 0; i < pointers; i++)
{
Expand Down
14 changes: 10 additions & 4 deletions sdk/core/allocator/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,13 @@ namespace
Capability m{tbase.cast<MState>()};

size_t hazardQuarantineSize =
Capability{
SHARED_OBJECT_WITH_PERMISSIONS(
void *, allocator_hazard_pointers, true, false, true, false)}
Capability{SHARED_OBJECT_WITH_PERMISSIONS(void *,
allocator_hazard_pointers,
true,
false,
true,
false,
false)}
.length();

m.bounds() = sizeof(*m);
Expand All @@ -128,13 +132,15 @@ namespace
{
if (gm == nullptr)
{
// Access without LoadGlobal to help ensure we don't break isolation
Capability heap = const_cast<void *>(
MMIO_CAPABILITY_WITH_PERMISSIONS(void,
heap,
/*load*/ true,
/*store*/ true,
/*capabilities*/ true,
/*loadMutable*/ true));
/*loadMutable*/ true,
/*loadGlobal*/ false));

revoker.init();
gm = mstate_init(heap, heap.bounds());
Expand Down
19 changes: 15 additions & 4 deletions sdk/core/loader/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -875,12 +875,18 @@ namespace loader
*/
static constexpr size_t PermitLoadMutable = (1UL << 28);

/**
* Bit in `sizeAndPermissions` indicating that this import has
* load-global permission.
*/
static constexpr size_t PermitLoadGlobal = (1UL << 27);

/**
* Mask for the used permissions.
*/
static constexpr size_t PermissionsMask = PermitLoad | PermitStore |
PermitLoadStoreCapabilities |
PermitLoadMutable;
static constexpr size_t PermissionsMask =
PermitLoad | PermitStore | PermitLoadStoreCapabilities |
PermitLoadMutable | PermitLoadGlobal;

/**
* Mask for the space reserved for permissions.
Expand Down Expand Up @@ -959,7 +965,8 @@ namespace loader
Permission::Load,
Permission::Store,
Permission::LoadStoreCapability,
Permission::LoadMutable};
Permission::LoadMutable,
Permission::LoadGlobal};
CHERI::PermissionSet p{DefaultPermissions};
if ((sizeAndPermissions & PermitLoad) == 0)
{
Expand All @@ -977,6 +984,10 @@ namespace loader
{
p = p.without(Permission::LoadMutable);
}
if ((sizeAndPermissions & PermitLoadGlobal) == 0)
{
p = p.without(Permission::LoadGlobal);
}
return p;
}
};
Expand Down
113 changes: 48 additions & 65 deletions sdk/include/compartment-macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@
* Helper macro for MMIO and pre-shared object imports, should not be used
* directly.
*/
#define IMPORT_CAPABILITY_WITH_PERMISSIONS_HELPER(type, \
name, \
prefix, \
mangledName, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable) \
#define IMPORT_CAPABILITY_WITH_PERMISSIONS_HELPER( \
type, name, prefix, mangledName, ...) \
({ \
static const struct Perms \
{ \
bool permitLoad, permitStore, permitLoadStoreCapabilities, \
permitLoadMutable, permitLoadGlobal; \
} perms = {__VA_ARGS__}; \
type *ret; /* NOLINT(bugprone-macro-parentheses) */ \
__asm(".ifndef " mangledName "\n" \
" .type " mangledName ",@object\n" \
Expand All @@ -36,56 +35,32 @@
" %%cheriot_compartment_hi(" mangledName ")\n" \
" clc %0, %%cheriot_compartment_lo_i(1b)(%0)\n" \
: "=C"(ret) \
: "i"(((permitLoad) ? (1 << 31) : 0) + \
((permitStore) ? (1 << 30) : 0) + \
((permitLoadStoreCapabilities) ? (1 << 29) : 0) + \
((permitLoadMutable) ? (1 << 28) : 0))); \
: "i"(((perms.permitLoad) ? (1 << 31) : 0) + \
((perms.permitStore) ? (1 << 30) : 0) + \
((perms.permitLoadStoreCapabilities) ? (1 << 29) : 0) + \
((perms.permitLoadMutable) ? (1 << 28) : 0) + \
((perms.permitLoadGlobal) ? (1 << 27) : 0))); \
ret; \
})

/**
* Helper macro, should not be used directly.
*/
#define MMIO_CAPABILITY_WITH_PERMISSIONS_HELPER(type, \
name, \
mangledName, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable) \
IMPORT_CAPABILITY_WITH_PERMISSIONS_HELPER(type, \
name, \
__export_mem_, \
mangledName, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable)

/**
* Provide a capability of the type `volatile type *` referring to the MMIO
* region exported in the linker script with `name` as its name. This macro
* can be used only in code (it cannot be used to initialise a global).
*
* The last arguments specify the set of permissions that this capability
* holds. MMIO capabilities are always global and without store local. They
* may optionally omit additional capabilities.
* holds: Load Data (LD), Store Data (SD), Memory Capabilities (MC), Load
* Mutable (LM), and Load Global (LG).
*
* MMIO capabilities are always global (GL) and without store local (SL).
*/
#define MMIO_CAPABILITY_WITH_PERMISSIONS(type, \
name, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable) \
MMIO_CAPABILITY_WITH_PERMISSIONS_HELPER( \
#define MMIO_CAPABILITY_WITH_PERMISSIONS(type, name, ...) \
IMPORT_CAPABILITY_WITH_PERMISSIONS_HELPER( \
volatile type, /* NOLINT(bugprone-macro-parentheses) */ \
name, \
"__import_mem_" #name "_" #permitLoad "_" #permitStore \
"_" #permitLoadStoreCapabilities "_" #permitLoadMutable, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable)
__export_mem_, \
"\"__import_mem_" #name "_" #__VA_ARGS__ "\"", \
__VA_ARGS__)

/**
* Provide a capability of the type `volatile type *` referring to the MMIO
Expand All @@ -97,45 +72,53 @@
* MMIO_CAPABILITY_WITH_PERMISSIONS.
*/
#define MMIO_CAPABILITY(type, name) \
MMIO_CAPABILITY_WITH_PERMISSIONS(type, name, true, true, false, false)
MMIO_CAPABILITY_WITH_PERMISSIONS(type, name, true, true)

/**
* Provide a capability of the type `type *` referring to the pre-shared object
* with `name` as its name. This macro can be used only in code (it cannot be
* used to initialise a global).
*
* The last arguments specify the set of permissions that this capability
* holds. Pre-shared objects are always global and without store local. They
* may optionally omit additional permissions.
* holds: Load Data (LD), Store Data (SD), Memory Capabilities (MC), Load
* Mutable (LM), and Load Global (LG).
*
* Capabilities to pre-shared objects are always global (GL) and without store
* local (SL).
*/
#define SHARED_OBJECT_WITH_PERMISSIONS(type, \
name, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable) \
#define SHARED_OBJECT_WITH_PERMISSIONS(type, name, ...) \
IMPORT_CAPABILITY_WITH_PERMISSIONS_HELPER( \
type, /* NOLINT(bugprone-macro-parentheses) */ \
name, \
__cheriot_shared_object_, \
"__import_cheriot_shared_object_" #name "_" #permitLoad "_" #permitStore \
"_" #permitLoadStoreCapabilities "_" #permitLoadMutable, \
permitLoad, \
permitStore, \
permitLoadStoreCapabilities, \
permitLoadMutable)
"\"__import_cheriot_shared_object_" #name "_" #__VA_ARGS__ "\"", \
__VA_ARGS__)

/**
* Provide a capability of the type `type *` referring to the pre-shared object
* with `name` as its name. This macro can be used only in code (it cannot be
* used to initialise a global).
*
* Pre-shared object capabilities produced by this macro have load, store,
* load-mutable, and load/store-capability permissions. To define a reduced
* set of permissions use `SHARED_OBJECT_WITH_PERMISSIONS`.
* Pre-shared object capabilities produced by this macro have Load Data (LD),
* Store Data (SD), Memory Capability (MC), and Load Mutable (LM) permissions.
* To define a reduced set of permissions use `SHARED_OBJECT_WITH_PERMISSIONS`.
*/
#define SHARED_OBJECT(type, name) \
SHARED_OBJECT_WITH_PERMISSIONS(type, name, true, true, true, true)
SHARED_OBJECT_WITH_PERMISSIONS(type, name, true, true, true, true, true)

/**
* Provide a capability of the type `type *` referring to the pre-shared object
* with `name` as its name. This macro can be used only in code (it cannot be
* used to initialise a global).
*
* Pre-shared object capabilities produced by this macro have the indicated load
* and store permission, but no load/store-capability permissions (and,
* therefore, no load-mutable or load-global permissions).
*/
#define SHARED_OBJECT_WITH_DATA_PERMISSIONS( \
type, name, permitLoad, permitStore) \
SHARED_OBJECT_WITH_PERMISSIONS( \
type, name, permitLoad, permitStore, false, false, false)

/**
* Macro to test whether a device with a specific name exists in the board
Expand Down
6 changes: 3 additions & 3 deletions sdk/lib/compartment_helpers/claim_fast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
int heap_claim_ephemeral(Timeout *timeout, const void *ptr, const void *ptr2)
{
void **hazards = switcher_thread_hazard_slots();
auto *epochCounter{const_cast<
cheriot::atomic<uint32_t> *>(SHARED_OBJECT_WITH_PERMISSIONS(
cheriot::atomic<uint32_t>, allocator_epoch, true, false, false, false))};
auto *epochCounter{const_cast<cheriot::atomic<uint32_t> *>(
SHARED_OBJECT_WITH_DATA_PERMISSIONS(
cheriot::atomic<uint32_t>, allocator_epoch, true, false))};
uint32_t epoch = epochCounter->load();
int values = 2;
// Skip processing pointers that don't refer to heap memory.
Expand Down
3 changes: 1 addition & 2 deletions tests.extra/regress-double_ref_shared/top1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

void top1()
{
auto ref1 =
SHARED_OBJECT_WITH_PERMISSIONS(struct Foo, foo, true, true, false, false);
auto ref1 = SHARED_OBJECT_WITH_DATA_PERMISSIONS(Foo, foo, true, true);

ref1->bar = 1;
}
Expand Down
3 changes: 1 addition & 2 deletions tests.extra/regress-double_ref_shared/top2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ using Debug = ConditionalDebug<true, "top2">;

void top2()
{
auto ref2 = SHARED_OBJECT_WITH_PERMISSIONS(
struct Foo, foo, true, false, false, false);
auto ref2 = SHARED_OBJECT_WITH_DATA_PERMISSIONS(Foo, foo, true, false);

Debug::log("ref2: {}", ref2->bar);
}
16 changes: 12 additions & 4 deletions tests/misc-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -381,22 +381,30 @@ int test_misc()
Permission::Load,
Permission::Store,
Permission::LoadStoreCapability,
Permission::LoadMutable});
Permission::LoadMutable,
Permission::LoadGlobal});
check_shared_object(
"exampleK",
SHARED_OBJECT_WITH_PERMISSIONS(void, exampleK, true, true, false, false),
SHARED_OBJECT_WITH_PERMISSIONS(
void, exampleK, true, true, false, false, false),
1024,
{Permission::Global, Permission::Load, Permission::Store});
check_shared_object(
"test_word",
SHARED_OBJECT_WITH_PERMISSIONS(void, test_word, true, false, true, false),
SHARED_OBJECT_WITH_PERMISSIONS(
void, test_word, true, false, true, false, false),
4,
{Permission::Global, Permission::Load, Permission::LoadStoreCapability});
check_shared_object("test_word",
SHARED_OBJECT_WITH_PERMISSIONS(
void, test_word, true, false, false, false),
void, test_word, true, false, false, false, false),
4,
{Permission::Global, Permission::Load});
check_shared_object(
"test_word data",
SHARED_OBJECT_WITH_DATA_PERMISSIONS(void, test_word, true, false),
4,
{Permission::Global, Permission::Load});
check_odd_memcmp();
TEST_EQUAL(strnlen(*volatileString, 3),
3,
Expand Down
Loading