Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/amd64/trap.c
Show First 20 Lines • Show All 802 Lines • ▼ Show 20 Lines | trap_pfault(struct trapframe *frame, int usermode) | ||||
* If the trap was caused by errant bits in the PTE then panic. | * If the trap was caused by errant bits in the PTE then panic. | ||||
*/ | */ | ||||
if (frame->tf_err & PGEX_RSV) { | if (frame->tf_err & PGEX_RSV) { | ||||
trap_fatal(frame, eva); | trap_fatal(frame, eva); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
/* | /* | ||||
* User-mode protection key violation (PKU). May happen | |||||
* either from usermode or from kernel if copyin accessed | |||||
* key-protected mapping. | |||||
*/ | |||||
if ((frame->tf_err & PGEX_PK) != 0) { | |||||
markj: Should we have a dedicated ucode for this case? | |||||
Done Inline ActionsI do not have an opinion there. After all, it is page protection. Not adding MD code might be good. kib: I do not have an opinion there. After all, it is page protection. Not adding MD code might be… | |||||
if (eva > VM_MAXUSER_ADDRESS) { | |||||
trap_fatal(frame, eva); | |||||
return (-1); | |||||
} | |||||
rv = KERN_PROTECTION_FAILURE; | |||||
goto after_vmfault; | |||||
} | |||||
/* | |||||
* If nx protection of the usermode portion of kernel page | * If nx protection of the usermode portion of kernel page | ||||
* tables caused trap, panic. | * tables caused trap, panic. | ||||
*/ | */ | ||||
if (usermode && trap_is_pti(frame)) | if (usermode && trap_is_pti(frame)) | ||||
panic("PTI: pid %d comm %s tf_err %#lx", p->p_pid, | panic("PTI: pid %d comm %s tf_err %#lx", p->p_pid, | ||||
p->p_comm, frame->tf_err); | p->p_comm, frame->tf_err); | ||||
/* | /* | ||||
Show All 18 Lines | if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) { | ||||
frame); | frame); | ||||
else | else | ||||
PMC_SOFT_CALL_TF( , , page_fault, write, | PMC_SOFT_CALL_TF( , , page_fault, write, | ||||
frame); | frame); | ||||
} | } | ||||
#endif | #endif | ||||
return (0); | return (0); | ||||
} | } | ||||
after_vmfault: | |||||
if (!usermode) { | if (!usermode) { | ||||
Done Inline ActionsWhat if a user application triggers a kernel mode protection key violation with copyin/out? markj: What if a user application triggers a kernel mode protection key violation with copyin/out? | |||||
Done Inline ActionsSuch access must only occur with pcb_onfault set to non-NULL, and then the condition below would jump to the handler after return from the fault. If kernel is tricked to access usermode without pcb_onfault, then we panic as should. kib: Such access must only occur with pcb_onfault set to non-NULL, and then the condition below… | |||||
Done Inline ActionsOops, right. markj: Oops, right. | |||||
if (td->td_intr_nesting_level == 0 && | if (td->td_intr_nesting_level == 0 && | ||||
curpcb->pcb_onfault != NULL) { | curpcb->pcb_onfault != NULL) { | ||||
frame->tf_rip = (long)curpcb->pcb_onfault; | frame->tf_rip = (long)curpcb->pcb_onfault; | ||||
return (0); | return (0); | ||||
} | } | ||||
trap_fatal(frame, eva); | trap_fatal(frame, eva); | ||||
return (-1); | return (-1); | ||||
} | } | ||||
Show All 26 Lines | printf("\n\nFatal trap %d: %s while in %s mode\n", type, msg, | ||||
TRAPF_USERMODE(frame) ? "user" : "kernel"); | TRAPF_USERMODE(frame) ? "user" : "kernel"); | ||||
#ifdef SMP | #ifdef SMP | ||||
/* two separate prints in case of a trap on an unmapped page */ | /* two separate prints in case of a trap on an unmapped page */ | ||||
printf("cpuid = %d; ", PCPU_GET(cpuid)); | printf("cpuid = %d; ", PCPU_GET(cpuid)); | ||||
printf("apic id = %02x\n", PCPU_GET(apic_id)); | printf("apic id = %02x\n", PCPU_GET(apic_id)); | ||||
#endif | #endif | ||||
if (type == T_PAGEFLT) { | if (type == T_PAGEFLT) { | ||||
printf("fault virtual address = 0x%lx\n", eva); | printf("fault virtual address = 0x%lx\n", eva); | ||||
printf("fault code = %s %s %s, %s\n", | printf("fault code = %s %s %s%s%s, %s\n", | ||||
code & PGEX_U ? "user" : "supervisor", | code & PGEX_U ? "user" : "supervisor", | ||||
code & PGEX_W ? "write" : "read", | code & PGEX_W ? "write" : "read", | ||||
code & PGEX_I ? "instruction" : "data", | code & PGEX_I ? "instruction" : "data", | ||||
code & PGEX_PK ? " prot key" : " ", | |||||
code & PGEX_SGX ? " SGX" : " ", | |||||
code & PGEX_RSV ? "reserved bits in PTE" : | code & PGEX_RSV ? "reserved bits in PTE" : | ||||
code & PGEX_P ? "protection violation" : "page not present"); | code & PGEX_P ? "protection violation" : "page not present"); | ||||
} | } | ||||
printf("instruction pointer = 0x%lx:0x%lx\n", | printf("instruction pointer = 0x%lx:0x%lx\n", | ||||
frame->tf_cs & 0xffff, frame->tf_rip); | frame->tf_cs & 0xffff, frame->tf_rip); | ||||
ss = frame->tf_ss & 0xffff; | ss = frame->tf_ss & 0xffff; | ||||
printf("stack pointer = 0x%x:0x%lx\n", ss, frame->tf_rsp); | printf("stack pointer = 0x%x:0x%lx\n", ss, frame->tf_rsp); | ||||
printf("frame pointer = 0x%x:0x%lx\n", ss, frame->tf_rbp); | printf("frame pointer = 0x%x:0x%lx\n", ss, frame->tf_rbp); | ||||
▲ Show 20 Lines • Show All 289 Lines • Show Last 20 Lines |
Should we have a dedicated ucode for this case?