Skip site navigation (1)Skip section navigation (2)
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>