sandbox_init()
in libcheri_sandbox.c;
Jobs include:
sandbox_parse_ccall_methods
: parse elf binary file (CHERI_CALLEE, and CHERI_CALLER sections) get a list of sandbox_provided_classes
(class, methods, offset), and its required methods (name, class, offset).sandbox_update_main_required_method_variables
, use the returned required method list from last step, updating the data structure in the sandbox (initialize the vtable offset);create libcheri_system_vtable
, libcheri_fd_vtable
// file:
// lib/libcheri/libcheri_sandbox.c
sandbox_init(void) -> sandbox_program_init(void)
// file:
// lib/libcheri/libcheri_sandbox.c
/* XXXBD: should be done in sandbox_init(), but need access to argv[0]. */
int
sandbox_program_init(void)
{
...
/* XXXBD: do this with RTLD or hypothentical getexecfd(). */
// Lele: kern.proc.pathname.(-1): current processes text file
if ((sysctl(mib, 4, buf, &cb, NULL, 0) != -1) && cb > 0) {
if ((fd = open(buf, O_RDONLY)) == -1)
warn("%s: open %s (from kern.proc.pathname.(-1))",
...
if (sandbox_parse_ccall_methods(fd, &main_provided_classes,
&main_required_methods) == -1) {
...
return (-1);
}
if (sandbox_update_main_required_method_variables() == -1) {
...
return (-1);
}
/* XXXBD: cheri_system needs to do this. */
libcheri_system_vtable = sandbox_make_vtable(NULL,
"_libcheri_system_object", main_provided_classes);
libcheri_fd_vtable = sandbox_make_vtable(NULL, "libcheri_fd",
main_provided_classes);
close(fd);
return (0);
}
In lib/libcheri/libcheri_sandbox.c:
sandbox_class_new(...)
, loading a sandbox binary from a given file. Resolve the
methods.
sandbox_object_new(struct sandbox_class *sbcp, size_t heaplen, struct sandbox_object **sbopp)
,
sandbox_object_new_system_object(void * __capability private_data, void * __capability invoke_pcc, vm_offset_t * __capability vtable, struct sandbox_object **sbopp)
,
File: bin/cheritest/cheritest_libcheri.c
// file
// bin/cheritest/cheritest_libcheri.c
int
cheritest_libcheri_setup(void)
{
/*
* Prepare CHERI objects representing stdin, stdout, and /dev/zero.
*/
if (libcheri_fd_new(STDIN_FILENO, &sbop_stdin) < 0)
err(EX_OSFILE, "libcheri_fd_new: stdin");
if (libcheri_fd_new(STDOUT_FILENO, &sbop_stdout) < 0)
err(EX_OSFILE, "clibheri_fd_new: stdout");
zero_fd = open("/dev/zero", O_RDWR);
if (zero_fd < 0)
err(EX_OSFILE, "open: /dev/zero");
if (libcheri_fd_new(zero_fd, &sbop_zero) < 0)
err(EX_OSFILE, "libcheri_fd_new: /dev/zero");
if (sandbox_class_new("/usr/libexec/cheritest-helper",
4*1024*1024, &cheritest_classp) < 0)
err(EX_OSERR, "sandbox_class_new: cheritest-helper");
if (sandbox_object_new(cheritest_classp, 2*1024*1024, &cheritest_objectp) < 0)
err(EX_OSERR, "sandbox_object_new: cheritest-helper");
cheritest = sandbox_object_getobject(cheritest_objectp);
cheritest2 = sandbox_object_getobject(cheritest_objectp);
libcheri_system_user_register_fn(&cheritest_libcheri_userfn_handler);
return (0);
}
Sandbox Class vs Object Class: ‘sandbox class’ is an instance of code that may be sandboxed and invoked, along with statistics/monitoring information, etc. (see lib/libcheri/libcheri_sandbox_internal.h) Object: ‘sandbox object’, or sandbox instance, is an in-flight combination of code and data. Currently, due the compiler limitations, we must conflate the ‘code’, ‘heap’, and ‘stack’, but eventually would like to allow one VM mapping of code to serve many object instances. This would also ease supporting multithreaded objects.
sandbox_provided_classes No two binaries can provide the same class as vtable offsets would be inconsistant. /* * List of classes provided by a sandbox binary. Each binary can * support one or more classes. No two binaries can provide the same * class as vtable offsets would be inconsistant. */ struct sandbox_provided_classes { struct sandbox_provided_methods **spcs_classes; /* Class pointers */ size_t spcs_nclasses; /* Number of methods */ size_t spcs_maxclasses; /* Array size */ size_t spcs_nmethods; /* Total methods */ vm_offset_t spcs_base; /* Base of vtable */ }; sandbox_required_method
// file: lib/libcheri/libcheri_sandbox_loader.c sandbox class load int sandbox_class_load(struct sandbox_class *sbcp) This will set up the code capability for a new sandbox class; (CHERI todo) set up the code and data capabilities differently. Steps includes: parse the provided classes, required methods from the ELF binary. set bounds and mask permissions on code capabilities. set offset of rtld, invoke vectors. sandbox object load int sandbox_object_load(struct sandbox_class *sbcp, struct sandbox_object *sbop)
If you could revise
the fundmental principles of
computer system design
to improve security...
... what would you change?