| #include <cheri.hh> | |
| using namespace CHERI; | |
| /** | |
| * C API for `check_pointer`. | |
| * | |
| * See `cheri.hh` for more information. | |
| */ | |
| bool check_pointer(const void *ptr, | |
| size_t space, | |
| uint32_t rawPermissions, | |
| bool checkStackNeeded) | |
| { | |
| auto permissions = PermissionSet::from_raw(rawPermissions); | |
| Capability<const void> cap{ptr}; | |
| bool isValid = cap.is_valid() && !cap.is_sealed(); | |
| // Skip the stack check if we're requiring a global capability. By | |
| // construction, such a thing cannot be derived from the stack | |
| // pointer. | |
| if (checkStackNeeded) | |
| { | |
| Capability<void> stack{__builtin_cheri_stack_get()}; | |
| // Check that the capability does not overlap the | |
| // stack. The base of the capability is <= its top, so | |
| // the capability is in bounds as long as either: | |
| // - its top is below the current stack or; | |
| // - its base is above the top of the current stack. | |
| isValid &= (cap.top() <= stack.base()) || (cap.base() >= stack.top()); | |
| } | |
| isValid &= cap.bounds() >= space; | |
| // Check that we have, at least, the required permissions | |
| isValid &= permissions.can_derive_from(cap.permissions()); | |
| return isValid; | |
| } | |
| bool __cheri_libcall check_timeout_pointer(const struct Timeout *timeout) | |
| { | |
| return !heap_address_is_valid(timeout) && | |
| check_pointer( | |
| timeout, | |
| sizeof(struct Timeout), | |
| PermissionSet{Permission::Load, Permission::Store}.as_raw(), | |
| false); | |
| } |