aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/traps.c24
-rw-r--r--arch/x86_64/kernel/traps.c30
2 files changed, 41 insertions, 13 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index af0d3f70a817..58dfecc8e36c 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -476,8 +476,6 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
476 siginfo_t *info) 476 siginfo_t *info)
477{ 477{
478 struct task_struct *tsk = current; 478 struct task_struct *tsk = current;
479 tsk->thread.error_code = error_code;
480 tsk->thread.trap_no = trapnr;
481 479
482 if (regs->eflags & VM_MASK) { 480 if (regs->eflags & VM_MASK) {
483 if (vm86) 481 if (vm86)
@@ -489,6 +487,18 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
489 goto kernel_trap; 487 goto kernel_trap;
490 488
491 trap_signal: { 489 trap_signal: {
490 /*
491 * We want error_code and trap_no set for userspace faults and
492 * kernelspace faults which result in die(), but not
493 * kernelspace faults which are fixed up. die() gives the
494 * process no chance to handle the signal and notice the
495 * kernel fault information, so that won't result in polluting
496 * the information about previously queued, but not yet
497 * delivered, faults. See also do_general_protection below.
498 */
499 tsk->thread.error_code = error_code;
500 tsk->thread.trap_no = trapnr;
501
492 if (info) 502 if (info)
493 force_sig_info(signr, info, tsk); 503 force_sig_info(signr, info, tsk);
494 else 504 else
@@ -497,8 +507,11 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, int vm86,
497 } 507 }
498 508
499 kernel_trap: { 509 kernel_trap: {
500 if (!fixup_exception(regs)) 510 if (!fixup_exception(regs)) {
511 tsk->thread.error_code = error_code;
512 tsk->thread.trap_no = trapnr;
501 die(str, regs, error_code); 513 die(str, regs, error_code);
514 }
502 return; 515 return;
503 } 516 }
504 517
@@ -603,9 +616,6 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs,
603 } 616 }
604 put_cpu(); 617 put_cpu();
605 618
606 current->thread.error_code = error_code;
607 current->thread.trap_no = 13;
608
609 if (regs->eflags & VM_MASK) 619 if (regs->eflags & VM_MASK)
610 goto gp_in_vm86; 620 goto gp_in_vm86;
611 621
@@ -624,6 +634,8 @@ gp_in_vm86:
624 634
625gp_in_kernel: 635gp_in_kernel:
626 if (!fixup_exception(regs)) { 636 if (!fixup_exception(regs)) {
637 current->thread.error_code = error_code;
638 current->thread.trap_no = 13;
627 if (notify_die(DIE_GPF, "general protection fault", regs, 639 if (notify_die(DIE_GPF, "general protection fault", regs,
628 error_code, 13, SIGSEGV) == NOTIFY_STOP) 640 error_code, 13, SIGSEGV) == NOTIFY_STOP)
629 return; 641 return;
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;