diff options
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/traps.c | 30 |
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; |