Browse Source

Support CFI shadow stacks via --zicfiss command-line arg

pull/343/head
Andrew Waterman 2 years ago
parent
commit
47a2e87ccd
  1. 1
      machine/minit.c
  2. 3
      pk/handlers.c
  3. 5
      pk/mmap.c
  4. 19
      pk/pk.c

1
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;

3
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;

5
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;

19
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);

Loading…
Cancel
Save