From: Chuck Ebbert <76306.1226@compuserve.com> Fix recursive faults during oops caused by invalid value in current by using __get_user()/__put_user() when dereferencing it. Reported by Krzysztof Halasa Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Cc: Andi Kleen Signed-off-by: Andrew Morton --- arch/i386/kernel/traps.c | 16 ++++++++++++---- arch/i386/mm/fault.c | 7 ++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff -puN arch/i386/kernel/traps.c~i386-fix-recursive-faults-during-oops-when-current arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c~i386-fix-recursive-faults-during-oops-when-current +++ a/arch/i386/kernel/traps.c @@ -343,8 +343,16 @@ void show_registers(struct pt_regs *regs int i; int in_kernel = 1; unsigned long esp; + char *comm = ""; + pid_t pid = 0; + void *thread_info = 0; unsigned short ss; + __get_user(thread_info, ¤t->thread_info); + __get_user(pid, ¤t->pid); + if (!__get_user(comm, (char **)current->comm)) + comm = current->comm; + esp = (unsigned long) (®s->esp); savesegment(ss, ss); if (user_mode_vm(regs)) { @@ -368,8 +376,8 @@ void show_registers(struct pt_regs *regs printk(KERN_EMERG "ds: %04x es: %04x ss: %04x\n", regs->xds & 0xffff, regs->xes & 0xffff, ss); printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", - TASK_COMM_LEN, current->comm, current->pid, - current_thread_info(), current, current->thread_info); + TASK_COMM_LEN, comm, pid, + current_thread_info(), current, thread_info); /* * When in-kernel, we also print out the stack and code at the * time of the fault.. @@ -454,6 +462,7 @@ void die(const char * str, struct pt_reg }; static int die_counter; unsigned long flags; + unsigned long trap_no = 0; /* default if task pointer is corrupt */ oops_enter(); @@ -493,8 +502,7 @@ void die(const char * str, struct pt_reg if (nl) printk("\n"); sysfs_printk_last_file(); - if (notify_die(DIE_OOPS, str, regs, err, - current->thread.trap_no, SIGSEGV) != + if (notify_die(DIE_OOPS, str, regs, err, trap_no, SIGSEGV) != NOTIFY_STOP) { show_registers(regs); /* Executive summary in case the oops scrolled away */ diff -puN arch/i386/mm/fault.c~i386-fix-recursive-faults-during-oops-when-current arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c~i386-fix-recursive-faults-during-oops-when-current +++ a/arch/i386/mm/fault.c @@ -576,9 +576,10 @@ no_context: printk(KERN_ALERT "*pte = %08lx\n", page); } #endif - tsk->thread.cr2 = address; - tsk->thread.trap_no = 14; - tsk->thread.error_code = error_code; + /* avoid possible fault here if tsk is garbage */ + __put_user(address, &tsk->thread.cr2); + __put_user(14, &tsk->thread.trap_no); + __put_user(error_code, &tsk->thread.error_code); die("Oops", regs, error_code); bust_spinlocks(0); do_exit(SIGKILL); _