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 34a327f35976..8f6dcd88202e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -203,7 +203,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str,  				return 0;  		}  	} else 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; @@ -358,6 +358,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; @@ -535,11 +539,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, desc, regs, error_code,  			       X86_TRAP_GP, SIGSEGV) != NOTIFY_STOP)  			die(desc, regs, error_code); @@ -815,7 +829,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;  | 
