riscv: handle page faults in the unmappable region
When handling a kernel page fault, check explicitly that stval resides in either the user or kernel address spaces, and make the page fault fatal if not. Otherwise, a properly crafted address may appear to pmap_fault() as a valid and present page in the kernel map, causing the page fault to be retried continuously. This is mainly due to the fact that the upper bits of virtual addresses are not validated by most of the pmap code. Faults of this nature should only occur due to some kind of bug in the kernel, but it is best to handle them gracefully when they do. Handle user page faults in the same way, sending a SIGSEGV immediately when a malformed address is encountered. Add an assertion to pmap_l1(), which should help catch other bugs of this kind that make it this far. Reviewed by: jrtc27, markj MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D31208
This commit is contained in:
parent
76c2e71c4c
commit
4a9f2f8b07
@ -186,6 +186,10 @@
|
||||
#define VM_MINUSER_ADDRESS (VM_MIN_USER_ADDRESS)
|
||||
#define VM_MAXUSER_ADDRESS (VM_MAX_USER_ADDRESS)
|
||||
|
||||
/* Check if an address resides in a mappable region. */
|
||||
#define VIRT_IS_VALID(va) \
|
||||
(((va) < VM_MAX_USER_ADDRESS) || ((va) >= VM_MIN_KERNEL_ADDRESS))
|
||||
|
||||
#define KERNBASE (VM_MIN_KERNEL_ADDRESS)
|
||||
#define SHAREDPAGE (VM_MAXUSER_ADDRESS - PAGE_SIZE)
|
||||
#define USRSTACK SHAREDPAGE
|
||||
|
@ -351,6 +351,8 @@ static __inline pd_entry_t *
|
||||
pmap_l1(pmap_t pmap, vm_offset_t va)
|
||||
{
|
||||
|
||||
KASSERT(VIRT_IS_VALID(va),
|
||||
("%s: malformed virtual address %#lx", __func__, va));
|
||||
return (&pmap->pm_l1[pmap_l1_index(va)]);
|
||||
}
|
||||
|
||||
|
@ -200,6 +200,11 @@ page_fault_handler(struct trapframe *frame, int usermode)
|
||||
goto fatal;
|
||||
|
||||
if (usermode) {
|
||||
if (!VIRT_IS_VALID(stval)) {
|
||||
call_trapsignal(td, SIGSEGV, SEGV_MAPERR, (void *)stval,
|
||||
frame->tf_scause & SCAUSE_CODE);
|
||||
goto done;
|
||||
}
|
||||
map = &td->td_proc->p_vmspace->vm_map;
|
||||
} else {
|
||||
/*
|
||||
@ -208,6 +213,9 @@ page_fault_handler(struct trapframe *frame, int usermode)
|
||||
*/
|
||||
intr_enable();
|
||||
|
||||
if (!VIRT_IS_VALID(stval))
|
||||
goto fatal;
|
||||
|
||||
if (stval >= VM_MAX_USER_ADDRESS) {
|
||||
map = kernel_map;
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user