Skip to content

Commit ccd23b9

Browse files
committed
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
2 parents 827a141 + 0d2ab0b commit ccd23b9

File tree

7 files changed

+59
-84
lines changed

7 files changed

+59
-84
lines changed

src/libstd/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,6 @@ extern crate backtrace_sys;
341341
#[cfg(test)] extern crate std as realstd;
342342

343343
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
344-
#[macro_use]
345-
#[allow(unused_imports)] // FIXME: without `#[macro_use]`, get error: “cannot
346-
// determine resolution for the macro `usercalls_asm`”
347344
extern crate fortanix_sgx_abi;
348345

349346
// The standard macros that are not built-in to the compiler.

src/libstd/sys/sgx/abi/entry.S

+17-38
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ IMAGE_BASE:
6969
.asciz "Re-entered aborted enclave!"
7070
.Lreentry_panic_msg_end:
7171

72-
.Lusercall_panic_msg:
73-
.asciz "Invalid usercall#!"
74-
.Lusercall_panic_msg_end:
75-
7672
.org .Lxsave_clear+512
7773
.Lxsave_header:
7874
.int 0, 0 /* XSTATE_BV */
@@ -219,13 +215,21 @@ sgx_entry:
219215
orq $8,%rsp
220216
jmp panic_msg
221217

222-
.Lusercall_panic:
223-
lea .Lusercall_panic_msg(%rip),%rdi
224-
mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi
225-
orq $8,%rsp
226-
jmp panic_msg
227-
228-
.macro push_callee_saved_registers
218+
/* This *MUST* be called with 6 parameters, otherwise register information */
219+
/* might leak! */
220+
.global usercall
221+
usercall:
222+
test %rcx,%rcx /* check `abort` function argument */
223+
jnz .Lusercall_abort /* abort is set, jump to abort code (unlikely forward conditional) */
224+
jmp .Lusercall_save_state /* non-aborting usercall */
225+
.Lusercall_abort:
226+
/* set aborted bit */
227+
movb $1,.Laborted(%rip)
228+
/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
229+
testb $0xff,DEBUG(%rip)
230+
jz .Lusercall_noreturn
231+
.Lusercall_save_state:
232+
/* save callee-saved state */
229233
push %r15
230234
push %r14
231235
push %r13
@@ -235,33 +239,8 @@ sgx_entry:
235239
sub $8, %rsp
236240
fstcw 4(%rsp)
237241
stmxcsr (%rsp)
238-
.endm
239-
240-
.global usercall_exit
241-
usercall_exit:
242-
/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
243-
testb $0xff,DEBUG(%rip)
244-
jz .Lskip_save_registers
245-
push_callee_saved_registers
246-
movq %rsp,%gs:tcsls_panic_last_rsp
247-
.Lskip_save_registers:
248-
/* set aborted bit */
249-
movb $1,.Laborted(%rip)
250-
/* call usercall exit(true) */
251-
/* NOP: mov %rsi,%rsi */ /* RSI = usercall() argument: panic */
252-
xor %rdx,%rdx /* RDX cleared */
253-
movq $usercall_nr_exit,%rdi /* RDI = usercall exit */
254-
jmp .Lexit
255-
256-
/* This *MUST* be called with 6 parameters, otherwise register information */
257-
/* might leak! */
258-
.global usercall
259-
usercall:
260-
test %rdi,%rdi
261-
jle .Lusercall_panic
262-
/* save callee-saved state */
263-
push_callee_saved_registers
264242
movq %rsp,%gs:tcsls_last_rsp
243+
.Lusercall_noreturn:
265244
/* clear general purpose register state */
266245
/* RAX overwritten by ENCLU */
267246
/* RBX set by sgx_exit */
@@ -281,7 +260,7 @@ usercall:
281260
jmp .Lsgx_exit
282261
.Lusercall_ret:
283262
movq $0,%gs:tcsls_last_rsp
284-
/* restore callee-saved state, cf. push_callee_saved_registers */
263+
/* restore callee-saved state, cf. "save" above */
285264
mov %r11,%rsp
286265
ldmxcsr (%rsp)
287266
fldcw 4(%rsp)

src/libstd/sys/sgx/abi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub mod tls;
1212
#[macro_use]
1313
pub mod usercalls;
1414

15-
global_asm!(concat!(usercalls_asm!(), include_str!("entry.S")));
15+
global_asm!(include_str!("entry.S"));
1616

1717
#[no_mangle]
1818
unsafe extern "C" fn tcs_init(secondary: bool) {

src/libstd/sys/sgx/abi/panic.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::usercalls::alloc::UserRef;
1+
use super::usercalls::{alloc::UserRef, self};
22
use cmp;
33
use io::{self, Write};
44
use mem;
@@ -52,7 +52,5 @@ impl Write for SgxPanicOutput {
5252
#[no_mangle]
5353
pub extern "C" fn panic_msg(msg: &str) -> ! {
5454
let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
55-
unsafe { usercall_exit(true); }
55+
usercalls::exit(true)
5656
}
57-
58-
extern "C" { pub fn usercall_exit(panic: bool) -> !; }

src/libstd/sys/sgx/abi/usercalls/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pub unsafe fn launch_thread() -> IoResult<()> {
120120
/// Usercall `exit`. See the ABI documentation for more information.
121121
#[unstable(feature = "sgx_platform", issue = "56975")]
122122
pub fn exit(panic: bool) -> ! {
123-
unsafe { super::panic::usercall_exit(panic) }
123+
unsafe { raw::exit(panic) }
124124
}
125125

126126
/// Usercall `wait`. See the ABI documentation for more information.

src/libstd/sys/sgx/abi/usercalls/raw.rs

+37-36
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
pub use fortanix_sgx_abi::*;
55

66
use ptr::NonNull;
7+
use num::NonZeroU64;
78

89
#[repr(C)]
910
struct UsercallReturn(u64, u64);
1011

1112
extern "C" {
12-
fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
13+
fn usercall(nr: NonZeroU64, p1: u64, p2: u64, abort: u64, p3: u64, p4: u64) -> UsercallReturn;
1314
}
1415

1516
/// Performs the raw usercall operation as defined in the ABI calling convention.
@@ -23,9 +24,11 @@ extern "C" {
2324
///
2425
/// Panics if `nr` is `0`.
2526
#[unstable(feature = "sgx_platform", issue = "56975")]
26-
pub unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) {
27-
if nr==0 { panic!("Invalid usercall number {}",nr) }
28-
let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4);
27+
#[inline]
28+
pub unsafe fn do_usercall(nr: NonZeroU64, p1: u64, p2: u64, p3: u64, p4: u64, abort: bool)
29+
-> (u64, u64)
30+
{
31+
let UsercallReturn(a, b) = usercall(nr, p1, p2, abort as _, p3, p4);
2932
(a, b)
3033
}
3134

@@ -41,7 +44,6 @@ trait ReturnValue {
4144
}
4245

4346
macro_rules! define_usercalls {
44-
// Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging`
4547
($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
4648
/// Usercall numbers as per the ABI.
4749
#[repr(u64)]
@@ -59,22 +61,6 @@ macro_rules! define_usercalls {
5961
};
6062
}
6163

62-
macro_rules! define_usercalls_asm {
63-
($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
64-
macro_rules! usercalls_asm {
65-
() => {
66-
concat!(
67-
".equ usercall_nr_LAST, 0\n",
68-
$(
69-
".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
70-
".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
71-
),*
72-
)
73-
}
74-
}
75-
};
76-
}
77-
7864
macro_rules! define_ra {
7965
(< $i:ident > $t:ty) => {
8066
impl<$i> RegisterArgument for $t {
@@ -173,74 +159,90 @@ impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
173159
}
174160
}
175161

162+
macro_rules! return_type_is_abort {
163+
(!) => { true };
164+
($r:ty) => { false };
165+
}
166+
167+
// In this macro: using `$r:tt` because `$r:ty` doesn't match ! in `return_type_is_abort`
176168
macro_rules! enclave_usercalls_internal_define_usercalls {
177169
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
178-
$n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
170+
$n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:tt) => (
179171
/// This is the raw function definition, see the ABI documentation for
180172
/// more information.
181173
#[unstable(feature = "sgx_platform", issue = "56975")]
182174
#[inline(always)]
183175
pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
184176
ReturnValue::from_registers(stringify!($f), do_usercall(
185-
Usercalls::$f as Register,
177+
NonZeroU64::new(Usercalls::$f as Register)
178+
.expect("Usercall number must be non-zero"),
186179
RegisterArgument::into_register($n1),
187180
RegisterArgument::into_register($n2),
188181
RegisterArgument::into_register($n3),
189182
RegisterArgument::into_register($n4),
183+
return_type_is_abort!($r)
190184
))
191185
}
192186
);
193-
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
187+
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:tt) => (
194188
/// This is the raw function definition, see the ABI documentation for
195189
/// more information.
196190
#[unstable(feature = "sgx_platform", issue = "56975")]
197191
#[inline(always)]
198192
pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
199193
ReturnValue::from_registers(stringify!($f), do_usercall(
200-
Usercalls::$f as Register,
194+
NonZeroU64::new(Usercalls::$f as Register)
195+
.expect("Usercall number must be non-zero"),
201196
RegisterArgument::into_register($n1),
202197
RegisterArgument::into_register($n2),
203198
RegisterArgument::into_register($n3),
204-
0
199+
0,
200+
return_type_is_abort!($r)
205201
))
206202
}
207203
);
208-
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
204+
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:tt) => (
209205
/// This is the raw function definition, see the ABI documentation for
210206
/// more information.
211207
#[unstable(feature = "sgx_platform", issue = "56975")]
212208
#[inline(always)]
213209
pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
214210
ReturnValue::from_registers(stringify!($f), do_usercall(
215-
Usercalls::$f as Register,
211+
NonZeroU64::new(Usercalls::$f as Register)
212+
.expect("Usercall number must be non-zero"),
216213
RegisterArgument::into_register($n1),
217214
RegisterArgument::into_register($n2),
218-
0,0
215+
0,0,
216+
return_type_is_abort!($r)
219217
))
220218
}
221219
);
222-
(def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
220+
(def fn $f:ident($n1:ident: $t1:ty) -> $r:tt) => (
223221
/// This is the raw function definition, see the ABI documentation for
224222
/// more information.
225223
#[unstable(feature = "sgx_platform", issue = "56975")]
226224
#[inline(always)]
227225
pub unsafe fn $f($n1: $t1) -> $r {
228226
ReturnValue::from_registers(stringify!($f), do_usercall(
229-
Usercalls::$f as Register,
227+
NonZeroU64::new(Usercalls::$f as Register)
228+
.expect("Usercall number must be non-zero"),
230229
RegisterArgument::into_register($n1),
231-
0,0,0
230+
0,0,0,
231+
return_type_is_abort!($r)
232232
))
233233
}
234234
);
235-
(def fn $f:ident() -> $r:ty) => (
235+
(def fn $f:ident() -> $r:tt) => (
236236
/// This is the raw function definition, see the ABI documentation for
237237
/// more information.
238238
#[unstable(feature = "sgx_platform", issue = "56975")]
239239
#[inline(always)]
240240
pub unsafe fn $f() -> $r {
241241
ReturnValue::from_registers(stringify!($f), do_usercall(
242-
Usercalls::$f as Register,
243-
0,0,0,0
242+
NonZeroU64::new(Usercalls::$f as Register)
243+
.expect("Usercall number must be non-zero"),
244+
0,0,0,0,
245+
return_type_is_abort!($r)
244246
))
245247
}
246248
);
@@ -250,4 +252,3 @@ macro_rules! enclave_usercalls_internal_define_usercalls {
250252
}
251253

252254
invoke_with_usercalls!(define_usercalls);
253-
invoke_with_usercalls!(define_usercalls_asm);

src/libstd/sys/sgx/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
125125
}
126126

127127
pub unsafe fn abort_internal() -> ! {
128-
abi::panic::usercall_exit(true)
128+
abi::usercalls::exit(true)
129129
}
130130

131131
pub fn hashmap_random_keys() -> (u64, u64) {

0 commit comments

Comments
 (0)