How do I set the bounds for a capability value?

We can explicitly restrict the bounds of an existing capability by calling the void *cheri_bounds_set(void *capability, size_t bounds) macro function, available in the <cheriintrin.h> header.

This macro takes a more permissive capability (one with larger bounds) and a bound (specified in bytes). It derives a more restricted capability with narrower bounds, which is the return value of the cheri_bounds_set call.

Note that hardware-checked bounds are a key feature of CHERI capabilities. Every capability comes with bounds, which are encoded in the metadata, and will have been set by default by the source of the capability, perhaps malloc or mmap. User code application code may set tighter bounds on capabilities. User code cannot set looser bounds, since this would break the capability monotonicity property (see below).

Here is some example code, where we have a more permissive pointer p and a less permissive version q, with the same base but a smaller bound.

#include <cheriintrin.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *p = malloc(5*sizeof(int));
    int *q = NULL;
    if (p==NULL) {
        fprintf(stderr, "out of memory\n");
    p[4] = 42;
    q = cheri_bounds_set(p, 3*sizeof(int));
    q[2] = 42;
    // can't access q[3] or q[4] !!
    return 0;

What happens if we try to set a more permissive bound?

The monotonicity property of CHERI means we cannot set the bounds of a derived capability to be more permissive than the original capability.

If we call cheri_bounds_set and attempt to derive a more permissive capability, then the capability loses its validity tag, so if it is used in a dereferencing operation it will cause a SIGPROT error.

The gdb single-step execution below illustrates this point:

(gdb) step
13     q = cheri_bounds_set(p, 10*sizeof(int));
(gdb) print p
$2 = (int *) 0x40c0f000 [rwRW,0x40c0f000-0x40c0f014]
(gdb) step
(gdb) print q
$3 = (int *) 0x40c0f000 [rwRW,0x40c0f000-0x40c0f028] (invalid)