diff --git a/machine/minit.c b/machine/minit.c index cee11da..ceae9f0 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -246,6 +246,7 @@ void enter_supervisor_mode(void (*fn)(uintptr_t), uintptr_t arg0, uintptr_t arg1 mstatus = INSERT_FIELD(mstatus, MSTATUS_MPIE, 0); write_csr(mstatus, mstatus); write_csr(mscratch, MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE); + write_csr(menvcfg, MENVCFG_SSE); #ifndef __riscv_flen uintptr_t *p_fcsr = (uintptr_t*)(MACHINE_STACK_TOP() - MENTRY_FRAME_SIZE); // the x0's save slot *p_fcsr = 0; diff --git a/pk/handlers.c b/pk/handlers.c index 2932d94..4946d94 100644 --- a/pk/handlers.c +++ b/pk/handlers.c @@ -99,6 +99,9 @@ static void handle_software_check_fault(trapframe_t* tf) case LANDING_PAD_FAULT: panic("Invalid landing pad!"); break; + case SHADOW_STACK_FAULT: + panic("Shadow stack comparison failed!"); + break; default: panic("Software check fault: unhandled stval: %d", stval); break; diff --git a/pk/mmap.c b/pk/mmap.c index 8f9a281..d554188 100644 --- a/pk/mmap.c +++ b/pk/mmap.c @@ -276,7 +276,7 @@ static inline pte_t prot_to_type(int prot, int user) { pte_t pte = 0; if (prot & PROT_READ) pte |= PTE_R | PTE_A; - if (prot & PROT_WRITE) pte |= PTE_W | PTE_D; + if (prot & PROT_WRITE) pte |= PTE_W | PTE_A | PTE_D; if (prot & PROT_EXEC) pte |= PTE_X | PTE_A; if (pte == 0) pte = PTE_R; if (user) pte |= PTE_U; @@ -327,7 +327,8 @@ static int __handle_page_fault(uintptr_t vaddr, int prot) } pte_t perms = pte_create(0, prot_to_type(prot, 1)); - if ((*pte & perms) != perms) + pte_t pte_perms = *pte | ((*pte & PTE_W) ? PTE_R : 0); // loads to shadow-stack pages are permitted + if ((pte_perms & perms) != perms) return -1; return 0; diff --git a/pk/pk.c b/pk/pk.c index dbfaa5a..64d8d57 100644 --- a/pk/pk.c +++ b/pk/pk.c @@ -13,7 +13,8 @@ elf_info current; long disabled_hart_mask; -bool zicfilp_enabled; +static bool zicfilp_enabled; +static bool zicfiss_enabled; static void help() { @@ -24,6 +25,7 @@ static void help() printk(" -p Disable on-demand program paging\n"); printk(" -s Print cycles upon termination\n"); printk(" --zicfilp Enable Zicfilp CFI mechanism for user program\n"); + printk(" --zicfiss Enable Zicfiss CFI mechanism for user program\n"); shutdown(0); } @@ -61,6 +63,11 @@ static void handle_option(const char* arg) return; } + if (strcmp(arg, "--zicfiss") == 0) { + zicfiss_enabled = true; + return; + } + panic("unrecognized option: `%s'", arg); suggest_help(); } @@ -105,6 +112,16 @@ static void run_loaded_program(size_t argc, char** argv, uintptr_t kstack_top) kassert(stack_bottom != (uintptr_t)-1); current.stack_top = stack_bottom + stack_size; + if (zicfiss_enabled) { + size_t shadow_stack_size = MAX(RISCV_PGSIZE, stack_size >> 5); + size_t shadow_stack_bottom = __do_mmap(stack_bottom - shadow_stack_size, shadow_stack_size, PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0); + kassert(shadow_stack_bottom != (uintptr_t)-1); + size_t shadow_stack_top = shadow_stack_bottom + shadow_stack_size; + + set_csr(senvcfg, SENVCFG_SSE); + write_csr(ssp, shadow_stack_top); + } + // copy phdrs to user stack size_t stack_top = current.stack_top - current.phdr_size; memcpy_to_user((void*)stack_top, (void*)current.phdr, current.phdr_size);