x86-64: honor notify_die() returning NOTIFY_STOP
[deliverable/linux.git] / arch / x86 / kernel / traps_64.c
index 1a12a81fdb1bafcce090287d9ad1de272b1f1944..cf90ceb48f5f942bdc914fb3360e7bc0b0c8b300 100644 (file)
@@ -488,7 +488,7 @@ unsigned __kprobes long oops_begin(void)
        return flags;
 }
 
-void __kprobes oops_end(unsigned long flags)
+void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr)
 { 
        die_owner = -1;
        bust_spinlocks(0);
@@ -497,12 +497,17 @@ void __kprobes oops_end(unsigned long flags)
                /* Nest count reaches zero, release the lock. */
                __raw_spin_unlock(&die_lock);
        raw_local_irq_restore(flags);
+       if (!regs) {
+               oops_exit();
+               return;
+       }
        if (panic_on_oops)
                panic("Fatal exception");
        oops_exit();
+       do_exit(signr);
 }
 
-void __kprobes __die(const char * str, struct pt_regs * regs, long err)
+int __kprobes __die(const char * str, struct pt_regs * regs, long err)
 {
        static int die_counter;
        printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff,++die_counter);
@@ -516,7 +521,8 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
        printk("DEBUG_PAGEALLOC");
 #endif
        printk("\n");
-       notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
+       if (notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+               return 1;
        show_registers(regs);
        add_taint(TAINT_DIE);
        /* Executive summary in case the oops scrolled away */
@@ -525,6 +531,7 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
        printk(" RSP <%016lx>\n", regs->sp);
        if (kexec_should_crash(current))
                crash_kexec(regs);
+       return 0;
 }
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -534,9 +541,9 @@ void die(const char * str, struct pt_regs * regs, long err)
        if (!user_mode(regs))
                report_bug(regs->ip, regs);
 
-       __die(str, regs, err);
-       oops_end(flags);
-       do_exit(SIGSEGV); 
+       if (__die(str, regs, err))
+               regs = NULL;
+       oops_end(flags, regs, SIGSEGV);
 }
 
 void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
@@ -553,10 +560,10 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
                crash_kexec(regs);
        if (do_panic || panic_on_oops)
                panic("Non maskable interrupt");
-       oops_end(flags);
+       oops_end(flags, NULL, SIGBUS);
        nmi_exit();
        local_irq_enable();
-       do_exit(SIGSEGV);
+       do_exit(SIGBUS);
 }
 
 static void __kprobes do_trap(int trapnr, int signr, char *str,
This page took 0.030006 seconds and 5 git commands to generate.