aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/traps.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 09d2e8a10a49..cceef5bd7302 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -581,10 +581,20 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
581{ 581{
582 struct task_struct *tsk = current; 582 struct task_struct *tsk = current;
583 583
584 tsk->thread.error_code = error_code;
585 tsk->thread.trap_no = trapnr;
586
587 if (user_mode(regs)) { 584 if (user_mode(regs)) {
585 /*
586 * We want error_code and trap_no set for userspace
587 * faults and kernelspace faults which result in
588 * die(), but not kernelspace faults which are fixed
589 * up. die() gives the process no chance to handle
590 * the signal and notice the kernel fault information,
591 * so that won't result in polluting the information
592 * about previously queued, but not yet delivered,
593 * faults. See also do_general_protection below.
594 */
595 tsk->thread.error_code = error_code;
596 tsk->thread.trap_no = trapnr;
597
588 if (exception_trace && unhandled_signal(tsk, signr)) 598 if (exception_trace && unhandled_signal(tsk, signr))
589 printk(KERN_INFO 599 printk(KERN_INFO
590 "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", 600 "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n",
@@ -605,8 +615,11 @@ static void __kprobes do_trap(int trapnr, int signr, char *str,
605 fixup = search_exception_tables(regs->rip); 615 fixup = search_exception_tables(regs->rip);
606 if (fixup) 616 if (fixup)
607 regs->rip = fixup->fixup; 617 regs->rip = fixup->fixup;
608 else 618 else {
619 tsk->thread.error_code = error_code;
620 tsk->thread.trap_no = trapnr;
609 die(str, regs, error_code); 621 die(str, regs, error_code);
622 }
610 return; 623 return;
611 } 624 }
612} 625}
@@ -682,10 +695,10 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
682 695
683 conditional_sti(regs); 696 conditional_sti(regs);
684 697
685 tsk->thread.error_code = error_code;
686 tsk->thread.trap_no = 13;
687
688 if (user_mode(regs)) { 698 if (user_mode(regs)) {
699 tsk->thread.error_code = error_code;
700 tsk->thread.trap_no = 13;
701
689 if (exception_trace && unhandled_signal(tsk, SIGSEGV)) 702 if (exception_trace && unhandled_signal(tsk, SIGSEGV))
690 printk(KERN_INFO 703 printk(KERN_INFO
691 "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", 704 "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n",
@@ -704,6 +717,9 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
704 regs->rip = fixup->fixup; 717 regs->rip = fixup->fixup;
705 return; 718 return;
706 } 719 }
720
721 tsk->thread.error_code = error_code;
722 tsk->thread.trap_no = 13;
707 if (notify_die(DIE_GPF, "general protection fault", regs, 723 if (notify_die(DIE_GPF, "general protection fault", regs,
708 error_code, 13, SIGSEGV) == NOTIFY_STOP) 724 error_code, 13, SIGSEGV) == NOTIFY_STOP)
709 return; 725 return;