From owner-p4-projects@FreeBSD.ORG Tue Nov 13 08:09:41 2012 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 28A60F72; Tue, 13 Nov 2012 08:09:41 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id DE4B1F6F for ; Tue, 13 Nov 2012 08:09:40 +0000 (UTC) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id C234E8FC08 for ; Tue, 13 Nov 2012 08:09:40 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.5/8.14.5) with ESMTP id qAD89eSA010671 for ; Tue, 13 Nov 2012 08:09:40 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.5/8.14.5/Submit) id qAD89e4e010668 for perforce@freebsd.org; Tue, 13 Nov 2012 08:09:40 GMT (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Date: Tue, 13 Nov 2012 08:09:40 GMT Message-Id: <201211130809.qAD89e4e010668@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson Subject: PERFORCE change 219766 for review To: Perforce Change Reviews Precedence: bulk X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.14 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 13 Nov 2012 08:09:41 -0000 http://p4web.freebsd.org/@@219766?ac=10 Change 219766 by rwatson@rwatson_zenith_cl_cam_ac_uk on 2012/11/13 08:09:18 Various enhancements to sandbox invocation calling conventions and related parts: - $c1-$c7 allow seven capabilities to be passed into the sandbox during invoke. - $c26 (IDC) is now used for the combined sandbox code/data segment required for MIPS compatibility mode. - Lay out the segment more maturely, using guard pages between explicit heap and stack sub-segments. - Pass information on heap layout into the sandbox, and populate global variables for use by in-sandbox malloc. This is done via a4 and a5. Affected files ... .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/mips64/sandboxasm.S#2 edit .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/sandbox.c#3 edit .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/sandbox.h#2 edit .. //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/malloc.c#2 edit .. //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/mips64/chsbrt.S#3 edit Differences ... ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/mips64/sandboxasm.S#2 (text+ko) ==== @@ -38,9 +38,9 @@ # for a CJALR into a sandbox. Eventually, this should be a CCALL. # # Temporary ABI conventions: -# $c1-$c2 will be filled with capability arguments -# $c3 is the segment of the invoked capability -# $a0-$a3 will be filled with general-purpose arguments +# $c1-$c7 will be filled with capability arguments +# $c26 is the segment of the invoked capability +# $a0-$a5 will be filled with general-purpose arguments # .text @@ -49,13 +49,6 @@ _chsbrt_invoke: # - # Install callee IDC, which will become callee $c0. - # - # XXXRW: This will be done by CCALL. - # - cmove $c26, $c3 - - # # XXXRW: When CCALL, save caller $c0 here. # @@ -92,7 +85,7 @@ # Enter sandbox, entering at 0x1000. # dli $t0, 0x1000 - cjalr $t0($c3) + cjalr $t0($c26) nop # XXXRW: Branch-delay slot? # ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/sandbox.c#3 (text+ko) ==== @@ -47,17 +47,23 @@ #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ +#define GUARD_PAGE_SIZE 0x1000 +#define PAGE_SIZE 0x1000 +#define STACK_SIZE (32*PAGE_SIZE) + /* * Library routine for setting up a sandbox. */ register_t _chsbrt_invoke(register_t, register_t, register_t, - register_t); + register_t, register_t, register_t); struct sandbox { char *sb_path; void *sb_mem; register_t sb_sandboxlen; + register_t sb_heapbase; + register_t sb_heaplen; struct chericap sb_segment; struct stat sb_stat; }; @@ -67,6 +73,8 @@ { struct sandbox *sb; int fd, saved_errno; + size_t length; + uint8_t *base; register_t v; fd = open(path, O_RDONLY); @@ -104,36 +112,94 @@ } /* - * Reserve space for a 1MB sandbox. + * 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: + * + * [stack] + * [guard page] + * [heap] + * [guard page] + * [memory mapped binary] + * [guard page] */ - sb->sb_mem = mmap(NULL, sandboxlen, 0, MAP_ANON, -1, 0); + length = sandboxlen; + base = sb->sb_mem = mmap(NULL, length, 0, MAP_ANON, -1, 0); if (sb->sb_mem == MAP_FAILED) { saved_errno = errno; warn("%s: mmap region", __func__); goto error; } - if (mmap((uint8_t *)sb->sb_mem + 0x1000, sb->sb_stat.st_size, - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0) == - MAP_FAILED) { + /* + * Skip guard page. + */ + base += GUARD_PAGE_SIZE; + length -= GUARD_PAGE_SIZE; + + /* + * Map program binary. + */ + if (mmap(base, sb->sb_stat.st_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0) == MAP_FAILED) { saved_errno = errno; warn("%s: mmap %s", __func__, path); goto error; } + base += roundup2(sb->sb_stat.st_size, PAGE_SIZE); + length += roundup2(sb->sb_stat.st_size, PAGE_SIZE); + close(fd); fd = -1; - if (mmap((uint8_t *)sb->sb_mem + 0x1000 + - roundup2(sb->sb_stat.st_size, 4096), - sandboxlen - (0x1000 + roundup2(sb->sb_stat.st_size, 4096)), - PROT_READ | PROT_WRITE, MAP_ANON | MAP_FIXED, -1, 0) == - MAP_FAILED) { + /* + * Skip guard page. + */ + base += GUARD_PAGE_SIZE; + length -= GUARD_PAGE_SIZE; + + /* + * Heap. + */ + sb->sb_heapbase = (register_t)base - (register_t)sb->sb_mem; + sb->sb_heaplen = length - (GUARD_PAGE_SIZE + STACK_SIZE); + if (mmap(base, sb->sb_heaplen, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED) { + saved_errno = errno; + warn("%s: mmap heap", __func__); + goto error; + } + base += sb->sb_heaplen; + length -= sb->sb_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 heap/stack", __func__); + warn("%s: mmap stack", __func__); goto error; } + 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); + + /* * XXXRW: Use $c10 to construct the sandbox's segment. This is * probably not the right thing. */ @@ -178,21 +244,30 @@ return (-1); } +#define CHERI_CLOADORCLEAR(cnum, cptr) do { \ + if (c ## cnum != NULL) \ + CHERI_CLC(cnum, 0, cptr, 0); \ + else \ + CHERI_CCLEARTAG(cnum); \ +} while (0) + register_t sandbox_invoke(struct sandbox *sb, register_t a0, register_t a1, - register_t a2, register_t a3, struct chericap *c1, struct chericap *c2) + register_t a2, register_t a3, struct chericap *c1, struct chericap *c2, + struct chericap *c3, struct chericap *c4, struct chericap *c5, + struct chericap *c6, struct chericap *c7) { - if (c1 != NULL) - CHERI_CLC(1, 0, c1, 0); - else - CHERI_CCLEARTAG(1); - if (c2 != NULL) - CHERI_CLC(2, 0, c2, 0); - else - CHERI_CCLEARTAG(2); - CHERI_CLC(3, 0, &sb->sb_segment, 0); - return (_chsbrt_invoke(a0, a1, a2, a3)); + CHERI_CLOADORCLEAR(1, c1); + CHERI_CLOADORCLEAR(2, c2); + CHERI_CLOADORCLEAR(3, c3); + CHERI_CLOADORCLEAR(4, c4); + CHERI_CLOADORCLEAR(5, c5); + CHERI_CLOADORCLEAR(6, c6); + CHERI_CLOADORCLEAR(7, c7); + CHERI_CLC(26, 0, &sb->sb_segment, 0); + return (_chsbrt_invoke(a0, a1, a2, a3, sb->sb_heapbase, + sb->sb_heaplen)); } void ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/sandbox.h#2 (text+ko) ==== @@ -36,7 +36,8 @@ struct sandbox **sbp); register_t sandbox_invoke(struct sandbox *sb, register_t a0, register_t a1, register_t a2, register_t a3, struct chericap *c1, - struct chericap *c2); + struct chericap *c2, struct chericap *c3, struct chericap *c4, + struct chericap *c5, struct chericap *c6, struct chericap *c7); void sandbox_destroy(struct sandbox *sb); #endif /* !_SANDBOX_H_ */ ==== //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/malloc.c#2 (text+ko) ==== @@ -28,8 +28,13 @@ * SUCH DAMAGE. */ +#include + #include +void *_sb_heapbase; +size_t _sb_heaplen; + void * malloc(size_t size __unused) { ==== //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/mips64/chsbrt.S#3 (text+ko) ==== @@ -43,15 +43,20 @@ # $fp contains a pointer to the top of the stack; 32-byte aligned # # $a0-$a3 contain user arguments +# $a4 contains the heap offset within the sandbox +# $a5 contains the heap length # $v0, $v1 contain user return values # # $c0, $pcc contain access to (100% overlapped) sandbox code and data # # $c1-$c7 contain user capability arguments # +# $c26 contains the invoked data capability - the complete segment, +# which will also be installed in $c0 locally due to lack of CCALL. +# # For now, assume: # (1) We are on the receiving end of CJALR, not CCALL. -# (2) The calling code has kindly set up C0 such that this and C code can run. +# (2) We enter with the caller's $c0 due to no CCALL # (3) The caller has not set up the general-purpose register context, that's # our job. # (4) The goal is not to set up the CHERI calling convention .. yet; we will @@ -75,18 +80,18 @@ # # Set up in-sandbox stack. # - cgetlen $sp, $c3 + cgetlen $sp, $c26 move $fp, $sp # # Temporarily, save caller $c0 for later restoration. # - # Notice: store relative to $c3, not $c0. + # Notice: store relative to $c26, not $c0. # # XXXRW: To change once we use CCALL. # daddiu $sp, -32 - csc $c0, $sp, 0($c3) + csc $c0, $sp, 0($c26) # # Install $idc as $c0. From here on out, we can do MIPS feteches and @@ -121,7 +126,15 @@ # registers that aren't explicit or ABI-implied arguments. # + # + # Set up global pointer, also install heap base and length from + # caller. + # dla $gp, _gp + dla $at, _sb_heapbase; + sd $a4, 0($at) + dla $at, _sb_heaplen; + sd $a5, 0($at) # # Invoke MIPS ABI C "invoke" function.