/* * Allocate a new cheri_fd object for an already-open file descriptor. */ int cheri_fd_new(int fd, struct cheri_object *cop) { __capability void *codecap, *datacap; struct cheri_fd *cfp; cfp = calloc(1, sizeof(*cfp)); if (cfp == NULL) { errno = ENOMEM; return (-1); } CHERI_SYSTEM_OBJECT_INIT(cfp, cheri_fd_vtable); cfp->cf_fd = fd; /* * Construct a sealed code capability for the class. This is just the * ambient $pcc with the offset set to the entry address. * * XXXRW: For now, when invoked, we install $pcc into $c0, so this * needs a full set of permissions rather than just LOAD/EXECUTE. In * the future, we will want to preserve a copy of cheri_getdefault() * in the struct cheri_fd to be reinstalled by the entry code. * * XXXRW: In the future, use cheri_codeptr() here? */ codecap = cheri_setoffset(cheri_getpcc(), (register_t)CHERI_CLASS_ENTRY(cheri_fd)); cop->co_codecap = cheri_seal(codecap, cheri_fd_type); /* * Construct a sealed data capability for the class. This describes * the 'struct cheri_fd' for the specific file descriptor. The $c0 * to reinstall later is the first field in the structure. * * XXXRW: Should we also do an explicit cheri_setoffset()? */ datacap = cheri_ptrperm(cfp, sizeof(*cfp), CHERI_PERM_GLOBAL | CHERI_PERM_LOAD | CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE | CHERI_PERM_STORE_CAP); cop->co_datacap = cheri_seal(datacap, cheri_fd_type); return (0); }
/* * XXXRW: I'm not really happy with this approach of limiting access to system * resources via flags passed here. We should use a more general security * model based on capability permissions. However, this does allow us to more * generally get up and running. * XXXBD: I broke the flags when switching system functions to cheri_ccallee. */ int sandbox_object_new_flags(struct sandbox_class *sbcp, size_t heaplen, uint flags, struct sandbox_object **sbopp) { struct sandbox_object *sbop; int error; if (sandbox_program_sanity_check() < 0) errx(1, "%s: sandbox_program_sanity_check", __func__); sbop = calloc(1, sizeof(*sbop)); if (sbop == NULL) return (-1); CHERI_SYSTEM_OBJECT_INIT(sbop, cheri_system_vtable); sbop->sbo_sandbox_classp = sbcp; sbop->sbo_flags = flags; sbop->sbo_heaplen = heaplen; /* * XXXRW: In due course, stack size should be a parameter rather than * a constant. */ sbop->sbo_stacklen = SANDBOX_STACK_SIZE; sbop->sbo_stackmem = mmap(0, sbop->sbo_stacklen, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); if (sbop->sbo_stackmem == NULL) { free(sbop); return (-1); } /* * Configure the object's stack before loading so that the stack * capability can be installed into sandbox metadata. Note that the * capability is local (can't be shared) and can store local pointers * (i.e., further stack-derived capabilities such as return * addresses). */ sbop->sbo_stackcap = cheri_local(cheri_ptrperm(sbop->sbo_stackmem, sbop->sbo_stacklen, CHERI_PERM_LOAD | CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE | CHERI_PERM_STORE_CAP | CHERI_PERM_STORE_LOCAL_CAP)); /* * Set up the sandbox's code/data segments, sealed capabilities. */ error = sandbox_object_load(sbcp, sbop); if (error) { (void)munmap(sbop->sbo_stackmem, sbop->sbo_stacklen); free(sbop); return (-1); } /* * Invoke object instance's constructors. Note that, given the tight * binding of class and object in the sandbox library currently, this * will need to change in the future. We also need to think more * carefully about the mechanism here. */ if (cheri_invoke(sbop->sbo_cheri_object_rtld, SANDBOX_RUNTIME_CONSTRUCTORS, 0, 0, 0, 0, 0, 0, 0, 0, cheri_zerocap(), cheri_zerocap(), cheri_zerocap(), cheri_zerocap(), cheri_zerocap(), cheri_zerocap(), cheri_zerocap(), cheri_zerocap()) != 0) { sandbox_object_unload(sbop); (void)munmap(sbop->sbo_stackmem, sbop->sbo_stacklen); return (-1); } /* * Now that constructors have completed, return object. */ *sbopp = sbop; return (0); }