about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-02-13 07:46:21 +0000
committerbors <bors@rust-lang.org>2019-02-13 07:46:21 +0000
commitccd23b95e5077a89a2ce35d09cbd4141ccc94f58 (patch)
tree081854c6d2d08c3e816a5661f73129cb53be960a /src/libstd/sys
parent827a141466e7bb85eb3c030600878a2c606019e9 (diff)
parent0d2ab0b77dd82d192f987ab4e1645577eccd3562 (diff)
downloadrust-ccd23b95e5077a89a2ce35d09cbd4141ccc94f58.tar.gz
rust-ccd23b95e5077a89a2ce35d09cbd4141ccc94f58.zip
Auto merge of #58235 - jethrogb:jb/sgx-usercall-internals, r=alexcrichton
SGX target: simplify usercall internals

This moves logic from assembly to Rust and removes the special case for exit/panic handling, merging it with regular usercall handling.

Also, this fixes a bug in the exit usercall introduced in a75ae00. The bug would make regular exits look like panics with high probability. It would also with some probability leak information through uncleared registers.

cc @VardhanThigle

r? @alexcrichton
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/sgx/abi/entry.S55
-rw-r--r--src/libstd/sys/sgx/abi/mod.rs2
-rw-r--r--src/libstd/sys/sgx/abi/panic.rs6
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/mod.rs2
-rw-r--r--src/libstd/sys/sgx/abi/usercalls/raw.rs73
-rw-r--r--src/libstd/sys/sgx/mod.rs2
6 files changed, 59 insertions, 81 deletions
diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S
index 9b46c2180d9..c03e3869aa3 100644
--- a/src/libstd/sys/sgx/abi/entry.S
+++ b/src/libstd/sys/sgx/abi/entry.S
@@ -69,10 +69,6 @@ IMAGE_BASE:
     .asciz "Re-entered aborted enclave!"
 .Lreentry_panic_msg_end:
 
-.Lusercall_panic_msg:
-    .asciz "Invalid usercall#!"
-.Lusercall_panic_msg_end:
-
 .org .Lxsave_clear+512
 .Lxsave_header:
     .int 0, 0 /*  XSTATE_BV */
@@ -219,13 +215,21 @@ sgx_entry:
     orq $8,%rsp
     jmp panic_msg
 
-.Lusercall_panic:
-    lea .Lusercall_panic_msg(%rip),%rdi
-    mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi
-    orq $8,%rsp
-    jmp panic_msg
-
-.macro push_callee_saved_registers
+/*  This *MUST* be called with 6 parameters, otherwise register information */
+/*  might leak! */
+.global usercall
+usercall:
+    test %rcx,%rcx            /* check `abort` function argument */
+    jnz .Lusercall_abort      /* abort is set, jump to abort code (unlikely forward conditional) */
+    jmp .Lusercall_save_state /* non-aborting usercall */
+.Lusercall_abort:
+/* set aborted bit */
+    movb $1,.Laborted(%rip)
+/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
+    testb $0xff,DEBUG(%rip)
+    jz .Lusercall_noreturn
+.Lusercall_save_state:
+/*  save callee-saved state */
     push %r15
     push %r14
     push %r13
@@ -235,33 +239,8 @@ sgx_entry:
     sub $8, %rsp
     fstcw 4(%rsp)
     stmxcsr (%rsp)
-.endm
-
-.global usercall_exit
-usercall_exit:
-/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
-    testb $0xff,DEBUG(%rip)
-    jz .Lskip_save_registers
-    push_callee_saved_registers
-    movq %rsp,%gs:tcsls_panic_last_rsp
-.Lskip_save_registers:
-/* set aborted bit */
-    movb $1,.Laborted(%rip)
-/* call usercall exit(true) */
-    /* NOP: mov %rsi,%rsi */ /*  RSI = usercall() argument: panic */
-    xor %rdx,%rdx /*  RDX cleared */
-    movq $usercall_nr_exit,%rdi /*  RDI = usercall exit */
-    jmp .Lexit
-
-/*  This *MUST* be called with 6 parameters, otherwise register information */
-/*  might leak! */
-.global usercall
-usercall:
-    test %rdi,%rdi
-    jle .Lusercall_panic
-/*  save callee-saved state */
-    push_callee_saved_registers
     movq %rsp,%gs:tcsls_last_rsp
+.Lusercall_noreturn:
 /*  clear general purpose register state */
     /*  RAX overwritten by ENCLU */
     /*  RBX set by sgx_exit */
@@ -281,7 +260,7 @@ usercall:
     jmp .Lsgx_exit
 .Lusercall_ret:
     movq $0,%gs:tcsls_last_rsp
-/*  restore callee-saved state, cf. push_callee_saved_registers */
+/*  restore callee-saved state, cf. "save" above */
     mov %r11,%rsp
     ldmxcsr (%rsp)
     fldcw 4(%rsp)
diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs
index 5ef069aa81c..509a1990d97 100644
--- a/src/libstd/sys/sgx/abi/mod.rs
+++ b/src/libstd/sys/sgx/abi/mod.rs
@@ -12,7 +12,7 @@ pub mod tls;
 #[macro_use]
 pub mod usercalls;
 
-global_asm!(concat!(usercalls_asm!(), include_str!("entry.S")));
+global_asm!(include_str!("entry.S"));
 
 #[no_mangle]
 unsafe extern "C" fn tcs_init(secondary: bool) {
diff --git a/src/libstd/sys/sgx/abi/panic.rs b/src/libstd/sys/sgx/abi/panic.rs
index d23fa9a9ec6..b2afacc70b8 100644
--- a/src/libstd/sys/sgx/abi/panic.rs
+++ b/src/libstd/sys/sgx/abi/panic.rs
@@ -1,4 +1,4 @@
-use super::usercalls::alloc::UserRef;
+use super::usercalls::{alloc::UserRef, self};
 use cmp;
 use io::{self, Write};
 use mem;
@@ -52,7 +52,5 @@ impl Write for SgxPanicOutput {
 #[no_mangle]
 pub extern "C" fn panic_msg(msg: &str) -> ! {
     let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
-    unsafe { usercall_exit(true); }
+    usercalls::exit(true)
 }
-
-extern "C" { pub fn usercall_exit(panic: bool) -> !; }
diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs
index bae044b906b..511d6e9e927 100644
--- a/src/libstd/sys/sgx/abi/usercalls/mod.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs
@@ -120,7 +120,7 @@ pub unsafe fn launch_thread() -> IoResult<()> {
 /// Usercall `exit`. See the ABI documentation for more information.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub fn exit(panic: bool) -> ! {
-    unsafe { super::panic::usercall_exit(panic) }
+    unsafe { raw::exit(panic) }
 }
 
 /// Usercall `wait`. See the ABI documentation for more information.
diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs
index 004cf57602b..447f20584f8 100644
--- a/src/libstd/sys/sgx/abi/usercalls/raw.rs
+++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs
@@ -4,12 +4,13 @@
 pub use fortanix_sgx_abi::*;
 
 use ptr::NonNull;
+use num::NonZeroU64;
 
 #[repr(C)]
 struct UsercallReturn(u64, u64);
 
 extern "C" {
-    fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
+    fn usercall(nr: NonZeroU64, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn;
 }
 
 /// Performs the raw usercall operation as defined in the ABI calling convention.
@@ -23,9 +24,11 @@ extern "C" {
 ///
 /// Panics if `nr` is `0`.
 #[unstable(feature = "sgx_platform", issue = "56975")]
-pub unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) {
-    if nr==0 { panic!("Invalid usercall number {}",nr) }
-    let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4);
+#[inline]
+pub unsafe fn do_usercall(nr: NonZeroU64, p1: u64, p2: u64, p3: u64, p4: u64, abort: bool)
+    -> (u64, u64)
+{
+    let UsercallReturn(a, b) = usercall(nr, p1, p2, abort as _, p3, p4);
     (a, b)
 }
 
@@ -41,7 +44,6 @@ trait ReturnValue {
 }
 
 macro_rules! define_usercalls {
-    // Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging`
     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
         /// Usercall numbers as per the ABI.
         #[repr(u64)]
@@ -59,22 +61,6 @@ macro_rules! define_usercalls {
     };
 }
 
-macro_rules! define_usercalls_asm {
-    ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
-        macro_rules! usercalls_asm {
-            () => {
-                concat!(
-                    ".equ usercall_nr_LAST, 0\n",
-                    $(
-                    ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
-                    ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
-                    ),*
-                )
-            }
-        }
-    };
-}
-
 macro_rules! define_ra {
     (< $i:ident > $t:ty) => {
         impl<$i> RegisterArgument for $t {
@@ -173,74 +159,90 @@ impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
     }
 }
 
+macro_rules! return_type_is_abort {
+    (!) => { true };
+    ($r:ty) => { false };
+}
+
+// In this macro: using `$r:tt` because `$r:ty` doesn't match ! in `return_type_is_abort`
 macro_rules! enclave_usercalls_internal_define_usercalls {
     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
-                     $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
+                     $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
                 RegisterArgument::into_register($n4),
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
+    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
                 RegisterArgument::into_register($n3),
-                0
+                0,
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
+    (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
                 RegisterArgument::into_register($n2),
-                0,0
+                0,0,
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
+    (def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f($n1: $t1) -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
                 RegisterArgument::into_register($n1),
-                0,0,0
+                0,0,0,
+                return_type_is_abort!($r)
             ))
         }
     );
-    (def fn $f:ident() -> $r:ty) => (
+    (def fn $f:ident() -> $r:tt) => (
         /// This is the raw function definition, see the ABI documentation for
         /// more information.
         #[unstable(feature = "sgx_platform", issue = "56975")]
         #[inline(always)]
         pub unsafe fn $f() -> $r {
             ReturnValue::from_registers(stringify!($f), do_usercall(
-                Usercalls::$f as Register,
-                0,0,0,0
+                NonZeroU64::new(Usercalls::$f as Register)
+                    .expect("Usercall number must be non-zero"),
+                0,0,0,0,
+                return_type_is_abort!($r)
             ))
         }
     );
@@ -250,4 +252,3 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
 }
 
 invoke_with_usercalls!(define_usercalls);
-invoke_with_usercalls!(define_usercalls_asm);
diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs
index f2593c35bed..4225ecbb206 100644
--- a/src/libstd/sys/sgx/mod.rs
+++ b/src/libstd/sys/sgx/mod.rs
@@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
 }
 
 pub unsafe fn abort_internal() -> ! {
-    abi::panic::usercall_exit(true)
+    abi::usercalls::exit(true)
 }
 
 pub fn hashmap_random_keys() -> (u64, u64) {