Libcheri CCall and Trampolines

libcheri_ccall.c

This file provides the C implementation of the userspace CCall trampoline for libcheri. Three object types are used: CCall path into rtld initialization, invocation, and CReturn.

For CCall data capabilities, we use the sandbox object pointer, where we can find any data required to perform the domain transition, including a suitable capability for use with TLS.
Currently, this means deriving these sealed data capabilities from DDC. (LLM: ??? where to derive in the future)

For CReturn data capabilities, we use a pointer to a global data structure that contains a suitable capability for use with TLS – as with above, we currently derive this capability from DDC.

XXXRW: Will we also want to do something to provide per-thread execution stacks to handle failures in CCall and CReturn.

XXXRW: How to handle signal delivery during CCall and CReturn?

init, ccall, and creturn vectors

External assembly trampolines for Initialization, CCall/invocation and CReturn. Ideally the rtld and general invocation vectors might be shared, but userspace CCall cannot currently reliable access the operand object type (see comments in trampoline source code: L129.)

// file
//  lib/libcheri/libcheri_ccall.c
extern void	libcheri_ccall_rtld_vector;
extern void	libcheri_ccall_invoke_vector;
extern void	libcheri_creturn_vector;

They are trampolines defined in lib/libcheri/mips/libcheri_ccall_trampoline.S. More details here.

Sealing capabilities

Sealing capabilities used to seal invocation, rtld, and creturn capabilities.

// file
//  lib/libcheri/libcheri_ccall.c
static void * __capability       libcheri_ccall_invoke_type;
static void * __capability       libcheri_ccall_rtld_type;
static void * __capability       libcheri_creturn_type;
Three sealed capabilities

The following sealed capabilities are shared across all sandbox objects: code for invocation and rtld; code and data for creturn:

// file
//  lib/libcheri/libcheri_ccall.c
static void * __capability	 libcheri_ccall_invoke_sealed_code;
static void * __capability	 libcheri_ccall_rtld_sealed_code;
static struct cheri_object	 libcheri_creturn_object;

CCall init

libcheri_ccall_init(void), defined in file lib/libcheri/libcheri_ccall.c

This is a one-time initialisation of libcheri on startup:

  • (1) Initialise sealing capabilities for invocation, rtld, and creturn; and
  • (2) Initialise sealed capabilities where the values will be shared across many sandboxes.

Initialize the sealing cap:

// file
//  lib/libcheri/libcheri_ccall.c: libcheri_ccall_init(void)

	/*
	 * Initialise sealing capabilities for invocation, rtld, and creturn,
	 *
	 */
	libcheri_ccall_invoke_type = libcheri_type_alloc();
	libcheri_ccall_rtld_type = libcheri_type_alloc();
	libcheri_creturn_type = libcheri_type_alloc();

	/*
	 * Pointer to the invocation vector.
	 */
	cap = cheri_getpcc();
	cap = cheri_setaddress(cap, (vaddr_t)&libcheri_ccall_invoke_vector);
	libcheri_ccall_invoke_sealed_code = cheri_seal(cap,
	    libcheri_ccall_invoke_type);

	/*
	 * Pointer to the rtld vector.
	 */
	cap = cheri_getpcc();
	cap = cheri_setaddress(cap, (vaddr_t)&libcheri_ccall_rtld_vector);
	libcheri_ccall_rtld_sealed_code =
	    cheri_seal(cap, libcheri_ccall_rtld_type);

	/*
	 * Pointer to the creturn vector, with global bounds in order to
	 * provide access to the trusted stack (etc).  There is no
	 * call-specific data, so use dummy data.
	 *
	 * XXXRW: Global bounds only for code, not data..?
	 */
	cap = cheri_getpcc();
	cap = cheri_setaddress(cap, (vaddr_t)&libcheri_creturn_vector);
	libcheri_creturn_object.co_codecap =
	    cheri_seal(cap, libcheri_creturn_type);

#ifdef __CHERI_CAPABILITY_TLS__
	cap = &libcheri_creturn_data;
#else
	/*
	 * Needed without bounds so it covers TLS.
	 */
	cap = cheri_getdefault();
	cap = cheri_setaddress(cap, (vaddr_t)&libcheri_creturn_data);
#endif
	libcheri_creturn_object.co_datacap =
	    cheri_seal(cap, libcheri_creturn_type);
  • Trampolines
  • file: lib/libcheri/mips/libcheri_ccall_trampoline.S This file contains “userspace implementation of libcheri invocation and return semantics”. “These vectors are intended to run on the inside of sealed call and return code capabilities, perform any necessary checks, transform the capability register file, and then jump into the target domain. Outline of trampolines Three types of objects and with corresponding three kinds of CCalls: for rtld init: libcheri_ccall_rtld_vector: is used for rtld initialization and destruction.

Created Aug 29, 2019 // Last Updated Sep 3, 2019

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

... what would you change?