blob: 76ee8f7efc17da3630240480bba1797329bf634b [file] [log] [blame]
#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);
}