The object type in user space is splited into two ranges:
- non-system type numbers: [1, $2^{22}$ - 1 ];
- system type numbers: [$2^{22}$, $2^{23}$ - 1 ];
while the object types in kernel space is [$2^{23}$, $2^{24}$ -1 ].
Cheri System class is the CHERI system type of the system library.
libcheri_system_type
IN file: lib/libcheri/libcheri_system.h:
The header defines the interface for the libcheri system class. Currently, it is a bit catch-all, and provides a few key service that make it easy to implement (and debug) sandboxed code. In the future, we anticipate the system class being an entry point to a number of other classes – e.g., providing an open() method that returns file-descriptor objects. We are definitely not yet at that point.
// file
// lib/libcheri/libcheri_system.h
/*
* XXXRW: Probably should be library-private: the CHERI type of the system
* library.
*/
extern void * __capability libcheri_system_type;
// ??? but where it is assigned to a value?
Never called in current CHERIBSD source code
// file
// lib/libcheri/libcheri_type.c
void * __capability
libcheri_system_type_alloc(void)
{
return (libcheri_alloc_type_capability(&libcheri_system_type_next,
libcheri_system_type_max));
}
libcheri_system_new(...)
creates a new CHERI system object for use with a specific sandbox object.
This is called during sandbox loading process.
int
libcheri_system_new(struct sandbox_object *sbop,
struct sandbox_object **sbopp)
{
void * __capability invoke_pcc;
/*
* Construct an object capability for the system-class instance that
* will be passed into the sandbox.
*
* The private data pointer is to the sandbox object that this system
* object serves.
*
* The code capability will simply be our $pcc.
*
* XXXRW: For now, we will populate $c0 with $pcc on invocation, so we
* need to leave a full set of permissions on it. Eventually, we
* would prefer to limit this to LOAD and EXECUTE.
*
* XXXRW: We should do this once per class .. or even just once
* globally, rather than on every object creation.
*
* XXXRW: Use cheri_codeptr() here in the future?
*
* XXXRW: Is this up-to-date?
*
* Set up vector pointer, remove sealing, point at tranpoline?
*/
invoke_pcc = cheri_getpcc();
invoke_pcc = cheri_setaddress(
invoke_pcc, (register_t)LIBCHERI_CLASS_ENTRY(libcheri_system));
return (sandbox_object_new_system_object(
(__cheri_tocap void * __capability)(void *)sbop, invoke_pcc,
libcheri_system_vtable, sbopp));
}
// file
// lib/libcheri/libcheri_system.h/c
/*
* Just a test function.
*/
int libcheri_system_helloworld(void);
/*
* Implementation of puts(), but with a capability argument. No persistent
* state, so no recovery required if an exception is thrown due to a bad
* capability being passed in.
*/
int libcheri_system_puts(const char * __capability str);
int libcheri_system_putchar(int c);
int libcheri_system_clock_gettime(clockid_t clock_id, struct timespec * __capability tp);
int libcheri_system_calloc(size_t number, size_t size, void * __capability * __capability ptrp);
int libcheri_system_free(void * __capability ptr);
/*
* Call a legacy user function.
*/
int libcheri_system_user_call_fn(register_t methodnum,
register_t a0, register_t a1, register_t a2,
register_t a3, register_t a4, register_t a5,
register_t a6,
void * __capability c3, void * __capability c4,
void * __capability c5, void * __capability c6,
void * __capability c7);
/*
* Allow the application to register its own methods.
*/
void
libcheri_system_user_register_fn(libcheri_system_user_fn_t fn_ptr);
LLM: ??? it looks like every sandbox will have this
libcheri_system_vtable
re-initialized upon sandbox initialization insandbox_program_init()
; However, if this vtable is a global variable and shared as the same for all sandboxes, will this be a conflict between all the sandboxes that are using this vtable?
Declare as extern in libcheri_system.h
// file:
// lib/libcheri/libcheri_system.h
/*
* Vtable for cheri_system methods.
*/
extern vm_offset_t * __capability libcheri_system_vtable;
Defined and used in libcheri_sandbox.c:
// file:
// lib/libcheri/libcheri_sandbox.c
/*
* libcheri_system_vtable is defined here and not in libcheri_system.h to avoid
* running into https://github.com/CTSRD-CHERI/cheribsd/issues/180
*/
vm_offset_t * __capability libcheri_system_vtable;
...
int sandbox_program_init(void)
{
...
/* XXXBD: cheri_system needs to do this. */
libcheri_system_vtable = sandbox_make_vtable(NULL,
"_libcheri_system_object", main_provided_classes);
...
}
sandbox_make_vtable will take the main_provided_classes
parsed from the sandbox binary and create it
test_sandbox_cs_helloworld() -> invoke_cheri_system_helloworld() -> libcheri_system_helloworld();
// The `invoke_cheri_system_helloworld()` will invoke hello world in a sandbox:
// file: bin/cheritest/cheritest_libcheri.c
void
test_sandbox_cs_helloworld(const struct cheri_test *ctp __unused)
{
register_t v;
v = invoke_cheri_system_helloworld();
if (v < 0)
cheritest_failure_errx("Sandbox returned %jd", (intmax_t)v);
else
cheritest_success();
}
The following is the declaration of the call gate of
invoke_cheri_system_helloworld()
// file: libexec/cheritest-helper/cheritest-helper.h
struct cheri_object;
BEGIN_CAPABILITIES
//...
CHERITEST_CCALL int invoke_cheri_system_helloworld(void);
//...
END_CAPABILITIES
// file: libexec/cheritest-helper/cheritest-helper.c
extern struct cheri_object cheritest;
#ifdef CHERITEST_INTERNAL
#define CHERITEST_CCALL \
__attribute__((cheri_ccallee)) \
__attribute__((cheri_method_class(cheritest)))
#else
#define CHERITEST_CCALL \
__attribute__((cheri_ccall)) \
__attribute__((cheri_method_suffix("_cap"))) \
__attribute__((cheri_method_class(cheritest)))
#endif
int
invoke_cheri_system_helloworld(void)
{
return (libcheri_system_helloworld());
}
The assembly code for test_sandbox_cs_helloworld()
:
/* file: cheritest.s , commit: def7a422bf */
000000000003c8a8 test_sandbox_cs_helloworld:
3c8a8: 67 bd ff e0 daddiu $sp, $sp, -32
3c8ac: ff bf 00 18 sd $ra, 24($sp)
3c8b0: ff be 00 10 sd $fp, 16($sp)
3c8b4: ff bc 00 08 sd $gp, 8($sp)
3c8b8: 03 a0 f0 25 move $fp, $sp
3c8bc: 3c 01 00 11 lui $1, 17
3c8c0: 00 39 08 2d daddu $1, $1, $25
3c8c4: 64 3c f7 58 daddiu $gp, $1, -2216
3c8c8: df 81 89 20 ld $1, -30432($gp)
3c8cc: df 83 87 80 ld $3, -30848($gp)
3c8d0: dc 22 00 00 ld $2, 0($1)
3c8d4: d8 20 18 00 clc $c1, $3, 0($ddc)
3c8d8: 64 61 00 20 daddiu $1, $3, 32
3c8dc: d8 40 08 00 clc $c2, $1, 0($ddc)
3c8e0: df 99 87 88 ld $25, -30840($gp)
3c8e4: 48 03 02 bf cgetnull $c3
3c8e8: 48 04 02 bf cgetnull $c4
3c8ec: 48 05 02 bf cgetnull $c5
3c8f0: 48 06 02 bf cgetnull $c6
3c8f4: 48 07 02 bf cgetnull $c7
3c8f8: 48 08 02 bf cgetnull $c8
3c8fc: 48 09 02 bf cgetnull $c9
3c900: 48 0a 02 bf cgetnull $c10
3c904: 64 04 00 00 daddiu $4, $zero, 0
3c908: 64 05 00 00 daddiu $5, $zero, 0
3c90c: 64 06 00 00 daddiu $6, $zero, 0
3c910: 64 07 00 00 daddiu $7, $zero, 0
3c914: 64 08 00 00 daddiu $8, $zero, 0
3c918: 64 09 00 00 daddiu $9, $zero, 0
3c91c: 64 0a 00 00 daddiu $10, $zero, 0
3c920: 03 20 f8 09 jalr $25
3c924: 64 0b 00 00 daddiu $11, $zero, 0
3c928: 04 41 00 06 bgez $2, 28 <test_sandbox_cs_helloworld+0x9c>
3c92c: 00 00 00 00 nop
3c930: df 81 80 c8 ld $1, -32568($gp)
3c934: 00 02 28 00 sll $5, $2, 0
3c938: df 99 84 90 ld $25, -31600($gp)
3c93c: 03 20 f8 09 jalr $25
3c940: 64 24 3b ce daddiu $4, $1, 15310
3c944: df 99 84 88 ld $25, -31608($gp)
3c948: 03 20 f8 09 jalr $25
3c94c: 00 00 00 00 nop
Another disassembly from cheriabitest:
/* file: cheriabitest.s, commit: def7a422bf*/
0000000120087310 test_sandbox_cs_helloworld:
120087310: 4a 6b 5f 80 cincoffset $c11, $c11, -128
120087314: fb 0b 00 06 csc $c24, $zero, 96($c11)
120087318: fa 4b 00 04 csc $c18, $zero, 64($c11)
12008731c: fa 2b 00 02 csc $c17, $zero, 32($c11)
120087320: 48 18 58 11 cincoffset $c24, $c11, $zero
120087324: 3c 01 00 14 lui $1, 20
120087328: 64 21 e1 30 daddiu $1, $1, -7888
12008732c: 48 12 60 51 cincoffset $c18, $c12, $1
120087330: 74 32 08 60 clcbi $c1, 34304($c18)
120087334: 74 52 03 5a clcbi $c2, 13728($c18)
120087338: c8 41 00 03 cld $2, $zero, 0($c1)
12008733c: d8 22 00 00 clc $c1, $zero, 0($c2)
120087340: d8 42 00 02 clc $c2, $zero, 32($c2)
120087344: 75 92 03 5c clcbi $c12, 13760($c18)
120087348: 48 03 02 bf cgetnull $c3
12008734c: 48 04 02 bf cgetnull $c4
120087350: 48 05 02 bf cgetnull $c5
120087354: 48 06 02 bf cgetnull $c6
120087358: 48 07 02 bf cgetnull $c7
12008735c: 48 08 02 bf cgetnull $c8
120087360: 48 09 02 bf cgetnull $c9
120087364: 48 0a 02 bf cgetnull $c10
120087368: 64 04 00 00 daddiu $4, $zero, 0
12008736c: 64 05 00 00 daddiu $5, $zero, 0
120087370: 64 06 00 00 daddiu $6, $zero, 0
120087374: 64 07 00 00 daddiu $7, $zero, 0
120087378: 64 08 00 00 daddiu $8, $zero, 0
12008737c: 64 09 00 00 daddiu $9, $zero, 0
120087380: 64 0a 00 00 daddiu $10, $zero, 0
120087384: 48 11 63 3f cjalr $c12, $c17
120087388: 64 0b 00 00 daddiu $11, $zero, 0
12008738c: 04 41 00 09 bgez $2, 40 <test_sandbox_cs_helloworld+0xa4>
120087390: 00 00 00 00 nop
120087394: 00 02 08 00 sll $1, $2, 0
120087398: e8 2b 00 03 csd $1, $zero, 0($c11)
12008739c: 4a 81 58 08 csetbounds $c1, $c11, 8
1200873a0: 34 01 ff d7 ori $1, $zero, 65495
1200873a4: 74 72 08 54 clcbi $c3, 34112($c18)
1200873a8: 75 92 01 92 clcbi $c12, 6432($c18)
1200873ac: 48 11 63 3f cjalr $c12, $c17
1200873b0: 48 0d 08 4d candperm $c13, $c1, $1
1200873b4: 75 92 01 8e clcbi $c12, 6368($c18)
1200873b8: 48 11 63 3f cjalr $c12, $c17
1200873bc: 00 00 00 00 nop
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?