Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Nov 2012 08:09:40 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 219766 for review
Message-ID:  <201211130809.qAD89e4e010668@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/types.h>
+
 #include <stdlib.h>
 
+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.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211130809.qAD89e4e010668>