Date: Sun, 6 Oct 2013 10:40:27 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 980156 for review Message-ID: <201310061040.r96AeRgE079587@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@980156?ac=10 Change 980156 by rwatson@rwatson_zenith_cl_cam_ac_uk on 2013/10/06 10:40:15 Rework setup of simple CCall/CReturn sandboxes in cheritest a little: - Abstract the code very mildly to allow different types of sandboxes to be created. - Clear $c3 once a sandbox is set up for calling in $c1 and $c2, as it is no longer required. - Save the host environment $c0 in $idc before CCall, and clear it before entering the sandbox; restore it from $idc after the sandbox has returned; sandboxes no longer inherit access to the global address space by default. - Add a new and highly adventurous ccall_nop_creturn test case, which not only enters and returns from a sandbox, but runs three (3) nops inside. Affected files ... .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest.c#24 edit .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest_sandbox.S#3 edit .. //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest_sandbox.h#3 edit Differences ... ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest.c#24 (text+ko) ==== @@ -68,9 +68,9 @@ usage(void) { - fprintf(stderr, "cheritest ccall\n"); + fprintf(stderr, "cheritest ccall_creturn\n"); + fprintf(stderr, "cheritest ccall_nop_creturn\n"); fprintf(stderr, "cheritest copyregs\n"); - fprintf(stderr, "cheritest creturn\n"); fprintf(stderr, "cheritest listcausereg\n"); fprintf(stderr, "cheritest listprivregs\n"); fprintf(stderr, "cheritest listregs\n"); @@ -99,8 +99,13 @@ CHERI_CSB(0, 0, 0, 1); } +/* + * 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. + */ static void -cheritest_ccall(void) +cheritest_sandbox_setup(void *sandbox_base, void *sandbox_end, + register_t sandbox_pc) { /*- @@ -109,16 +114,10 @@ * * Derive from $c3 a code capability in $c1, and data capability in * $c2, suitable for use with CCall. - * - * Current limitations: - * - $c2 doesn't matter as sandbox_creturn doesn't access data. - * - We don't flush registers before CCall. - * - We don't restore registers after CCall. */ - CHERI_CINCBASE(3, 0, &sandbox_creturn); - CHERI_CSETTYPE(3, 3, 0); - CHERI_CSETLEN(3, 3, (uintptr_t)&sandbox_creturn_end - - (uintptr_t)&sandbox_creturn); + CHERI_CINCBASE(3, 0, sandbox_base); + CHERI_CSETTYPE(3, 3, sandbox_pc); + CHERI_CSETLEN(3, 3, (uintptr_t)sandbox_end - (uintptr_t)sandbox_base); /* * Construct a code capability in $c1, derived from $c3, suitable for @@ -133,16 +132,59 @@ */ CHERI_CANDPERM(2, 3, CHERI_PERM_LOAD); CHERI_CSEALDATA(2, 2, 3); - - /* Invoke capability. */ - CHERI_CCALL(1, 2); + + /* + * Clear $c3 which we no longer require. + */ + CHERI_CCLEARTAG(3); +} + +/* + * Wrapper for CHERI_CCALL(). We don't use the normal CHERI_CCALL() macro + * because we want to sort out $c0, and can't let compiler-generated code run + * between $c0 manipulation and CCall. + * + * XXXRW: We should probably be flushing much of the general-purpose register + * file before CCall, and restore them afterwards, at measurable cost. + * + * XXXRW: This should probably just be an assembly function rather than inline + * assembly, because then the compiler would save caller-save registers for + * us, if required, saving some work. + */ +static void +cheritest_ccall(void) +{ + + __asm__ __volatile__ ( + /* Move $c0 to $idc so that it will be saved by CCall. */ + "cmove $c26, $c0;" + + /* Clear $c0 so it's not available to sandbox. */ + "ccleartag $c0;" + + /* Invoke object capability. */ + "ccall $c1, $c2;" + + /* Set $c0 back to stored $idc. */ + "cmove $c0, $c26" + : : : "memory"); +} + +static void +cheritest_ccall_creturn(void) +{ + + cheritest_sandbox_setup(&sandbox_creturn, &sandbox_creturn_end, 0); + cheritest_ccall(); } static void -cheritest_creturn(void) +cheritest_ccall_nop_creturn(void) { - CHERI_CRETURN(); + cheritest_sandbox_setup(&sandbox_nop_creturn, + &sandbox_nop_creturn_end, 0); + cheritest_ccall(); } static void @@ -345,12 +387,12 @@ cheritest_listprivregs(); else if (strcmp(argv[i], "listregs") == 0) cheritest_listregs(); - else if (strcmp(argv[i], "ccall") == 0) - cheritest_ccall(); + else if (strcmp(argv[i], "ccall_creturn") == 0) + cheritest_ccall_creturn(); + else if (strcmp(argv[i], "ccall_nop_creturn") == 0) + cheritest_ccall_nop_creturn(); else if (strcmp(argv[i], "copyregs") == 0) cheritest_copyregs(); - else if (strcmp(argv[i], "creturn") == 0) - cheritest_creturn(); else if (strcmp(argv[i], "nullderef") == 0) cheritest_nullderef(); else if (strcmp(argv[i], "overrun") == 0) ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest_sandbox.S#3 (text+ko) ==== @@ -50,3 +50,22 @@ .global sandbox_creturn_end sandbox_creturn_end: + + + /* + * Sandbox code that performs a series of nops before creturn. + * Position-independent, no memory access. + */ + .text + .global sandbox_nop_creturn + .ent sandbox_nop_creturn +sandbox_nop_creturn: + + nop + nop + nop + creturn + .end sandbox_nop_creturn + + .global sandbox_nop_creturn_end +sandbox_nop_creturn_end: ==== //depot/projects/ctsrd/cheribsd/src/bin/cheritest/cheritest_sandbox.h#3 (text+ko) ==== @@ -34,4 +34,7 @@ extern void *sandbox_creturn; extern void *sandbox_creturn_end; +extern void *sandbox_nop_creturn; +extern void *sandbox_nop_creturn_end; + #endif /* !_CHERITEST_SANDBOX_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310061040.r96AeRgE079587>