void * memcpy(void *dst, const void *src, size_t len) { if (len == 0) return (dst); memcpy_c(cheri_ptr(dst, len), cheri_ptr((void *)src, len), len); return (dst); }
u_int juniper_mlppp_print(const struct pcap_pkthdr *h, packetbody_t p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_MLPPP; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; /* suppress Bundle-ID if frame was captured on a child-link * best indicator if the cookie looks like a proto */ if (eflag && EXTRACT_16BITS(cheri_ptr(&l2info.cookie, 2)) != PPP_OSI && EXTRACT_16BITS(cheri_ptr(&l2info.cookie, 2)) != (PPP_ADDRESS << 8 | PPP_CONTROL)) printf("Bundle-ID %u: ",l2info.bundle); p+=l2info.header_len; /* first try the LSQ protos */ switch(l2info.proto) { case JUNIPER_LSQ_L3_PROTO_IPV4: /* IP traffic going to the RE would not have a cookie * -> this must be incoming IS-IS over PPP */ if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR)) ppp_print(p, l2info.length); else ip_print(gndo, p, l2info.length); return l2info.header_len; #ifdef INET6 case JUNIPER_LSQ_L3_PROTO_IPV6: ip6_print(gndo, p,l2info.length); return l2info.header_len; #endif case JUNIPER_LSQ_L3_PROTO_MPLS: mpls_print(p,l2info.length); return l2info.header_len; case JUNIPER_LSQ_L3_PROTO_ISO: isoclns_print(p,l2info.length,l2info.caplen); return l2info.header_len; default: break; } /* zero length cookie ? */ switch (EXTRACT_16BITS(cheri_ptr(&l2info.cookie, 2))) { case PPP_OSI: ppp_print(PACKET_SUBTRACT(p,2),l2info.length+2); break; case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */ default: ppp_print(p,l2info.length); break; } return l2info.header_len; }
u_int juniper_mlfr_print(const struct pcap_pkthdr *h, packetbody_t p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_MLFR; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* suppress Bundle-ID if frame was captured on a child-link */ if (eflag && EXTRACT_32BITS(cheri_ptr(l2info.cookie, 4)) != 1) printf("Bundle-ID %u, ",l2info.bundle); switch (l2info.proto) { case (LLC_UI): case (LLC_UI<<8): isoclns_print(p, l2info.length, l2info.caplen); break; case (LLC_UI<<8 | NLPID_Q933): case (LLC_UI<<8 | NLPID_IP): case (LLC_UI<<8 | NLPID_IP6): /* pass IP{4,6} to the OSI layer for proper link-layer printing */ isoclns_print(PACKET_SUBTRACT(p, 1), l2info.length+1, l2info.caplen+1); break; default: printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length); } return l2info.header_len; }
u_int juniper_mfr_print(const struct pcap_pkthdr *h, packetbody_t p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_MFR; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* child-link ? */ if (l2info.cookie_len == 0) { mfr_print(p,l2info.length); return l2info.header_len; } /* first try the LSQ protos */ if (l2info.cookie_len == AS_PIC_COOKIE_LEN) { switch(l2info.proto) { case JUNIPER_LSQ_L3_PROTO_IPV4: ip_print(gndo, p, l2info.length); return l2info.header_len; #ifdef INET6 case JUNIPER_LSQ_L3_PROTO_IPV6: ip6_print(gndo, p,l2info.length); return l2info.header_len; #endif case JUNIPER_LSQ_L3_PROTO_MPLS: mpls_print(p,l2info.length); return l2info.header_len; case JUNIPER_LSQ_L3_PROTO_ISO: isoclns_print(p,l2info.length,l2info.caplen); return l2info.header_len; default: break; } return l2info.header_len; } /* suppress Bundle-ID if frame was captured on a child-link */ if (eflag && EXTRACT_32BITS(cheri_ptr(l2info.cookie, 4)) != 1) printf("Bundle-ID %u, ",l2info.bundle); switch (l2info.proto) { case (LLCSAP_ISONS<<8 | LLCSAP_ISONS): isoclns_print(p+1, l2info.length-1, l2info.caplen-1); break; case (LLC_UI<<8 | NLPID_Q933): case (LLC_UI<<8 | NLPID_IP): case (LLC_UI<<8 | NLPID_IP6): /* pass IP{4,6} to the OSI layer for proper link-layer printing */ isoclns_print(PACKET_SUBTRACT(p, 1), l2info.length+1, l2info.caplen+1); break; default: printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length); } return l2info.header_len; }
/* * Print the TR MAC header */ static inline void token_hdr_print(__capability const struct token_header *trp, register u_int length, u_char *fsrc, u_char *fdst) { const char *srcname, *dstname; srcname = etheraddr_string(cheri_ptr(fsrc, 6)); dstname = etheraddr_string(cheri_ptr(fdst, 6)); if (vflag) (void) printf("%02x %02x %s %s %d: ", trp->token_ac, trp->token_fc, srcname, dstname, length); else printf("%s %s %d: ", srcname, dstname, length); }
__capability void * memcpy_c_tocap(__capability void *dst, const void *src, size_t len) { #ifdef __CHERI_SANDBOX__ return (memcpy_c(dst, src, len)); #else return (memcpy_c(dst, cheri_ptr((void *)src, len), len)); #endif }
void * memcpy_c_fromcap(void *dst, __capability const void *src, size_t len) { #ifdef __CHERI_SANDBOX__ return (memcpy_c(dst, src, len)); #else memcpy_c(cheri_ptr(dst, len), src, len); return (dst); #endif }
_gc_cap void * gc_vm_get_stack(_gc_cap struct gc_vm_tbl *vt) { _gc_cap void *p; _gc_cap struct gc_vm_ent *ve; /* Heuristic; just return last entry. */ ve = &vt->vt_ent[vt->vt_nent - 1]; p = cheri_ptr((void *)ve->ve_start, ve->ve_end - ve->ve_start); return (p); }
static int invoke_fd_write_c(struct cheri_object fd_object) { struct cheri_fd_ret ret; const char *buf = "fd write test\n"; __capability const void *buf_c; buf_c = cheri_ptr(buf, strlen(buf)); ret = cheri_fd_write_c(fd_object, buf_c); printf("cheri_fd_write_c returned (%ld, %ld)\n", ret.cfr_retval0, ret.cfr_retval1); return (0); }
static int invoke_fd_read_c(struct cheri_object fd_object) { struct cheri_fd_ret ret; char buf[10]; __capability void *buf_c; buf_c = cheri_ptr(buf, sizeof(buf)); ret = cheri_fd_read_c(fd_object, buf_c); printf("cheri_fd_read_c returned (%ld, %ld)\n", ret.cfr_retval0, ret.cfr_retval1); return (0); }
static int invoke_fd_fstat_c(struct cheri_object fd_object) { struct cheri_fd_ret ret; struct stat sb; __capability void *sb_c; sb_c = cheri_ptr(&sb, sizeof(sb)); ret = cheri_fd_fstat_c(fd_object, sb_c); printf("cheri_fd_fstat_c returned (%ld, %ld)\n", ret.cfr_retval0, ret.cfr_retval1); return (0); }
u_int juniper_atm2_print(const struct pcap_pkthdr *h, packetbody_t p) { u_int16_t extracted_ethertype; struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_ATM2; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */ oam_print(p,l2info.length,ATM_OAM_NOHEC); return l2info.header_len; } if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL, &extracted_ethertype) != 0) return l2info.header_len; } if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */ (EXTRACT_32BITS(cheri_ptr(l2info.cookie, 4)) & ATM2_GAP_COUNT_MASK)) { ether_print(gndo, p, l2info.length, l2info.caplen, NULL, NULL); return l2info.header_len; } if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1); /* FIXME check if frame was recognized */ return l2info.header_len; } if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */ return l2info.header_len; if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */ return l2info.header_len; return l2info.header_len; }
static int juniper_parse_header (packetbody_t p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) { struct juniper_cookie_table_t *lp = juniper_cookie_table; u_int idx, jnx_ext_len, jnx_header_len = 0; u_int8_t tlv_type,tlv_len; u_int32_t control_word; int tlv_value; packetbody_t tptr; l2info->header_len = 0; l2info->cookie_len = 0; l2info->proto = 0; l2info->length = h->len; l2info->caplen = h->caplen; PACKET_HAS_SPACE_OR_TRUNC(p,4); l2info->flags = p[3]; l2info->direction = p[3]&JUNIPER_BPF_PKT_IN; if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */ printf("no magic-number found!"); return 0; } if (eflag) /* print direction */ printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction)); /* magic number + flags */ jnx_header_len = 4; if (vflag>1) printf("\n\tJuniper PCAP Flags [%s]", bittok2str(jnx_flag_values, "none", l2info->flags)); /* extensions present ? - calculate how much bytes to skip */ if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) { tptr = p+jnx_header_len; /* ok to read extension length ? */ PACKET_HAS_SPACE_OR_TRUNC(tptr, 2); jnx_ext_len = EXTRACT_16BITS(tptr); jnx_header_len += 2; tptr +=2; /* nail up the total length - * just in case something goes wrong * with TLV parsing */ jnx_header_len += jnx_ext_len; if (vflag>1) printf(", PCAP Extension(s) total length %u", jnx_ext_len); PACKET_HAS_SPACE_OR_TRUNC(tptr, jnx_ext_len); while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) { tlv_type = *(tptr++); tlv_len = *(tptr++); tlv_value = 0; /* sanity check */ if (tlv_type == 0 || tlv_len == 0) break; if (vflag>1) printf("\n\t %s Extension TLV #%u, length %u, value ", tok2str(jnx_ext_tlv_values,"Unknown",tlv_type), tlv_type, tlv_len); tlv_value = juniper_read_tlv_value(tptr, tlv_type, tlv_len); switch (tlv_type) { case JUNIPER_EXT_TLV_IFD_NAME: /* FIXME */ break; case JUNIPER_EXT_TLV_IFD_MEDIATYPE: case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE: if (tlv_value != -1) { if (vflag>1) printf("%s (%u)", tok2str(juniper_ifmt_values, "Unknown", tlv_value), tlv_value); } break; case JUNIPER_EXT_TLV_IFL_ENCAPS: case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS: if (tlv_value != -1) { if (vflag>1) printf("%s (%u)", tok2str(juniper_ifle_values, "Unknown", tlv_value), tlv_value); } break; case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */ case JUNIPER_EXT_TLV_IFL_UNIT: case JUNIPER_EXT_TLV_IFD_IDX: default: if (tlv_value != -1) { if (vflag>1) printf("%u",tlv_value); } break; } tptr+=tlv_len; jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD; } if (vflag>1) printf("\n\t-----original packet-----\n\t"); } if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) { if (eflag) printf("no-L2-hdr, "); /* there is no link-layer present - * perform the v4/v6 heuristics * to figure out what it is */ PACKET_HAS_SPACE_OR_TRUNC(p, (jnx_header_len+4) + 1); if(ip_heuristic_guess(p+jnx_header_len+4,l2info->length-(jnx_header_len+4)) == 0) printf("no IP-hdr found!"); l2info->header_len=jnx_header_len+4; return 0; /* stop parsing the output further */ } l2info->header_len = jnx_header_len; p+=l2info->header_len; l2info->length -= l2info->header_len; l2info->caplen -= l2info->header_len; /* search through the cookie table and copy values matching for our PIC type */ while (lp->s != NULL) { if (lp->pictype == l2info->pictype) { l2info->cookie_len += lp->cookie_len; switch (p[0]) { case LS_COOKIE_ID: l2info->cookie_type = LS_COOKIE_ID; l2info->cookie_len += 2; break; case AS_COOKIE_ID: l2info->cookie_type = AS_COOKIE_ID; l2info->cookie_len = 8; break; default: l2info->bundle = l2info->cookie[0]; break; } #ifdef DLT_JUNIPER_MFR /* MFR child links don't carry cookies */ if (l2info->pictype == DLT_JUNIPER_MFR && (p[0] & MFR_BE_MASK) == MFR_BE_MASK) { l2info->cookie_len = 0; } #endif l2info->header_len += l2info->cookie_len; l2info->length -= l2info->cookie_len; l2info->caplen -= l2info->cookie_len; if (eflag) printf("%s-PIC, cookie-len %u", lp->s, l2info->cookie_len); if (l2info->cookie_len > 0) { PACKET_HAS_SPACE_OR_TRUNC(p,l2info->cookie_len); if (eflag) printf(", cookie 0x"); for (idx = 0; idx < l2info->cookie_len; idx++) { l2info->cookie[idx] = p[idx]; /* copy cookie data */ if (eflag) printf("%02x",p[idx]); } } if (eflag) printf(": "); /* print demarc b/w L2/L3*/ l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len); break; } ++lp; } p+=l2info->cookie_len; /* DLT_ specific parsing */ switch(l2info->pictype) { #ifdef DLT_JUNIPER_MLPPP case DLT_JUNIPER_MLPPP: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(cheri_ptr(&l2info->cookie[6], 2))>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_MLFR case DLT_JUNIPER_MLFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(cheri_ptr(&l2info->cookie[6], 2))>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; } break; #endif #ifdef DLT_JUNIPER_MFR case DLT_JUNIPER_MFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(cheri_ptr(&l2info->cookie[6], 2))>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_ATM2 case DLT_JUNIPER_ATM2: PACKET_HAS_SPACE_OR_TRUNC(p,4); /* ATM cell relay control word present ? */ if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) { control_word = EXTRACT_32BITS(p); /* some control word heuristics */ switch(control_word) { case 0: /* zero control word */ case 0x08000000: /* < JUNOS 7.4 control-word */ case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/ l2info->header_len += 4; break; default: break; } if (eflag) printf("control-word 0x%08x ", control_word); } break; #endif #ifdef DLT_JUNIPER_GGSN case DLT_JUNIPER_GGSN: break; #endif #ifdef DLT_JUNIPER_ATM1 case DLT_JUNIPER_ATM1: break; #endif #ifdef DLT_JUNIPER_PPP case DLT_JUNIPER_PPP: break; #endif #ifdef DLT_JUNIPER_CHDLC case DLT_JUNIPER_CHDLC: break; #endif #ifdef DLT_JUNIPER_ETHER case DLT_JUNIPER_ETHER: break; #endif #ifdef DLT_JUNIPER_FRELAY case DLT_JUNIPER_FRELAY: break; #endif default: printf("Unknown Juniper DLT_ type %u: ", l2info->pictype); break; } if (eflag > 1) printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto); return 1; /* everything went ok so far. continue parsing */ trunc: printf("[|juniper_hdr], length %u",h->len); 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); }
u_int token_print(packetbody_t p, u_int length, u_int caplen) { __capability const struct token_header *trp; u_short extracted_ethertype; struct ether_header ehdr; u_int route_len = 0, hdr_len = TOKEN_HDRLEN; int seg; trp = (__capability const struct token_header *)p; if (caplen < TOKEN_HDRLEN) { printf("[|token-ring]"); return hdr_len; } /* * Get the TR addresses into a canonical form */ extract_token_addrs(trp, (char*)ESRC(&ehdr), (char*)EDST(&ehdr)); /* Adjust for source routing information in the MAC header */ if (IS_SOURCE_ROUTED(trp)) { /* Clear source-routed bit */ *ESRC(&ehdr) &= 0x7f; if (eflag) token_hdr_print(trp, length, ESRC(&ehdr), EDST(&ehdr)); if (caplen < TOKEN_HDRLEN + 2) { printf("[|token-ring]"); return hdr_len; } route_len = RIF_LENGTH(trp); hdr_len += route_len; if (caplen < hdr_len) { printf("[|token-ring]"); return hdr_len; } if (vflag) { printf("%s ", broadcast_indicator[BROADCAST(trp)]); printf("%s", direction[DIRECTION(trp)]); for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) printf(" [%d:%d]", RING_NUMBER(trp, seg), BRIDGE_NUMBER(trp, seg)); } else { printf("rt = %x", EXTRACT_16BITS(&trp->token_rcf)); for (seg = 0; seg < SEGMENT_COUNT(trp); seg++) printf(":%x", EXTRACT_16BITS(&trp->token_rseg[seg])); } printf(" (%s) ", largest_frame[LARGEST_FRAME(trp)]); } else { if (eflag) token_hdr_print(trp, length, ESRC(&ehdr), EDST(&ehdr)); } /* Skip over token ring MAC header and routing information */ length -= hdr_len; p += hdr_len; caplen -= hdr_len; /* Frame Control field determines interpretation of packet */ if (FRAME_TYPE(trp) == TOKEN_FC_LLC) { /* Try to print the LLC-layer header & higher layers */ if (llc_print(p, length, caplen, cheri_ptr(ESRC(&ehdr), 6), cheri_ptr(EDST(&ehdr), 6), &extracted_ethertype) == 0) { /* ether_type not known, print raw packet */ if (!eflag) token_hdr_print(trp, length + TOKEN_HDRLEN + route_len, ESRC(&ehdr), EDST(&ehdr)); if (extracted_ethertype) { printf("(LLC %s) ", etherproto_string(htons(extracted_ethertype))); } if (!suppress_default_print) default_print(p, caplen); } } else { /* Some kinds of TR packet we cannot handle intelligently */ /* XXX - dissect MAC packets if frame type is 0 */ if (!eflag) token_hdr_print(trp, length + TOKEN_HDRLEN + route_len, ESRC(&ehdr), EDST(&ehdr)); if (!suppress_default_print) default_print(p, caplen); } return (hdr_len); }
int sandbox_object_load(struct sandbox_class *sbcp, struct sandbox_object *sbop) { __capability void *basecap, *sbcap; struct sandbox_metadata *sbm; size_t length; int saved_errno; uint8_t *base; /* * Perform an initial reservation of space for the sandbox, but using * anonymous memory that is neither readable nor writable. This * ensures there is space for all the various segments we will be * installing later. * * The rough sandbox memory map is as follows: * * K + 0x1000 [stack] * K [guard page] * J + 0x1000 [heap] * J [guard page] * 0x8000 [memory mapped binary] (SANDBOX_ENTRY) * 0x2000 [guard page] * 0x1000 [read-only sandbox metadata page] * 0x0000 [guard page] * * Address constants in sandbox.h must be synchronised with the layout * implemented here. Location and contents of sandbox metadata is * part of the ABI. */ length = sbcp->sbc_sandboxlen; base = sbop->sbo_mem = mmap(NULL, length, 0, MAP_ANON, -1, 0); if (sbop->sbo_mem == MAP_FAILED) { saved_errno = errno; warn("%s: mmap region", __func__); goto error; } /* * Skip guard page(s) to the base of the metadata structure. */ base += SANDBOX_METADATA_BASE; length -= SANDBOX_METADATA_BASE; /* * Map metadata structure -- but can't fill it out until we have * calculated all the other addresses involved. */ if ((sbm = mmap(base, METADATA_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_FIXED, -1, 0)) == MAP_FAILED) { saved_errno = errno; warn("%s: mmap metadata", __func__); goto error; } /* * Skip forward to the mapping location for the binary -- in case we * add more metadata in the future. Assert that we didn't bump into * the sandbox entry address. This address is hard to change as it is * the address used in static linking for sandboxed code. */ assert((register_t)base - (register_t)sbop->sbo_mem < SANDBOX_ENTRY); base = (void *)((register_t)sbop->sbo_mem + SANDBOX_ENTRY); length = sbcp->sbc_sandboxlen - SANDBOX_ENTRY; /* * Map program binary. */ if (mmap(base, sbcp->sbc_stat.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, sbcp->sbc_fd, 0) == MAP_FAILED) { saved_errno = errno; warn("%s: mmap %s", __func__, sbcp->sbc_path); goto error; } base += roundup2(sbcp->sbc_stat.st_size, PAGE_SIZE); length += roundup2(sbcp->sbc_stat.st_size, PAGE_SIZE); /* * Skip guard page. */ base += GUARD_PAGE_SIZE; length -= GUARD_PAGE_SIZE; /* * Heap. */ sbop->sbo_heapbase = (register_t)base - (register_t)sbop->sbo_mem; sbop->sbo_heaplen = length - (GUARD_PAGE_SIZE + STACK_SIZE); if (mmap(base, sbop->sbo_heaplen, PROT_READ | PROT_WRITE, MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED) { saved_errno = errno; warn("%s: mmap heap", __func__); goto error; } memset(base, 0, sbop->sbo_heaplen); base += sbop->sbo_heaplen; length -= sbop->sbo_heaplen; /* * Skip guard page. */ base += GUARD_PAGE_SIZE; length -= GUARD_PAGE_SIZE; /* * Stack. */ if (mmap(base, length, PROT_READ | PROT_WRITE, MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED) { saved_errno = errno; warn("%s: mmap stack", __func__); goto error; } memset(base, 0, length); base += STACK_SIZE; length -= STACK_SIZE; /* * There should not be too much, nor too little space remaining. 0 * is our Goldilocks number. */ assert(length == 0); /* * Now that addresses are known, write out metadata for in-sandbox * use; then mprotect() so that it can't be modified by the sandbox. */ sbm->sbm_heapbase = sbop->sbo_heapbase; sbm->sbm_heaplen = sbop->sbo_heaplen; if (mprotect(base, METADATA_SIZE, PROT_READ) < 0) { saved_errno = errno; warn("%s: mprotect metadata", __func__); goto error; } if (sbcp->sbc_sandbox_class_statp != NULL) { (void)sandbox_stat_object_register( &sbop->sbo_sandbox_object_statp, sbcp->sbc_sandbox_class_statp, SANDBOX_OBJECT_TYPE_POINTER, (uintptr_t)sbop->sbo_mem); SANDBOX_CLASS_ALLOC(sbcp->sbc_sandbox_class_statp); } /* * Construct a generic capability that describes the combined * data/code segment that we will seal. */ basecap = cheri_ptrtype(sbop->sbo_mem, sbcp->sbc_sandboxlen, SANDBOX_ENTRY); /* Construct sealed code capability. */ sbcap = cheri_andperm(basecap, CHERI_PERM_EXECUTE | CHERI_PERM_LOAD | CHERI_PERM_SEAL); sbop->sbo_cheri_object.co_codecap = cheri_sealcode(sbcap); /* Construct sealed data capability. */ sbcap = cheri_andperm(basecap, CHERI_PERM_LOAD | CHERI_PERM_STORE | CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE_CAP | CHERI_PERM_STORE_EPHEM_CAP); sbop->sbo_cheri_object.co_datacap = cheri_sealdata(sbcap, basecap); /* * Construct an object capability for the system class instance that * will be passed into the sandbox. Its code capability is just our * $c0; the data capability is to the sandbox structure itself, which * allows the system class to identify which sandbox a request is * being issued from. * * Note that $c0 in the 'sandbox' will be set from $pcc, so leave a * full set of write/etc permissions on the code capability. */ basecap = cheri_settype(cheri_getdefault(), (register_t)CHERI_CLASS_ENTRY(libcheri_system)); sbop->sbo_cheri_system_object.co_codecap = cheri_sealcode(basecap); sbcap = cheri_ptr(sbop, sizeof(*sbop)); sbcap = cheri_andperm(sbcap, CHERI_PERM_LOAD | CHERI_PERM_STORE | CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE_CAP | CHERI_PERM_STORE_EPHEM_CAP); sbop->sbo_cheri_system_object.co_datacap = cheri_sealdata(sbcap, basecap); return (0); error: if (sbop->sbo_mem != NULL) munmap(sbop->sbo_mem, sbcp->sbc_sandboxlen); errno = saved_errno; return (-1); }
#include <sysexits.h> #include <unistd.h> #include "cheritest.h" /* * First batch of tests exercises CHERI faults outside of sandboxes. */ #define ARRAY_LEN 2 static char array[ARRAY_LEN]; static char sink; void test_fault_bounds(const struct cheri_test *ctp __unused) { __capability char *arrayp = cheri_ptr(array, sizeof(array)); int i; for (i = 0; i < ARRAY_LEN; i++) arrayp[i] = 0; arrayp[i] = 0; } void test_fault_perm_load(const struct cheri_test *ctp __unused) { __capability char *arrayp = cheri_ptrperm(array, sizeof(array), 0); sink = arrayp[0]; }