blob: c0791857a2f1ac98b571f728c328752df65be4e5 [file] [log] [blame]
// Copyright CHERIoT Contributors.
// SPDX-License-Identifier: MIT
#define TEST_NAME "Test check_pointer"
#include "tests.hh"
int object;
using namespace CHERI;
/**
* Test the `EnforceStrictPermissions` feature of `CHERI::check_pointer`.
*
* This test checks the following:
*
* 1. When passed `EnforceStrictPermissions = false` (default behavior),
* `CHERI::check_pointer` does not modify the permissions and length of
* passed capability with a Capability argument.
* 2. When passed `EnforceStrictPermissions = false` (default behavior),
* `CHERI::check_pointer` does not modify the permissions and length of
* passed capability with a raw capability argument.
* 3. When passed `EnforceStrictPermissions = true`, `CHERI::check_pointer`
* changes permissions and length appropriately with a Capability argument.
* 4. When passed `EnforceStrictPermissions = true`, `CHERI::check_pointer`
* changes permissions and length appropriately with a raw capability
* argument.
* 5. For both 3. and 4., it also checks that `EnforceStrictPermissions = true`
* does not invalidate the capability.
*/
void check_pointer_strict_mode(int *ptr)
{
bool isValid;
Capability cap{ptr};
debug_log("Test default check_pointer (EnforceStrictPermissions = false).");
debug_log("Test with Capability argument.");
PermissionSet permissionsAtCreation = cap.permissions();
auto boundsAtCreation = cap.bounds();
// Check that the capability has > load permissions at creation.
TEST(permissionsAtCreation.contains(Permission::Load, Permission::Store),
"Permissions of new capability do not include load/store.");
// Check that the capability has length > 1 at creation.
TEST(boundsAtCreation > 1,
"Permissions of new capability do not include load/store.");
// We will detect if `check_pointer` changes the permissions because we
// are calling load only and bounds = 1 here.
TEST(check_pointer<PermissionSet{Permission::Load}>(cap, 1),
"Cannot check valid capability (calling with Capability object).");
TEST(cap.permissions() == permissionsAtCreation,
"check_pointer reduced the permissions of passed Capability "
"object although EnforceStrictPermissions = false.");
TEST(cap.bounds() == boundsAtCreation,
"check_pointer reduced the bounds of passed Capability "
"object although EnforceStrictPermissions = false.");
debug_log("Test with raw capability argument.");
TEST(check_pointer<PermissionSet{Permission::Load}>(ptr, 1),
"Cannot check valid capability (calling with raw capability).");
Capability capShouldBeTheSame{ptr};
TEST(capShouldBeTheSame.permissions() == permissionsAtCreation,
"check_pointer reduced the permissions of passed raw "
"capability although EnforceStrictPermissions = false.");
TEST(capShouldBeTheSame.bounds() == boundsAtCreation,
"check_pointer reduced the bounds of passed Capability "
"capability although EnforceStrictPermissions = false.");
debug_log("Test check_pointer with EnforceStrictPermissions = true.");
debug_log("Test with Capability argument.");
// We can re-use `cap` here because it was not changed.
isValid =
check_pointer<PermissionSet{Permission::Load}, true, true>(cap, 1);
TEST(isValid,
"Cannot check valid capability when EnforceStrictPermissions = true "
"(calling with Capability object).");
// The capability should now be load-only.
TEST(cap.permissions() == PermissionSet{Permission::Load},
"check_pointer did not reduce the permissions of passed Capability "
"object although EnforceStrictPermissions = true.");
// The bounds should now be 1.
TEST(cap.bounds() == 1,
"check_pointer did not reduce the bounds of passed Capability "
"object although EnforceStrictPermissions = true.");
TEST(check_pointer<PermissionSet{Permission::Load}>(cap, 1),
"EnforceStrictPermissions = true breaks the capability when called "
"with a Capability object.");
debug_log("Test with raw capability argument.");
// We cannot re-use `cap` because it was changed.
Capability cap2{ptr};
TEST(
cap2.permissions() == permissionsAtCreation,
"Permissions of freshly created capability do not include load/store.");
isValid =
check_pointer<PermissionSet{Permission::Load}, true, true>(ptr, 1);
TEST(isValid,
"Cannot check valid capability when EnforceStrictPermissions = true "
"(calling with raw capability).");
// We need to create a new Capability object with the updated pointer
// to check its permissions.
Capability cap3{ptr};
TEST(cap3.permissions() == PermissionSet{Permission::Load},
"check_pointer did not reduce the permissions of passed raw "
"capability although EnforceStrictPermissions = true.");
TEST(cap3.bounds() == 1,
"check_pointer did not reduce the bounds of passed raw "
"capability although EnforceStrictPermissions = true.");
TEST(check_pointer<PermissionSet{Permission::Load}>(ptr, 1),
"EnforceStrictPermissions = true breaks the capability when called "
"with a raw capability.");
}
int test_check_pointer()
{
check_pointer_strict_mode(&object);
return 0;
}