From 27ff72008c8bf1871eb9dc402bdf2852a5f7094d Mon Sep 17 00:00:00 2001 From: Jo Van Bulck Date: Thu, 11 Apr 2024 17:26:39 +0000 Subject: [PATCH] app/memcmp: support simulation mode via rflags.tf --- app/memcmp/main.c | 96 ++++++++++++++++++++++++++++++-------------- libsgxstep/cpu.h | 6 +++ libsgxstep/enclave.c | 1 + 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/app/memcmp/main.c b/app/memcmp/main.c index d456f2c..82063e7 100644 --- a/app/memcmp/main.c +++ b/app/memcmp/main.c @@ -3,6 +3,7 @@ #include #include #include "libsgxstep/apic.h" +#include "libsgxstep/cpu.h" #include "libsgxstep/pt.h" #include "libsgxstep/sched.h" #include "libsgxstep/enclave.h" @@ -14,10 +15,23 @@ #include #define MAX_LEN 15 -#define DO_STEP 1 +#define DO_TIMER_STEP 1 #define DEBUG 0 #define DBG_ENCL 1 -#define ANIMATION_DELAY 50000000 +#if DO_TIMER_STEP + #define ANIMATION_DELAY 50000000 +#else + #define ANIMATION_DELAY 5000 +#endif + +/* + * NOTE: set DO_TIMER_STEP=0 to _simulate_ a single-stepping attack through the + * x86 hardware trap flag (RFLAGS.TF). Use for demonstration/debugging purposes + * only, as this does _not_ work for SGX debug enclaves(!) + */ +#if !DO_TIMER_STEP + #warning "Using simulated stepping through HW trap flag; will not work for production enclaves!" +#endif sgx_enclave_id_t eid = 0; int irq_cnt = 0, do_irq = 0, fault_cnt = 0, trigger_cnt = 0, step_cnt = 0; @@ -29,6 +43,10 @@ void *code_adrs, *trigger_adrs; /* Called before resuming the enclave after an Asynchronous Enclave eXit. */ void aep_cb_func(void) { + #if !DO_TIMER_STEP + DISABLE_TF; + #endif + #if DEBUG uint64_t erip = edbgrd_erip() - (uint64_t) get_enclave_base(); info("^^ enclave RIP=%#llx; ACCESSED=%d", erip, ACCESSED(*pte_encl)); @@ -69,64 +87,67 @@ void aep_cb_func(void) * enclave instruction. * */ -#if DO_STEP if (do_irq) { *pmd_encl = MARK_NOT_ACCESSED( *pmd_encl ); +#if DO_TIMER_STEP apic_timer_irq( SGX_STEP_TIMER_INTERVAL ); - } +#else + ENABLE_TF; #endif + } } /* Called upon SIGSEGV caused by untrusted page tables. */ void fault_handler(int signo, siginfo_t * si, void *ctx) { - ASSERT(fault_cnt++ < 10); - switch ( signo ) { case SIGSEGV: + ASSERT(fault_cnt++ < 10); + #if DEBUG info("Caught page fault (base address=%p)", si->si_addr); #endif + + if (si->si_addr == trigger_adrs) + { + #if DEBUG + info("Restoring trigger access rights.."); + #endif + ASSERT(!mprotect(trigger_adrs, 4096, PROT_READ | PROT_WRITE)); + do_irq = 1; + } + else + { + info("Unknown #PF address!"); + } + + break; + + #if !DO_TIMER_STEP + case SIGTRAP: + #if DEBUG + //info("Caught single-step trap (RIP=%p)\n", si->si_addr); + #endif break; + #endif default: info("Caught unknown signal '%d'", signo); abort(); } - if (si->si_addr == trigger_adrs) - { - #if DEBUG - info("Restoring trigger access rights.."); - #endif - ASSERT(!mprotect(trigger_adrs, 4096, PROT_READ | PROT_WRITE)); - do_irq = 1; - } - else - { - info("Unknown #PF address!"); - } - // NOTE: return eventually continues at aep_cb_func and initiates // single-stepping mode. } /* ================== ATTACKER INIT/SETUP ================= */ -/* Configure and check attacker untrusted runtime environment. */ -void attacker_config_runtime(void) +void register_signal_handler(int signo) { struct sigaction act, old_act; - ASSERT( !claim_cpu(VICTIM_CPU) ); - ASSERT( !prepare_system_for_benchmark(PSTATE_PCT) ); - //print_system_settings(); - - register_enclave_info(); - print_enclave_info(); - /* Specify #PF handler with signinfo arguments */ memset(&act, sizeof(sigaction), 0); act.sa_sigaction = fault_handler; @@ -134,7 +155,19 @@ void attacker_config_runtime(void) /* Block all signals while the signal is being handled */ sigfillset(&act.sa_mask); - ASSERT(!sigaction( SIGSEGV, &act, &old_act )); + ASSERT(!sigaction( signo, &act, &old_act )); +} + +/* Configure and check attacker untrusted runtime environment. */ +void attacker_config_runtime(void) +{ + ASSERT( !claim_cpu(VICTIM_CPU) ); + ASSERT( !prepare_system_for_benchmark(PSTATE_PCT) ); + //print_system_settings(); + + register_enclave_info(); + print_enclave_info(); + register_signal_handler( SIGSEGV ); } /* Provoke page fault on enclave entry to initiate single-stepping mode. */ @@ -184,11 +217,14 @@ int main( int argc, char **argv ) attacker_config_page_table(); register_aep_cb(aep_cb_func); -#if DO_STEP +#if DO_TIMER_STEP info_event("Establishing user-space APIC/IDT mappings"); map_idt(&idt); install_kernel_irq_handler(&idt, __ss_irq_handler, IRQ_VECTOR); apic_timer_oneshot(IRQ_VECTOR); +#else + register_signal_handler( SIGTRAP ); + set_debug_optin(); #endif /* 2. Single-step enclaved execution. */ diff --git a/libsgxstep/cpu.h b/libsgxstep/cpu.h index 9c14470..5650512 100644 --- a/libsgxstep/cpu.h +++ b/libsgxstep/cpu.h @@ -26,6 +26,12 @@ #define IA32_APIC_BASE_MSR 0x1b #define IA32_TSC_DEADLINE_MSR 0x6e0 +#define ENABLE_TF \ + __asm__ volatile ("pushf\norl $0x100, (%rsp)\npopf\n") + +#define DISABLE_TF \ + __asm__ volatile ("pushf\nandl $0xfffffeff, (%rsp)\npopf\n") + uint64_t rdtsc_begin( void ); uint64_t rdtsc_end( void ); uint64_t read_flags(void); diff --git a/libsgxstep/enclave.c b/libsgxstep/enclave.c index 6726862..fb33d43 100644 --- a/libsgxstep/enclave.c +++ b/libsgxstep/enclave.c @@ -110,6 +110,7 @@ void register_enclave_info(void) victim.tcs = (uint64_t) sgx_get_tcs(); victim.aep = (uint64_t) sgx_get_aep(); + info("tcs at %lx; aep at %lx", victim.tcs, victim.aep); ASSERT( victim.tcs >= victim.base && victim.tcs < victim.limit); ioctl_init = 1; }