| #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); |
| } |