diff --git a/deps/rust-sgx-sdk.patch b/deps/rust-sgx-sdk.patch index db0d9c52..da1a036e 100644 --- a/deps/rust-sgx-sdk.patch +++ b/deps/rust-sgx-sdk.patch @@ -1,3 +1,17 @@ +From ba4147e76c7cfe17f843b7b28bf535d04bc5db77 Mon Sep 17 00:00:00 2001 +From: "Tate, Hongliang Tian" +Date: Wed, 3 Jun 2020 08:11:35 +0000 +Subject: [PATCH 1/3] Add support for integrity-only SGX files + +--- + samplecode/unit-test/enclave/src/lib.rs | 2 + + samplecode/unit-test/enclave/src/test_file.rs | 41 +++++++++ + sgx_tprotected_fs/src/fs.rs | 84 +++++++++++++++++++ + sgx_tstd/src/sgxfs.rs | 39 ++++++++- + sgx_tstd/src/sys/sgxfs.rs | 38 +++++++-- + sgx_types/src/function.rs | 6 +- + 6 files changed, 203 insertions(+), 7 deletions(-) + diff --git a/samplecode/unit-test/enclave/src/lib.rs b/samplecode/unit-test/enclave/src/lib.rs index b9ea49be..d740753f 100644 --- a/samplecode/unit-test/enclave/src/lib.rs @@ -356,3 +370,78 @@ index 3c2db3a4..f96cd9e8 100644 } /* intel sgx sdk 2.0 */ +-- +2.17.1 + + +From 982897c432dd98c6d63691ddb238acd29db4233f Mon Sep 17 00:00:00 2001 +From: "Tate, Hongliang Tian" +Date: Wed, 3 Jun 2020 08:35:53 +0000 +Subject: [PATCH 2/3] Add data structures for #PF and #GP exceptions + +--- + sgx_types/src/types.rs | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sgx_types/src/types.rs b/sgx_types/src/types.rs +index 4f191364..651d088e 100644 +--- a/sgx_types/src/types.rs ++++ b/sgx_types/src/types.rs +@@ -865,6 +865,8 @@ impl_enum! { + SGX_EXCEPTION_VECTOR_BP = 3, /* INT 3 instruction */ + SGX_EXCEPTION_VECTOR_BR = 5, /* BOUND instruction */ + SGX_EXCEPTION_VECTOR_UD = 6, /* UD2 instruction or reserved opcode */ ++ SGX_EXCEPTION_VECTOR_GP = 13, /* General protection */ ++ SGX_EXCEPTION_VECTOR_PF = 14, /* Page fault */ + SGX_EXCEPTION_VECTOR_MF = 16, /* x87 FPU floating-point or WAIT/FWAIT instruction */ + SGX_EXCEPTION_VECTOR_AC = 17, /* Any data reference in memory */ + SGX_EXCEPTION_VECTOR_XM = 19, /* SSE/SSE2/SSE3 floating-point instruction */ +@@ -922,11 +924,20 @@ cfg_if! { + } + } + ++impl_struct! { ++ pub struct sgx_exinfo_t { ++ pub maddr: u64, ++ pub errcd: u32, ++ pub _unused: u32, ++ } ++} ++ + impl_struct! { + pub struct sgx_exception_info_t { + pub cpu_context: sgx_cpu_context_t, + pub exception_vector: sgx_exception_vector_t, + pub exception_type: sgx_exception_type_t, ++ pub exinfo: sgx_exinfo_t, + } + } + +-- +2.17.1 + + +From 43b32d82c09a796fd52b954dc0217ac9ce01c559 Mon Sep 17 00:00:00 2001 +From: "Tate, Hongliang Tian" +Date: Wed, 3 Jun 2020 08:37:47 +0000 +Subject: [PATCH 3/3] Add a new exception type: simulated + +--- + sgx_types/src/types.rs | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sgx_types/src/types.rs b/sgx_types/src/types.rs +index 651d088e..ef43d7d6 100644 +--- a/sgx_types/src/types.rs ++++ b/sgx_types/src/types.rs +@@ -879,6 +879,7 @@ impl_enum!{ + pub enum sgx_exception_type_t { + SGX_EXCEPTION_HARDWARE = 3, + SGX_EXCEPTION_SOFTWARE = 6, ++ SGX_EXCEPTION_SIMULATED = 7, + } + } + +-- +2.17.1 + diff --git a/src/libos/Cargo.toml b/src/libos/Cargo.toml index 3fc7382a..7f770d72 100644 --- a/src/libos/Cargo.toml +++ b/src/libos/Cargo.toml @@ -24,10 +24,11 @@ serde_json = { path = "../../deps/serde-json-sgx" } sgx_tstd = { path = "../../deps/rust-sgx-sdk/sgx_tstd" } [features] -default = ["integrity_only_opt", "sgx_file_cache"] +default = ["integrity_only_opt", "sgx_file_cache", "sgx1_exception_sim"] syscall_timing = [] # Timing for each syscall. But it has cost from more ocall. integrity_only_opt = [] # Clear bss only. It should be disabled if checking memory reads. sgx_file_cache = [] # Cache SgxFile objects. Invalidation is unimplemented. +sgx1_exception_sim = [] # Simulate #PF and #GP exceptions on SGX 1 [target.'cfg(not(target_env = "sgx"))'.dependencies] xmas-elf = { path = "../../deps/xmas-elf" } diff --git a/src/libos/src/exception/mod.rs b/src/libos/src/exception/mod.rs index 544bd75f..830a1df9 100644 --- a/src/libos/src/exception/mod.rs +++ b/src/libos/src/exception/mod.rs @@ -37,9 +37,7 @@ pub fn do_handle_exception( user_context: *mut CpuContext, ) -> Result { let info = unsafe { &mut *info }; - if info.exception_type != sgx_exception_type_t::SGX_EXCEPTION_HARDWARE { - return_errno!(EINVAL, "Can only handle hardware exceptions"); - } + check_exception_type(info.exception_type)?; let user_context = unsafe { &mut *user_context }; *user_context = CpuContext::from_sgx(&info.cpu_context); @@ -72,3 +70,32 @@ pub fn do_handle_exception( Ok(0) } + +// Notes about #PF and #GP exception simulation for SGX 1. +// +// SGX 1 cannot capture #PF and #GP exceptions inside enclaves. This leaves us +// no choice but to rely on untrusted info about #PF or #PG exceptions from +// outside the enclave. Due to the obvious security risk, the feature can be +// disabled. +// +// On the bright side, SGX 2 has native support for #PF and #GP exceptions. So +// this exception simulation and its security risk is not a problem in the long +// run. + +#[cfg(not(feature = "sgx1_exception_sim"))] +fn check_exception_type(type_: sgx_exception_type_t) -> Result<()> { + if type_ != sgx_exception_type_t::SGX_EXCEPTION_HARDWARE { + return_errno!(EINVAL, "Can only handle hardware exceptions"); + } + Ok(()) +} + +#[cfg(feature = "sgx1_exception_sim")] +fn check_exception_type(type_: sgx_exception_type_t) -> Result<()> { + if type_ != sgx_exception_type_t::SGX_EXCEPTION_HARDWARE + && type_ != sgx_exception_type_t::SGX_EXCEPTION_SIMULATED + { + return_errno!(EINVAL, "Can only handle hardware / simulated exceptions"); + } + Ok(()) +} diff --git a/src/libos/src/signal/signals/fault.rs b/src/libos/src/signal/signals/fault.rs index 25d945dc..171676ce 100644 --- a/src/libos/src/signal/signals/fault.rs +++ b/src/libos/src/signal/signals/fault.rs @@ -7,33 +7,52 @@ use crate::prelude::*; pub struct FaultSignal { num: SigNum, code: i32, + addr: Option, } impl FaultSignal { pub fn new(info: &sgx_exception_info_t) -> Self { - // FIXME: the following mapping from exception to signal is not accurate. + // TODO: the current mapping from exceptinon to signal is only a first + // order approximation. The resulting signum or siginfo may not be + // idential to Linux's behavior. use sgx_exception_vector_t::*; - let (num, code) = match info.exception_vector { + let (num, code, addr) = match info.exception_vector { // Divider exception - SGX_EXCEPTION_VECTOR_DE => (SIGFPE, FPE_INTDIV), + SGX_EXCEPTION_VECTOR_DE => (SIGFPE, FPE_INTDIV, None), // Floating-point exception SGX_EXCEPTION_VECTOR_MF | // SIMD floating-point exception - SGX_EXCEPTION_VECTOR_XM => (SIGFPE, FPE_FLTDIV), + SGX_EXCEPTION_VECTOR_XM => (SIGFPE, FPE_FLTDIV, None), // Invalid opcode exception SGX_EXCEPTION_VECTOR_UD | // Debug exception: should not occur in enclave; treat is as #UD SGX_EXCEPTION_VECTOR_DB | // Break point exception: should not occur in enclave; treat is as #UD - SGX_EXCEPTION_VECTOR_BP => (SIGILL, ILL_ILLOPC), + SGX_EXCEPTION_VECTOR_BP => (SIGILL, ILL_ILLOPC, None), // Bound range exception - SGX_EXCEPTION_VECTOR_BR => (SIGSEGV, SEGV_BNDERR), + SGX_EXCEPTION_VECTOR_BR => (SIGSEGV, SEGV_BNDERR, None), // Alignment check exception - SGX_EXCEPTION_VECTOR_AC => (SIGBUS, BUS_ADRALN), - // TODO: handle page fault and general protection exceptions - _ => panic!("illegal exception: cannot be converted to signal"), + SGX_EXCEPTION_VECTOR_AC => (SIGBUS, BUS_ADRALN, None), + // Page fault exception + SGX_EXCEPTION_VECTOR_PF => { + const PF_ERR_FLAG_PRESENT : u32 = 1u32 << 0; + let code = if info.exinfo.errcd & PF_ERR_FLAG_PRESENT != 0 { + SEGV_ACCERR + } else { + SEGV_MAPERR + }; + let addr = Some(info.exinfo.maddr); + (SIGSEGV, code, addr) + }, + // General protection exception + SGX_EXCEPTION_VECTOR_PF => (SIGBUS, BUS_ADRERR, None), + _ => panic!("exception cannot be converted to signal"), }; - Self { num, code } + Self { num, code, addr } + } + + pub fn addr(&self) -> Option { + self.addr } } @@ -43,8 +62,8 @@ impl Signal for FaultSignal { } fn to_info(&self) -> siginfo_t { - let info = siginfo_t::new(self.num, self.code); - // TODO: set info.si_addr + let mut info = siginfo_t::new(self.num, self.code); + info.set_si_addr(self.addr.unwrap_or_default() as *const c_void); info } } diff --git a/test/signal/main.c b/test/signal/main.c index 4b1825d3..fc987e43 100644 --- a/test/signal/main.c +++ b/test/signal/main.c @@ -228,7 +228,7 @@ int div_maybe_zero(int x, int y) { return x / y; } -int test_catch_fault() { +int test_handle_sigfpe() { #ifdef SGX_MODE_SIM printf("WARNING: Skip this test case as we do not support " "capturing hardware exception in SGX simulation mode\n"); @@ -261,6 +261,56 @@ int test_catch_fault() { #endif /* SGX_MODE_SIM */ } + +// TODO: rewrite this in assembly +int read_maybe_null(int *p) { + return *p; +} + +static void handle_sigsegv(int num, siginfo_t *info, void *_context) { + printf("SIGSEGV Caught\n"); + assert(num == SIGSEGV); + assert(info->si_signo == SIGSEGV); + + ucontext_t *ucontext = _context; + mcontext_t *mcontext = &ucontext->uc_mcontext; + // TODO: how long is the instruction? + // The faulty instruction should be `idiv %esi` (f7 fe) + mcontext->gregs[REG_RIP] += 2; + + return; +} + + +int test_handle_sigsegv() { +#ifdef SGX_MODE_SIM + printf("WARNING: Skip this test case as we do not support " + "capturing hardware exception in SGX simulation mode\n"); + return 0; +#else + // Set up a signal handler that handles divide-by-zero exception + struct sigaction new_action, old_action; + new_action.sa_sigaction = handle_sigsegv; + new_action.sa_flags = SA_SIGINFO; + if (sigaction(SIGSEGV, &new_action, &old_action) < 0) { + THROW_ERROR("registering new signal handler failed"); + } + if (old_action.sa_handler != SIG_DFL) { + THROW_ERROR("unexpected old sig handler"); + } + + int *addr = NULL; + volatile int val = read_maybe_null(addr); + + printf("Signal handler successfully jumped over a null-dereferencing instruction\n"); + + if (sigaction(SIGSEGV, &old_action, NULL) < 0) { + THROW_ERROR("restoring old signal handler failed"); + } + return 0; +#endif /* SGX_MODE_SIM */ +} + // ============================================================================ // Test handle signal on alternate signal stack // ============================================================================ @@ -364,7 +414,8 @@ static test_case_t test_cases[] = { TEST_CASE(test_raise), TEST_CASE(test_abort), TEST_CASE(test_kill), - TEST_CASE(test_catch_fault), + TEST_CASE(test_handle_sigfpe), + TEST_CASE(test_handle_sigsegv), TEST_CASE(test_sigaltstack), TEST_CASE(test_sigchld), };