If we are faulting in kernel it is quite possible this will lead to a panic. Save trap number, cr2 (in case of page fault) and error_code in the current thread (these fields already exist for signal delivery but are not used here). This helps later kdump crash analyzing from user-space (a script has been submitted to dig this info out in gdb).
Unified · Split
| @@ -369,6 +369,10 @@ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long e · 368 unmodified lines | ||
| 369 | 369 | static void do_trap(int trapnr, int signr, char *str, int vm86, |
| 370 | 370 | struct pt_regs * regs, long error_code, siginfo_t *info) |
| 371 | 371 | { |
| 372 | + struct task_struct *tsk = current; | |
| 373 | + tsk->thread.error_code = error_code; | |
| 374 | + tsk->thread.trap_no = trapnr; | |
| 375 | + | |
| 372 | 376 | if (regs->eflags & VM_MASK) { |
| 373 | 377 | if (vm86) |
| 374 | 378 | goto vm86_trap; |
| @@ -379,9 +383,6 @@ static void do_trap(int trapnr, int signr, char *str, int vm86, · 4 unmodified lines | ||
| 379 | 383 | goto kernel_trap; |
| 380 | 384 | |
| 381 | 385 | trap_signal: { |
| 382 | − struct task_struct *tsk = current; | |
| 383 | − tsk->thread.error_code = error_code; | |
| 384 | − tsk->thread.trap_no = trapnr; | |
| 385 | 386 | if (info) |
| 386 | 387 | force_sig_info(signr, info, tsk); |
| 387 | 388 | else |
| @@ -494,6 +495,9 @@ fastcall void do_general_protection(struct pt_regs * regs, long error_code) · 106 unmodified lines | ||
| 494 | 495 | } |
| 495 | 496 | put_cpu(); |
| 496 | 497 | |
| 498 | + current->thread.error_code = error_code; | |
| 499 | + current->thread.trap_no = 13; | |
| 500 | + | |
| 497 | 501 | if (regs->eflags & VM_MASK) |
| 498 | 502 | goto gp_in_vm86; |
| 499 | 503 | |
| @@ -897,9 +901,9 @@ fastcall void do_simd_coprocessor_error(struct pt_regs * regs, · 397 unmodified lines | ||
| 897 | 901 | error_code); |
| 898 | 902 | return; |
| 899 | 903 | } |
| 900 | − die_if_kernel("cache flush denied", regs, error_code); | |
| 901 | 904 | current->thread.trap_no = 19; |
| 902 | 905 | current->thread.error_code = error_code; |
| 906 | + die_if_kernel("cache flush denied", regs, error_code); | |
| 903 | 907 | force_sig(SIGSEGV, current); |
| 904 | 908 | } |
| 905 | 909 | } |
| @@ -463,6 +463,9 @@ no_context: · 462 unmodified lines | ||
| 463 | 463 | printk(KERN_ALERT "*pte = %08lx\n", page); |
| 464 | 464 | } |
| 465 | 465 | #endif |
| 466 | + tsk->thread.cr2 = address; | |
| 467 | + tsk->thread.trap_no = 14; | |
| 468 | + tsk->thread.error_code = error_code; | |
| 466 | 469 | die("Oops", regs, error_code); |
| 467 | 470 | bust_spinlocks(0); |
| 468 | 471 | do_exit(SIGKILL); |