diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/traps.c | 24 | ||||
-rw-r--r-- | arch/x86_64/kernel/traps.c | 30 |
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 | ||
625 | gp_in_kernel: | 635 | gp_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; |