PERFORCE change 985964 for review
Robert Watson
rwatson at FreeBSD.org
Sun Oct 6 21:28:59 UTC 2013
http://p4web.freebsd.org/@@985964?ac=10
Change 985964 by rwatson at 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
More information about the p4-projects
mailing list