SGX target: improve panic & exit handling

This commit is contained in:
Jethro Beekman 2019-01-29 17:10:22 +05:30
parent 5f60208ba1
commit a75ae00c63
4 changed files with 32 additions and 22 deletions

View File

@ -66,7 +66,7 @@ IMAGE_BASE:
globvar EH_FRM_HDR_SIZE 8 globvar EH_FRM_HDR_SIZE 8
.Lreentry_panic_msg: .Lreentry_panic_msg:
.asciz "Re-entered panicked enclave!" .asciz "Re-entered aborted enclave!"
.Lreentry_panic_msg_end: .Lreentry_panic_msg_end:
.Lusercall_panic_msg: .Lusercall_panic_msg:
@ -80,7 +80,7 @@ IMAGE_BASE:
.org .+48 /* reserved bits */ .org .+48 /* reserved bits */
.data .data
.Lpanicked: .Laborted:
.byte 0 .byte 0
/* TCS local storage section */ /* TCS local storage section */
@ -134,6 +134,9 @@ sgx_entry:
jz .Lskip_debug_init jz .Lskip_debug_init
mov %r10,%gs:tcsls_debug_panic_buf_ptr mov %r10,%gs:tcsls_debug_panic_buf_ptr
.Lskip_debug_init: .Lskip_debug_init:
/* check for abort */
bt $0,.Laborted(%rip)
jc .Lreentry_panic
/* check if returning from usercall */ /* check if returning from usercall */
mov %gs:tcsls_last_rsp,%r11 mov %gs:tcsls_last_rsp,%r11
test %r11,%r11 test %r11,%r11
@ -164,9 +167,6 @@ sgx_entry:
mov %r14,%r8 mov %r14,%r8
mov %r15,%r9 mov %r15,%r9
.Lskip_init: .Lskip_init:
/* check for panic */
bt $0,.Lpanicked(%rip)
jc .Lreentry_panic
/* call into main entry point */ /* call into main entry point */
load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */ load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */
call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */ call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */
@ -237,18 +237,18 @@ sgx_entry:
stmxcsr (%rsp) stmxcsr (%rsp)
.endm .endm
.global panic_exit .global usercall_exit
panic_exit: usercall_exit:
/* save registers in DEBUG mode, so that debugger can reconstruct the stack */ /* save registers in DEBUG mode, so that debugger can reconstruct the stack */
testb $0xff,DEBUG(%rip) testb $0xff,DEBUG(%rip)
jz .Lskip_save_registers jz .Lskip_save_registers
push_callee_saved_registers push_callee_saved_registers
movq %rsp,%gs:tcsls_panic_last_rsp movq %rsp,%gs:tcsls_panic_last_rsp
.Lskip_save_registers: .Lskip_save_registers:
/* set panicked bit */ /* set aborted bit */
movb $1,.Lpanicked(%rip) movb $1,.Laborted(%rip)
/* call usercall exit(true) */ /* call usercall exit(true) */
mov $1,%esi /* RSI = usercall() argument: panic = true */ /* NOP: mov %rsi,%rsi */ /* RSI = usercall() argument: panic */
xor %rdx,%rdx /* RDX cleared */ xor %rdx,%rdx /* RDX cleared */
movq $usercall_nr_exit,%rdi /* RDI = usercall exit */ movq $usercall_nr_exit,%rdi /* RDI = usercall exit */
jmp .Lexit jmp .Lexit

View File

@ -1,12 +1,18 @@
use super::usercalls::alloc::UserRef;
use cmp;
use io::{self, Write}; use io::{self, Write};
use slice::from_raw_parts_mut; use mem;
extern "C" { extern "C" {
fn take_debug_panic_buf_ptr() -> *mut u8; fn take_debug_panic_buf_ptr() -> *mut u8;
static DEBUG: u8; static DEBUG: u8;
} }
pub(crate) struct SgxPanicOutput(Option<&'static mut [u8]>); pub(crate) struct SgxPanicOutput(Option<&'static mut UserRef<[u8]>>);
fn empty_user_slice() -> &'static mut UserRef<[u8]> {
unsafe { UserRef::from_raw_parts_mut(1 as *mut u8, 0) }
}
impl SgxPanicOutput { impl SgxPanicOutput {
pub(crate) fn new() -> Option<Self> { pub(crate) fn new() -> Option<Self> {
@ -17,32 +23,36 @@ impl SgxPanicOutput {
} }
} }
fn init(&mut self) -> &mut &'static mut [u8] { fn init(&mut self) -> &mut &'static mut UserRef<[u8]> {
self.0.get_or_insert_with(|| unsafe { self.0.get_or_insert_with(|| unsafe {
let ptr = take_debug_panic_buf_ptr(); let ptr = take_debug_panic_buf_ptr();
if ptr.is_null() { if ptr.is_null() {
&mut [] empty_user_slice()
} else { } else {
from_raw_parts_mut(ptr, 1024) UserRef::from_raw_parts_mut(ptr, 1024)
} }
}) })
} }
} }
impl Write for SgxPanicOutput { impl Write for SgxPanicOutput {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { fn write(&mut self, src: &[u8]) -> io::Result<usize> {
self.init().write(buf) let dst = mem::replace(self.init(), empty_user_slice());
let written = cmp::min(src.len(), dst.len());
dst[..written].copy_from_enclave(&src[..written]);
self.0 = Some(&mut dst[written..]);
Ok(written)
} }
fn flush(&mut self) -> io::Result<()> { fn flush(&mut self) -> io::Result<()> {
self.init().flush() Ok(())
} }
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn panic_msg(msg: &str) -> ! { pub extern "C" fn panic_msg(msg: &str) -> ! {
let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes())); let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
unsafe { panic_exit(); } unsafe { usercall_exit(true); }
} }
extern "C" { pub fn panic_exit() -> !; } extern "C" { pub fn usercall_exit(panic: bool) -> !; }

View File

@ -119,7 +119,7 @@ pub unsafe fn launch_thread() -> IoResult<()> {
/// Usercall `exit`. See the ABI documentation for more information. /// Usercall `exit`. See the ABI documentation for more information.
#[unstable(feature = "sgx_platform", issue = "56975")] #[unstable(feature = "sgx_platform", issue = "56975")]
pub fn exit(panic: bool) -> ! { pub fn exit(panic: bool) -> ! {
unsafe { raw::exit(panic) } unsafe { super::panic::usercall_exit(panic) }
} }
/// Usercall `wait`. See the ABI documentation for more information. /// Usercall `wait`. See the ABI documentation for more information.

View File

@ -125,7 +125,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
} }
pub unsafe fn abort_internal() -> ! { pub unsafe fn abort_internal() -> ! {
abi::panic::panic_exit() abi::panic::usercall_exit(true)
} }
pub fn hashmap_random_keys() -> (u64, u64) { pub fn hashmap_random_keys() -> (u64, u64) {