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:
committed by
Masamichi Takagi
parent
fe08ac4a67
commit
f5023c9730
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
20
kernel/mem.c
20
kernel/mem.c
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user