PERFORCE change 219766 for review
Robert Watson
rwatson at FreeBSD.org
Tue Nov 13 08:09:41 UTC 2012
http://p4web.freebsd.org/@@219766?ac=10
Change 219766 by rwatson at 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.
More information about the p4-projects
mailing list