page fault handler: protect thread accesses

current cpu's thread can be NULL during init, we don't want null derefs
in the page fault handler

Change-Id: I0a2c22b39cae2c258d211317cffc2408e19f3bbf
This commit is contained in:
Dominique Martinet
2019-02-06 11:38:39 +09:00
committed by Masamichi Takagi
parent fe08ac4a67
commit f5023c9730
3 changed files with 25 additions and 11 deletions

View File

@ -1563,7 +1563,7 @@ void
unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
{
const uintptr_t address = (uintptr_t)fault_addr;
struct process_vm *vm = thread->vm;
struct process_vm *vm;
struct vm_range *range;
unsigned long irqflags;
unsigned long error = 0;
@ -1578,6 +1578,11 @@ unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
(error & PF_RSVD ? "was" : "wasn't"),
(error & PF_INSTR ? "was" : "wasn't"));
if (!thread)
goto skipvm;
vm = thread->vm;
range = lookup_process_memory_range(vm, address, address+1);
if (range) {
__kprintf("address is in range, flag: 0x%lx\n",
@ -1587,6 +1592,7 @@ unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
__kprintf("address is out of range! \n");
}
skipvm:
kprintf_unlock(irqflags);
/* TODO */

View File

@ -1089,7 +1089,7 @@ void
unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
{
const uintptr_t address = (uintptr_t)fault_addr;
struct process_vm *vm = thread->vm;
struct process_vm *vm;
struct vm_range *range;
unsigned long irqflags;
unsigned long error = ((struct x86_user_context *)regs)->gpr.error;
@ -1104,6 +1104,11 @@ unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
(error & PF_RSVD ? "was" : "wasn't"),
(error & PF_INSTR ? "was" : "wasn't"));
if (!thread)
goto skipvm;
vm = thread->vm;
range = lookup_process_memory_range(vm, address, address+1);
if (range) {
__kprintf("address is in range, flag: 0x%lx\n",
@ -1113,6 +1118,7 @@ unhandled_page_fault(struct thread *thread, void *fault_addr, void *regs)
__kprintf("address is out of range! \n");
}
skipvm:
kprintf_unlock(irqflags);
/* TODO */

View File

@ -1150,7 +1150,7 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
int error;
#ifdef PROFILE_ENABLE
uint64_t t_s = 0;
if (thread->profile)
if (thread && thread->profile)
t_s = rdtsc();
#endif // PROFILE_ENABLE
@ -1163,7 +1163,7 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
cpu_enable_interrupt();
if ((uintptr_t)fault_addr < PAGE_SIZE) {
if ((uintptr_t)fault_addr < PAGE_SIZE || !thread) {
error = -EINVAL;
} else {
error = page_fault_process_vm(thread->vm, fault_addr, reason);
@ -1179,9 +1179,9 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
// no return
}
kprintf("%s fault VM failed for TID: %d, addr: 0x%lx, "
"reason: %d, error: %d\n", __FUNCTION__,
thread->tid, fault_addr, reason, error);
kprintf("%s fault VM failed for TID: %d, addr: 0x%lx, reason: %d, error: %d\n",
__func__, thread ? thread->tid : -1, fault_addr,
reason, error);
unhandled_page_fault(thread, fault_addr, regs);
preempt_enable();
memset(&info, '\0', sizeof info);
@ -1192,12 +1192,14 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
set_signal(SIGBUS, regs, &info);
}
else {
struct process_vm *vm = thread->vm;
struct vm_range *range;
struct vm_range *range = NULL;
info.si_signo = SIGSEGV;
info.si_code = SEGV_MAPERR;
range = lookup_process_memory_range(vm, (uintptr_t)fault_addr, ((uintptr_t)fault_addr) + 1);
if (thread)
range = lookup_process_memory_range(thread->vm,
(uintptr_t)fault_addr,
((uintptr_t)fault_addr) + 1);
if (range)
info.si_code = SEGV_ACCERR;
info._sifields._sigfault.si_addr = fault_addr;
@ -1219,7 +1221,7 @@ out:
set_cputime(interrupt_from_user(regs) ?
CPUTIME_MODE_K2U : CPUTIME_MODE_K2K_OUT);
#ifdef PROFILE_ENABLE
if (thread->profile)
if (thread && thread->profile)
profile_event_add(PROFILE_page_fault, (rdtsc() - t_s));
#endif // PROFILE_ENABLE
return;