Date: Sun, 6 Oct 2013 21:28:58 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 985964 for review Message-ID: <201310062128.r96LSwEW094916@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@985964?ac=10 Change 985964 by rwatson@rwatson_zenith_cl_cam_ac_uk on 2013/10/06 21:28:27 Update libcheri, used by our various sandboxing demos, to use CCall/CReturn instead of CJALR/CJR and new capability-register calling conventions. Update cheritest-helper to conform to run in CCall sandboxes. When constructing data capabilities for sandboxed code in both libcheri and cheritest, do permit data stores as well data loads; also permit storing and loading capabilities. Other libcheri-aware sandboxed code will need updating for new calling conventions as well. Affected files ... .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest.c#25 edit .. //depot/projects/ctsrd/cheribsd/src/lib/libcheri/mips64/sandboxasm.S#2 edit .. //depot/projects/ctsrd/cheribsd/src/lib/libcheri/sandbox.c#4 edit .. //depot/projects/ctsrd/cheribsd/src/lib/libcheri/sandbox.h#3 edit .. //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/cheritest-helper.c#7 edit .. //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/mips64/chsbrt.S#5 edit Differences ... ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest.c#25 (text+ko) ==== @@ -101,7 +101,8 @@ /* * Configure $c1 and $c2 to enter a simple sandbox. Not suitable for more - * complex tests as it has no notion of configuring heaps/stacks/etc. + * complex tests as it has no notion of configuring heaps/stacks/etc. For + * that, we use libcheri. */ static void cheritest_sandbox_setup(void *sandbox_base, void *sandbox_end, @@ -130,7 +131,8 @@ * Construct a data capability in $c2, derived from $c1 and $c3, * suitable for use with CCall. */ - CHERI_CANDPERM(2, 3, CHERI_PERM_LOAD); + CHERI_CANDPERM(2, 3, CHERI_PERM_LOAD | CHERI_PERM_STORE | + CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE_CAP); CHERI_CSEALDATA(2, 2, 3); /* @@ -295,7 +297,7 @@ err(1, "sandbox_setup"); v = sandbox_invoke(sb, 0, 1, 0, 0, NULL, NULL, NULL, NULL, NULL, - NULL, NULL); + NULL, NULL, NULL); printf("%s: sandbox returned %ju\n", __func__, (uintmax_t)v); sandbox_destroy(sb); } @@ -305,7 +307,7 @@ * stack. Odd. */ static char md5string[] = "hello world"; -static struct chericap c1, c2; +static struct chericap c3, c4; static void cheritest_sandbox_invoke_md5(void) @@ -321,15 +323,15 @@ CHERI_CINCBASE(10, 0, &md5string); CHERI_CSETLEN(10, 10, strlen(md5string)); CHERI_CANDPERM(10, 10, CHERI_PERM_LOAD); - CHERI_CSC(10, 0, &c1, 0); + CHERI_CSC(10, 0, &c3, 0); CHERI_CINCBASE(10, 0, &buf); CHERI_CSETLEN(10, 10, sizeof(buf)); CHERI_CANDPERM(10, 10, CHERI_PERM_STORE); - CHERI_CSC(10, 0, &c2, 0); + CHERI_CSC(10, 0, &c4, 0); - v = sandbox_invoke(sb, strlen(md5string), 0, 0, 0, &c1, &c2, NULL, - NULL, NULL, NULL, NULL); + v = sandbox_invoke(sb, strlen(md5string), 0, 0, 0, &c3, &c4, NULL, + NULL, NULL, NULL, NULL, NULL); printf("%s: sandbox returned %ju\n", __func__, (uintmax_t)v); sandbox_destroy(sb); buf[32] = '\0'; @@ -377,9 +379,6 @@ if (argc == 0) usage(); - /* Save original C0 in C1 for later use. */ - CHERI_CMOVE(1, 0); - for (i = 0; i < argc; i++) { if (strcmp(argv[i], "listcausereg") == 0) cheritest_listcausereg(); ==== //depot/projects/ctsrd/cheribsd/src/lib/libcheri/mips64/sandboxasm.S#2 (text+ko) ==== @@ -1,5 +1,5 @@ #- -# Copyright (c) 2012 Robert N. M. Watson +# Copyright (c) 2012-2013 Robert N. M. Watson # All rights reserved. # # This software was developed by SRI International and the University of @@ -35,13 +35,22 @@ # # Caller side of the CHERI sandbox runtime startup code -- set up arguments -# for a CJALR into a sandbox. Eventually, this should be a CCALL. +# for a CCall into a sandbox. +# +# ABI conventions; *'d items implemented here: +# $c1 contains to-be-invoked sealed code capability * +# $c2 contains to-be-invoked sealed data capability * +# $c3-$c10 caller-save argument registers +# $c3 return value register +# $c11-$c16 caller-save registers +# $c17-$c24 callee-save registers +# $c25 unused * +# $c26 IDC * # -# Temporary ABI conventions: -# $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 # +# XXXRW: No floating-point support. +# .text .global _chsbrt_invoke @@ -49,15 +58,11 @@ _chsbrt_invoke: # - # XXXRW: When CCALL, save caller $c0 here. - # - - # # Save caller-save general-purpose registers. # # XXXRW: Check this -- and also other caller-save registers? # - # XXXRW: Notice: neither floating point registers nor CHERI registers. + # XXXRW: Save caller-save capability registers. # daddiu $sp, -96 sd $gp, 88($sp) @@ -74,24 +79,23 @@ sd $fp, 0($sp) # - # XXXRW: When CCALL, scrub general-purpose and CHERI registers here. + # XXXRW: When CCall, scrub general-purpose and capability registers + # here. # - # - # XXXRW: When CCALL, install $c0 here. - # + # Save $c0 in IDC for use after return. + cmove $c26, $c0 + + # Clear $c0 so it is not available to the sanebox. + ccleartag $c0 + + # Invoke object capability. + ccall $c1, $c2 - # - # Enter sandbox, entering at 0x1000. - # - dli $t0, 0x1000 - cjalr $t0($c26) - nop # XXXRW: Branch-delay slot? + # Set $c0 back to restored $idc. + cmove $c0, $c26 - # - # Notice that we are trusting the returned $sp value; fine for CJALR - # but not for CCALL. - # + # Use CCall-restored $sp to restore other registers of note. ld $fp, 0($sp) ld $s0, 8($sp) ld $s1, 16($sp) @@ -107,11 +111,10 @@ daddiu $sp, 96 # - # XXXRW: When CCALL, restore $c0 here. + # XXXRW: Restore caller-save capability registers. # - - # - # XXXRW: Defensively clear registers on return? + # XXXRW: Defensively clear other general-purpose, capability registers + # on return? # # ==== //depot/projects/ctsrd/cheribsd/src/lib/libcheri/sandbox.c#4 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012 Robert N. M. Watson + * Copyright (c) 2012-2013 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of @@ -66,7 +66,8 @@ register_t sb_sandboxlen; register_t sb_heapbase; register_t sb_heaplen; - struct chericap sb_segment; + struct chericap sb_codecap; /* Sealed code capability for CCall. */ + struct chericap sb_datacap; /* Sealed data capability for CCall. */ struct stat sb_stat; }; @@ -204,13 +205,36 @@ assert(length == 0); /* - * XXXRW: Use $c10 to construct the sandbox's segment. This is - * probably not the right thing. + * Construct a generic capability in $c10 that describes the combined + * code/data segment that we will seal. + * + * Derive from $c3 a code capability in $c1, and data capability in + * $c2, suitable for use with CCall. Store in the persistent sandbox + * description for later use. + * + * XXXRW: $c3 is probably not the right thing. + */ + CHERI_CINCBASE(3, 0, sb->sb_mem); + CHERI_CSETTYPE(3, 3, 0x1000); /* Sandbox start address. */ + CHERI_CSETLEN(3, 3, sandboxlen); + + /* + * Construct a code capability in $c1, derived from $c3, suitable for + * use with CCall. + */ + CHERI_CANDPERM(1, 3, CHERI_PERM_EXECUTE | CHERI_PERM_SEAL); + CHERI_CSEALCODE(1, 1); + + /* + * Construct a data capability in $c2, derived from $c1 and $c3, + * suitable for use with CCall. */ - CHERI_CMOVE(10, 0); - CHERI_CINCBASE(10, 10, sb->sb_mem); - CHERI_CSETLEN(10, 10, sandboxlen); - CHERI_CSC(10, 0, &sb->sb_segment, 0); + CHERI_CANDPERM(2, 3, CHERI_PERM_LOAD | CHERI_PERM_STORE | + CHERI_PERM_LOAD_CAP | CHERI_PERM_STORE_CAP); + CHERI_CSEALDATA(2, 2, 3); + + CHERI_CSC(1, 0, &sb->sb_codecap, 0); + CHERI_CSC(2, 0, &sb->sb_datacap, 0); sb->sb_sandboxlen = sandboxlen; if (sb_verbose) { @@ -218,21 +242,42 @@ printf(" Path: %s\n", sb->sb_path); printf(" Mem: %p\n", sb->sb_mem); printf(" Len: %ju\n", (uintmax_t)sb->sb_sandboxlen); - printf(" Segment:\n"); - CHERI_CGETTAG(v, 10); + printf(" Code capability:\n"); + CHERI_CGETTAG(v, 1); + printf(" t %u", (u_int)v); + CHERI_CGETUNSEALED(v, 1); + printf(" u %u", (u_int)v); + CHERI_CGETPERM(v, 1); + printf(" perms %04x", (u_int)v); + CHERI_CGETTYPE(v, 1); + printf(" otype %p\n", (void *)v); + CHERI_CGETBASE(v, 1); + printf(" base %p", (void *)v); + CHERI_CGETLEN(v, 1); + printf(" length %p\n", (void *)v); + + printf(" Data capability:\n"); + CHERI_CGETTAG(v, 2); printf(" t %u", (u_int)v); - CHERI_CGETUNSEALED(v, 10); + CHERI_CGETUNSEALED(v, 2); printf(" u %u", (u_int)v); - CHERI_CGETPERM(v, 10); + CHERI_CGETPERM(v, 2); printf(" perms %04x", (u_int)v); - CHERI_CGETTYPE(v, 10); + CHERI_CGETTYPE(v, 2); printf(" otype %p\n", (void *)v); - CHERI_CGETBASE(v, 10); + CHERI_CGETBASE(v, 2); printf(" base %p", (void *)v); - CHERI_CGETLEN(v, 10); + CHERI_CGETLEN(v, 2); printf(" length %p\n", (void *)v); } + /* + * Clear $c1, $c2, and $c3, which we no longer require. + */ + CHERI_CCLEARTAG(1); + CHERI_CCLEARTAG(2); + CHERI_CCLEARTAG(3); + *sbp = sb; return (0); @@ -259,19 +304,39 @@ 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 *c3, struct chericap *c4, struct chericap *c5, - struct chericap *c6, struct chericap *c7) + register_t a2, register_t a3, struct chericap *c3, struct chericap *c4, + struct chericap *c5, struct chericap *c6, struct chericap *c7, + struct chericap *c8, struct chericap *c9, struct chericap *c10) { - CHERI_CLOADORCLEAR(1, c1); - CHERI_CLOADORCLEAR(2, c2); + CHERI_CLC(1, 0, &sb->sb_codecap, 0); + CHERI_CLC(2, 0, &sb->sb_datacap, 0); 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); + CHERI_CLOADORCLEAR(8, c8); + CHERI_CLOADORCLEAR(9, c9); + CHERI_CLOADORCLEAR(10, c10); +#ifndef SPEEDY_BUT_SLOPPY + CHERI_CCLEARTAG(11); + CHERI_CCLEARTAG(12); + CHERI_CCLEARTAG(13); + CHERI_CCLEARTAG(14); + CHERI_CCLEARTAG(15); + CHERI_CCLEARTAG(16); + CHERI_CCLEARTAG(17); + CHERI_CCLEARTAG(18); + CHERI_CCLEARTAG(19); + CHERI_CCLEARTAG(20); + CHERI_CCLEARTAG(21); + CHERI_CCLEARTAG(22); + CHERI_CCLEARTAG(23); + CHERI_CCLEARTAG(24); + CHERI_CCLEARTAG(25); + CHERI_CCLEARTAG(26); +#endif return (_chsbrt_invoke(a0, a1, a2, a3, sb->sb_heapbase, sb->sb_heaplen)); } ==== //depot/projects/ctsrd/cheribsd/src/lib/libcheri/sandbox.h#3 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012 Robert N. M. Watson + * Copyright (c) 2012-2013 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of @@ -37,9 +37,10 @@ int sandbox_setup(const char *path, register_t sandboxlen, 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 *c3, struct chericap *c4, - struct chericap *c5, struct chericap *c6, struct chericap *c7); + register_t a1, register_t a2, register_t a3, struct chericap *c3, + struct chericap *c4, struct chericap *c5, struct chericap *c6, + struct chericap *c7, struct chericap *c8, struct chericap *c9, + struct chericap *c10); void sandbox_destroy(struct sandbox *sb); #endif /* !_SANDBOX_H_ */ ==== //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/cheritest-helper.c#7 (text+ko) ==== @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2012 Robert N. M. Watson + * Copyright (c) 2012-2013 Robert N. M. Watson * All rights reserved. * * This software was developed by SRI International and the University of @@ -41,8 +41,8 @@ /* * Sample sandboxed code. Calculate an MD5 checksum of the data arriving via - * c1, and place the checksum in c2. a0 will hold input data length. c2 - * must be (at least) 33 bytes. + * c3, and place the checksum in c4. a0 will hold input data length. c4 must + * be (at least) 33 bytes. * * ... unless a1 is set, in which case immediately abort() to test that case. */ @@ -59,11 +59,11 @@ MD5Init(&md5context); for (count = 0; count < a0; count++) { - memcpy_fromcap(&ch, 1, count, sizeof(ch)); + memcpy_fromcap(&ch, 3, count, sizeof(ch)); MD5Update(&md5context, &ch, sizeof(ch)); } MD5End(&md5context, buf); - memcpy_tocap(2, buf, 0, sizeof(buf)); + memcpy_tocap(4, buf, 0, sizeof(buf)); /* * Invoke getpid() to trigger kernel protection features. Should ==== //depot/projects/ctsrd/cheribsd/src/libexec/cheritest-helper/mips64/chsbrt.S#5 (text+ko) ==== @@ -1,5 +1,5 @@ #- -# Copyright (c) 2012 Robert N. M. Watson +# Copyright (c) 2012-2013 Robert N. M. Watson # All rights reserved. # # This software was developed by SRI International and the University of @@ -49,17 +49,16 @@ # # $c0, $pcc contain access to (100% overlapped) sandbox code and data # -# $c1-$c7 contain user capability arguments +# $c1, $c2 contain the invoked object capability +# $c3-$c10 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. +# $c26 contains the invoked data capability - the complete segment, which +# we will install into $c0 to allow MIPS code to access it. # # For now, assume: -# (1) We are on the receiving end of CJALR, not CCALL. -# (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 +# (1) 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 +# (2) The goal is not to set up the CHERI calling convention .. yet; we will # run only native MIPS64 code, or hand-crafted CHERI assembler. Thus # must change before we can run Clang-compiled CHERI code. # @@ -69,31 +68,12 @@ __start: # - # Temporarily, save caller stack in temporaries so that we can - # restore them on return. - # - # XXXRW: To change once we use CCALL. - # - move $t0, $sp - move $t1, $fp - - # # Set up in-sandbox stack. # cgetlen $sp, $c26 move $fp, $sp # - # Temporarily, save caller $c0 for later restoration. - # - # Notice: store relative to $c26, not $c0. - # - # XXXRW: To change once we use CCALL. - # - daddiu $sp, -32 - csc $c0, $sp, 0($c26) - - # # Install $idc as $c0. From here on out, we can do MIPS feteches and # stores to memory inside the sandbox, and $c0-relative capability # fetches and stores. @@ -101,27 +81,6 @@ cmove $c0, $c26 # - # Push return capability. - # - daddiu $sp, -32 - csc $c24, $sp, 0($c0) - - # - # Push return address. - # - daddiu $sp, -8 - sd $ra, 0($sp) - - # - # Save caller stack pointers for later restoration. - # - # XXXRW: To change once we use CCALL. - # - daddiu $sp, -16 - sd $t0, 0($sp) - sd $t1, 8($sp) - - # # XXXRW: Defensively clear all general-purpose and capability # registers that aren't explicit or ABI-implied arguments. # @@ -137,89 +96,32 @@ sd $a5, 0($at) # - # If abort() is called, we effectively longjmp back to just after the - # call to invoke(). Save a stack pointer for that unwind. + # Invoke MIPS ABI C "invoke" function. # - dla $at, abort_stack - sd $sp, 0($at) - - # - # Invoke MIPS ABI C "invoke" function. + # XXXRW: $t9 not set properly. # dla $25, invoke jalr $25 nop # Branch-delay slot - # - # Pop caller stack pointers for later installation. - # - # XXXRW: To move to caller context once using CCALL. - # abort_target: - ld $t0, 0($sp) - ld $t1, 8($sp) - daddiu $sp, 16 - # - # Pop return address. + # Clear our $c0 so that it is not leaked back to caller. # - ld $ra, 0($sp) - daddiu $sp, 8 - - # - # Pop return capability. - # - clc $c24, $sp, 0($c0) - daddiu $sp, 32 - - # - # Pop caller $c0 -- no more use of MIPS fetch/store after this point. - # - # XXXRW: To move to caller context once using CCALL. - # - clc $c0, $sp, 0($c0) - daddiu $sp, 32 + ccleartag $c0 # - # Re-install caller stack. - # - # XXXRW: To move to caller context once using CCALL. - # - move $sp, $t0 - move $fp, $t1 - - # - # XXXRW: Defensively clear general-purpose and capability registers - # that aren't explicit or ABI-implied return values. - # - dli $at, 0 - dli $t2, 0 - dli $t3, 0 - dli $t8, 0 - dli $t9, 0 - - # # Return to caller. # - cjr $31($c24) # Jump to return capability register - nop # Branch-delay slot? + creturn .end __start .global abort .ent abort abort: - # - # If abort() is called, unwind the stack and jump into the return - # code. Set $v0 to -2 so that it's somewhat recognisable, even if - # non-ideal. - # - dla $at, abort_stack - ld $sp, 0($at) dli $v0, -2 b abort_target nop .end abort .data -abort_stack: - .dword 0x0000000000000000 # What to restore sp to on abort
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310062128.r96LSwEW094916>