libcheri Sandbox

Initialization of system-class sandbox

see libcheri system sandbox

Initialization of user defined sandbox

sandbox_init() in libcheri_sandbox.c;

Jobs include:

  • get current process text file and open it;
  • 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);
    }

create new instance of a class/object

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),

Example 1: cheritest-helper

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);
}
  • Class Object
  • 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 Methods
  • 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

  • Sandbox Loader
  • // 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)

Created Sep 3, 2019 // Last Updated Sep 9, 2019

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

... what would you change?