static int invoke_cap_fault(register_t op) { char buffer[N], ch; __capability char *cap; cap = cheri_ptrperm(buffer, sizeof(buffer), CHERI_PERM_LOAD); switch (op) { case CHERITEST_HELPER_OP_CP2_BOUND: ch = cap[N]; return (ch); case CHERITEST_HELPER_OP_CP2_PERM: cap[0] = 0; break; case CHERITEST_HELPER_OP_CP2_TAG: cap = cheri_zerocap(); ch = cap[0]; return (ch); case CHERITEST_HELPER_OP_CP2_SEAL: cap = cheri_sealcode(cap); ch = cap[0]; return (ch); } return (0); }
int call_cheri_system_puts(void) { __capability char *hello_world_str_c; hello_world_str_c = cheri_ptrperm(&hello_world_str, sizeof(hello_world_str), CHERI_PERM_LOAD); /* Nul-terminated. */ return (cheri_system_puts(hello_world_str_c)); }
int call_cheri_fd_write_c(struct cheri_object fd_object) { __capability char *hello_world_buf_c; size_t len_buf_c; len_buf_c = strlen(hello_world_str_nl); hello_world_buf_c = cheri_ptrperm(&hello_world_str_nl, len_buf_c, CHERI_PERM_LOAD); /* Just the text. */ return (cheri_fd_write_c(fd_object, hello_world_buf_c, len_buf_c).cfr_retval0); }
/* * 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); }
int test_sb(struct tf_test *thiz) { struct sb sb; struct sb_param sp; __capability struct sb_param *spc; int rc; __capability void *cap; thiz->t_pf("create sandbox\n"); rc = sb_init(thiz, &sb, SB_BIN, SB_HPSZ); if (rc != 0) return (rc); spc = cheri_ptr(&sp, sizeof(sp)); memset(&sp, 0, sizeof(sp)); rc = cheri_gc_new(CHERI_GC_METHOD_ALLOC_C | CHERI_GC_METHOD_STATUS_C, &sp.sp_gc); if (rc != 0) { thiz->t_pf("error: cheri_gc_new\n"); return (rc); } thiz->t_pf("sandbox codecap: %s\n", gc_cap_str(sb.sb_op->sbo_cheri_object_invoke.co_codecap)); thiz->t_pf("sandbox datacap: %s\n", gc_cap_str(sb.sb_op->sbo_cheri_object_invoke.co_datacap)); spc->sp_cap1 = cheri_ptrperm(&cap, sizeof(cap), CHERI_PERM_STORE_CAP); /* XXX: assume GC initialized. */ thiz->t_pf("invoke sandbox\n"); spc->sp_op = OP_INIT; rc = sb_invoke(thiz, &sb, spc); thiz->t_pf("return value from sandbox: %d\n", rc); /* In the sandbox, force p to the stack. */ thiz->t_pf("invoke sandbox\n"); spc->sp_op = OP_TRY_USE; printf("note: spc is %s\n", gc_cap_str(spc)); rc = sb_invoke(thiz, &sb, spc); thiz->t_pf("return value from sandbox: %d\n", rc); thiz->t_pf("cap: %s\n", gc_cap_str(cap)); /* Check stack. */ //struct gc_tags tg1 = gc_get_page_tags(gc_cheri_ptr(0x160c0c000ULL, 0x1000)); //printf("lo: 0x%llx hi: 0x%llx\n", tg1.tg_lo, tg1.tg_hi); /* Do a collection. */ //gc_extern_collect(); // Revoke a cap. rc = gc_revoke(cap); thiz->t_pf("revoke rc: %d\n", rc); gc_extern_collect(); thiz->t_pf("invoke sandbox\n"); spc->sp_op = OP_TRY_USE; printf("note: spc is %s\n", gc_cap_str(spc)); rc = sb_invoke(thiz, &sb, spc); thiz->t_pf("return value from sandbox: %d\n", rc); thiz->t_pf("cap: %s\n", gc_cap_str(cap)); return (0); }