s
. Unsealed capabilities were redefined as having otype of $2^64 -1$ and this bit was reclaimed as reserved.“The CHERI object-type space is split between userspace and kernel, permitting kernel object references to be delegated to userspace (if desired). Currently, we provide 23 bits of namespace to each, with the top bit set for kernel object types, but it is easy to imagine other splits. User and kernel software should be written so as to not place assumptions about the specific values used here, as they may change.”
//file:
// ./sys/mips/include/cherireg.h
#define CHERI_OTYPE_USER_MIN (0)
#define CHERI_OTYPE_USER_MAX ((1 << 23) - 1)
#define CHERI_OTYPE_KERN_MIN (1 << 23)
#define CHERI_OTYPE_KERN_MAX ((1 << 24) - 1)
#define CHERI_OTYPE_KERN_FLAG (1 << 23)
#define CHERI_OTYPE_ISKERN(x) (((x) & CHERI_OTYPE_KERN_FLAG) != 0)
#define CHERI_OTYPE_ISUSER(x) (!(CHERI_OTYPE_ISKERN(x)))
“When performing a userspace-to-userspace CCall
, capability flow-control
checks normally prevent local capabilities from being delegated. This can
be disabled on call (but not return) by using an object type with the 22nd
bit set – combined with a suitable selector on the CCall
instruction to
ensure that this behaviour is intended.
//file:
// ./sys/mips/include/cherireg.h
#define CHERI_OTYPE_LOCALOK_SHIFT (22)
#define CHERI_OTYPE_LOCALOK_FLAG (1 << CHERI_OTYPE_LOCALOK_SHIFT
#define CHERI_OTYPE_IS_LOCALOK(x) (((x) & CHERI_OTYPE_LOCALOK_FLAG) != 0)
cheri_maketype()
is used to “construct a capability suitable to describe a type identified by ‘ptr’; set it to zero-length with the offset equal to the base.” The caller must
provide a root capability (in the old world order, derived from $ddc, but
in the new world order, likely extracted from the kernel using sysarch(2)).
The caller may wish to assert various properties about the returned capability, including that CHERI_PERM_SEAL is set.
Note: type
value passed in is stored as the offset of the returned otype_t
, which is a capability. (LLM: This means this capability is a pointer that stores an ‘address’ of a type???)
// file:
// sys/cheri/cheric.h
static __inline otype_t
cheri_maketype(void * __capability root_type, register_t type)
{
void * __capability c;
c = root_type;
c = cheri_setoffset(c, type); /* Set type as desired. */
c = cheri_csetbounds(c, 1); /* ISA implies length of 1. */
c = cheri_andperm(c, CHERI_PERM_GLOBAL | CHERI_PERM_SEAL); /* Perms. */
return (c);
}
User space object manipulation is mainly implemented in lib/libcheri/libcheri_type.c. User space type range Total user space type range is [0 , $2^{23}$ - 1 ], and kernel space is [$2^{23}$, $2^{24}$ -1 ]. The user space is further splited into two ranges: non-system type numbers: [1, $2^{22}$ - 1 ]; system type numbers: [$2^{22}$, $2^{23}$ - 1 ]; // file: // lib/libcheri/libcheri_type.c /* The number of bits in the type field of a capability.
Kernel object manipulation is mainly defined in sys/cheri/cheri_otype.c. Kernel Sealing capability A global sealing capability kernel_sealcap is used throughout the kernel; it is initiliazed in _start(). kernel_sealcap is initialized to have PCC with offset CHERI_SEALCAP_KERNEL_BASE, bounds CHERI_SEALCAP_KERNEL_LENGTH, perms CHERI_SEALCAP_KERNEL_PERMS. See more on Cheri kernel booting structs for objects management A struct unrhdr *cheri_otypes is used to maintain a unit number space for type value allocations. The unit number space is created as a set of all possible type values for allocation.
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?