Kernel Object

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. The unit number space is named cheri_otypes, which is defined as:

static struct unrhdr *cheri_otypes;

unit number space: It is a number space described by the unit number space header as below:

// file:
//  sys/sys/_unrhdr.h

/* Header element for a unr number space. */

struct unrhdr {
	TAILQ_HEAD(unrhd,unr)	head;
	u_int			low;	/* Lowest item */
	u_int			high;	/* Highest item */
	u_int			busy;	/* Count of allocated items */
	u_int			alloc;	/* Count of memory allocations */
	u_int			first;	/* items in allocated from start */
	u_int			last;	/* items free at end */
	struct mtx		*mtx;
	TAILQ_HEAD(unrfr,unr)	ppfree;	/* Items to be freed after mtx
					   lock dropped */
};

Basically, it maintains a set of unit numbers from low to high, while keeping track of the number of allocated items, the items allocated, etc.

cheri_otype_init(void * dummy __unused)

The unit numeber space is initialized by creating a struct unrhdr which represents a set of numbers in [CHERI_OTYPE_KERN_MIN, CHERI_OTYPE_KERN_MAX], with a lock cheri_otype_lock, which is used to lock the set internally evey time the unit number is allocated/freed from the set.

// file:
//  sys/cheri/cheri_otype.c
static void cheri_otype_init(void *dummy __unused)
{
	mtx_init(&cheri_otype_lock, "CHERI object type lock", NULL, MTX_DEF);
	cheri_otypes = new_unrhdr(CHERI_OTYPE_KERN_MIN,
	    CHERI_OTYPE_KERN_MAX, &cheri_otype_lock);
}

SYSINIT(cheri_otype_init, SI_SUB_LOCK, SI_ORDER_FIRST, cheri_otype_init, NULL);

This function is called during system startup via registeration of SYSINT macro above.

cheri_otype_alloc(void)

A type is allocated via cheri_otype_alloc(). It returns an otype_t, which is defined as a capability type:

// file
//  sys/sys/types.h

typedef	void * __capability	otype_t;

cheri_otype_alloc use a global sealing capability, kernel_sealcap, to create a capability with a new type. Type value is generated by alloc_unr() which allocates a unit number from unit number space cheri_otype.

kenrel_sealcap is initialized during boot.

// file:
//  sys/cheri/cheri_otype.c
otype_t cheri_otype_alloc(void)
{
        u_int type;

        type = alloc_unr(cheri_otypes);
        if (type == -1)
                return (NULL);
        return (cheri_maketype(kernel_sealcap,
            type - CHERI_SEALCAP_KERNEL_BASE));
}

cheri_otype_free(otype_t cap)

cheri_otype_free is used to return a type to the pool. Ideally we would ensure that no capablities of this type remain in memory, but that would be VERY expensive.
In practice, most consumers will never free a type.

// file:
//  sys/cheri/cheri_otype.c
void cheri_otype_free(otype_t cap)
{
	u_int type;

	type = cheri_getbase(cap);
	free_unr(cheri_otypes, type);
}

Until CheriBSD commit (e430b100ab1e8408ec92655ad26786bb5ec23ef1) on Aug 29, there is no call to ‘cheri_otype_free()’ from any place in the entire cheribsd source code (master branch).

Examples

Until CheriBSD commit (e430b100ab1e8408ec92655ad26786bb5ec23ef1) on Aug 29, there is no call to ‘cheri_otype_alloc()’ from any place in the entire cheribsd source code (master branch).

However, cheri_otype_init is called during system boot.

Created Aug 26, 2019 // Last Updated Oct 27, 2019

If you could revise
the fundmental principles of
computer system design
to improve security...

... what would you change?