Skip to content

Commit d96f011

Browse files
tolboothrmn30
authored andcommitted
Added tests for allocator permissions
These tests cover all basic cases of using the allocator permissions to restrict the use of allocator APIs. We test that behaviour is properly restricted, existing tests ensure that the original functionality is undisturbed, and we test that the restrictions don't interfere with one another.
1 parent 13d92b2 commit d96f011

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed

tests/allocator-test.cc

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define TEST_NAME "Allocator"
66

77
#include "tests.hh"
8+
#include <allocator.h>
89
#include <cheri.hh>
910
#include <cheriot-atomic.hh>
1011
#include <cstdlib>
@@ -1223,6 +1224,144 @@ namespace
12231224
debug_log("End of token hazard test");
12241225
}
12251226

1227+
/**
1228+
* Test allocator capability permission restrictions.
1229+
* Tests that the permission bits in sealed allocator capabilities
1230+
* correctly restrict operations across the allocator APIs.
1231+
*/
1232+
__noinline void test_permissions()
1233+
{
1234+
debug_log("Beginning permission restriction tests");
1235+
1236+
Timeout t{UnlimitedTimeout};
1237+
size_t allocSize = 128;
1238+
1239+
auto noAllocCap =
1240+
allocator_permissions_and(SECOND_HEAP, ~AllocatorPermitAllocate);
1241+
auto noFreeAllCap =
1242+
allocator_permissions_and(SECOND_HEAP, ~AllocatorPermitFreeAll);
1243+
auto noPermsCap =
1244+
allocator_permissions_and(SECOND_HEAP, AllocatorPermitNone);
1245+
1246+
// Verify permission getter returns correct permission bits
1247+
TEST_EQUAL((allocator_permissions(noAllocCap) & AllocatorPermitFreeAll),
1248+
AllocatorPermitFreeAll,
1249+
"no-allocate capability has wrong permissions");
1250+
TEST_EQUAL(
1251+
(allocator_permissions(noFreeAllCap) & AllocatorPermitAllocate),
1252+
AllocatorPermitAllocate,
1253+
"no-free-all capability has wrong permissions");
1254+
TEST_EQUAL(allocator_permissions(SECOND_HEAP),
1255+
AllocatorPermitFull,
1256+
"full capability has wrong permissions");
1257+
TEST_EQUAL(allocator_permissions(noPermsCap),
1258+
AllocatorPermitNone,
1259+
"fully depermissioned capability has wrong permissions");
1260+
1261+
// Verify fully depermissioned capability can still heap_free
1262+
void *ptr = heap_allocate(&t, SECOND_HEAP, allocSize);
1263+
TEST(__builtin_cheri_tag_get(ptr),
1264+
"Failed to allocate for depermissioned free test");
1265+
TEST_EQUAL(heap_free(noPermsCap, ptr),
1266+
0,
1267+
"heap_free failed with fully depermissioned capability");
1268+
1269+
// Try to allocate with no-allocate quota
1270+
ptr = heap_allocate(&t, noAllocCap, allocSize);
1271+
TEST(!__builtin_cheri_tag_get(ptr),
1272+
"Allocation succeeded with no-allocate quota");
1273+
// Ensure that no-allocate can still free (heap_free is always allowed)
1274+
ptr = heap_allocate(&t, SECOND_HEAP, allocSize);
1275+
TEST(__builtin_cheri_tag_get(ptr),
1276+
"Failed to allocate for free permission test");
1277+
TEST_EQUAL(
1278+
heap_free(noAllocCap, ptr), 0, "Free failed with no-alloc quota");
1279+
1280+
// Ensure that no-free-all can still allocate
1281+
ptr = heap_allocate(&t, noFreeAllCap, allocSize);
1282+
TEST(__builtin_cheri_tag_get(ptr),
1283+
"Failed to allocate for free permission test");
1284+
// heap_free should still work with no-free-all quota
1285+
TEST_EQUAL(heap_free(noFreeAllCap, ptr),
1286+
0,
1287+
"heap_free failed with no-free-all quota");
1288+
1289+
// Try to claim with owner no-allocate quota
1290+
ptr = heap_allocate(&t, SECOND_HEAP, allocSize);
1291+
TEST(__builtin_cheri_tag_get(ptr),
1292+
"Failed to allocate for claim permission test");
1293+
TEST_EQUAL(heap_claim(noAllocCap, ptr),
1294+
-EPERM,
1295+
"Owner claim succeeded with no-allocate quota");
1296+
TEST_EQUAL(heap_free(SECOND_HEAP, ptr), 0, "Cleanup free failed");
1297+
1298+
// Try to claim with non-owner no-allocate quota
1299+
void *mallocPtr = heap_allocate(&t, MALLOC_CAPABILITY, allocSize);
1300+
TEST(__builtin_cheri_tag_get(mallocPtr),
1301+
"Failed to allocate for claim permission test");
1302+
TEST_EQUAL(heap_claim(noAllocCap, mallocPtr),
1303+
-EPERM,
1304+
"Non-owner claim succeeded with no-allocate quota");
1305+
1306+
// Release claim should work with no-free-all quota (heap_free is
1307+
// implicit)
1308+
TEST(heap_claim(SECOND_HEAP, mallocPtr) > 0,
1309+
"Failed to claim for claim release permission test");
1310+
TEST_EQUAL(heap_free(noFreeAllCap, mallocPtr),
1311+
0,
1312+
"Released claim failed with no-free-all quota");
1313+
TEST_EQUAL(
1314+
heap_free(MALLOC_CAPABILITY, mallocPtr), 0, "Cleanup free failed");
1315+
1316+
// Try heap_free_all with no-free-all quota
1317+
ptr = heap_allocate(&t, SECOND_HEAP, allocSize);
1318+
TEST(__builtin_cheri_tag_get(ptr),
1319+
"Failed to allocate for free_all permission test");
1320+
ssize_t freed = heap_free_all(noFreeAllCap);
1321+
TEST_EQUAL(
1322+
freed, -EPERM, "heap_free_all succeeded with no-free-all quota");
1323+
TEST(Capability{ptr}.is_valid(),
1324+
"Object freed despite permission denial");
1325+
TEST(heap_free_all(SECOND_HEAP) >= allocSize,
1326+
"Cleanup free_all failed");
1327+
1328+
// Try heap_allocate_array with no-allocate quota
1329+
int numAllocs = 4;
1330+
ptr = heap_allocate_array(&t, noAllocCap, numAllocs, allocSize);
1331+
TEST(!Capability{ptr}.is_valid(),
1332+
"Array allocation succeeded with no-allocate quota: ",
1333+
"{}",
1334+
ptr);
1335+
1336+
// Try to make sealed allocation with no-allocate quota
1337+
auto sealingCapability = STATIC_SEALING_TYPE(sealingTest);
1338+
void *unsealedCapability;
1339+
Capability sealedPointer = token_sealed_unsealed_alloc(
1340+
&t, noAllocCap, sealingCapability, 128, &unsealedCapability);
1341+
TEST(!sealedPointer.is_valid(),
1342+
"Sealed object allocation succeeded with no-allocate quota: "
1343+
"{}",
1344+
sealedPointer);
1345+
1346+
// Verify heap_can_free works with restricted permissions
1347+
ptr = heap_allocate(&t, SECOND_HEAP, allocSize);
1348+
TEST(__builtin_cheri_tag_get(ptr),
1349+
"Failed to allocate for heap_can_free test");
1350+
TEST_EQUAL(heap_can_free(noPermsCap, ptr),
1351+
0,
1352+
"heap_can_free failed with fully depermissioned capability");
1353+
1354+
// Verify heap_quota_remaining works with restricted permissions
1355+
ssize_t quotaRemaining = heap_quota_remaining(noPermsCap);
1356+
TEST(quotaRemaining >= 0,
1357+
"heap_quota_remaining failed with no-allocate capability");
1358+
1359+
// Cleanup
1360+
TEST_EQUAL(heap_free(SECOND_HEAP, ptr), 0, "Final cleanup free failed");
1361+
1362+
debug_log("End of permission restriction tests");
1363+
}
1364+
12261365
} // namespace
12271366

12281367
/**
@@ -1292,6 +1431,7 @@ int test_allocator()
12921431
"After alloc and free from 1024-byte quota, {} bytes left",
12931432
quotaLeft);
12941433
test_claims();
1434+
test_permissions();
12951435

12961436
TEST(heap_address_is_valid(&t) == false,
12971437
"Stack object incorrectly reported as heap address");

0 commit comments

Comments
 (0)