diff options
Diffstat (limited to 'arch/x86/kernel/traps.c')
| -rw-r--r-- | arch/x86/kernel/traps.c | 20 | 
1 files changed, 17 insertions, 3 deletions
| diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index e6db475164ed..5bd0a997d81e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -206,7 +206,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,  	}  	if (!user_mode(regs)) { -		if (fixup_exception(regs, trapnr)) +		if (fixup_exception(regs, trapnr, error_code, 0))  			return 0;  		tsk->thread.error_code = error_code; @@ -383,6 +383,10 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code)  		 * we won't enable interupts or schedule before we invoke  		 * general_protection, so nothing will clobber the stack  		 * frame we just set up. +		 * +		 * We will enter general_protection with kernel GSBASE, +		 * which is what the stub expects, given that the faulting +		 * RIP will be the IRET instruction.  		 */  		regs->ip = (unsigned long)general_protection;  		regs->sp = (unsigned long)&gpregs->orig_ax; @@ -551,11 +555,21 @@ do_general_protection(struct pt_regs *regs, long error_code)  	tsk = current;  	if (!user_mode(regs)) { -		if (fixup_exception(regs, X86_TRAP_GP)) +		if (fixup_exception(regs, X86_TRAP_GP, error_code, 0))  			return;  		tsk->thread.error_code = error_code;  		tsk->thread.trap_nr = X86_TRAP_GP; + +		/* +		 * To be potentially processing a kprobe fault and to +		 * trust the result from kprobe_running(), we have to +		 * be non-preemptible. +		 */ +		if (!preemptible() && kprobe_running() && +		    kprobe_fault_handler(regs, X86_TRAP_GP)) +			return; +  		if (notify_die(DIE_GPF, "general protection fault", regs, error_code,  			       X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP)  			die("general protection fault", regs, error_code); @@ -838,7 +852,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)  	cond_local_irq_enable(regs);  	if (!user_mode(regs)) { -		if (fixup_exception(regs, trapnr)) +		if (fixup_exception(regs, trapnr, error_code, 0))  			return;  		task->thread.error_code = error_code; |