UML - Kernel segfaults should dump proper registers
PATCH 2/4 UML - Kernel segfaults should dump proper registers
If there's a segfault inside the kernel, we want a dump of the registers at the point of the segfault, not the registers at the point of calling panic or the last userspace registers.
sig_handler_common_skas now uses a static register set in the case of a SIGSEGV to avoid messing up the process registers if the segfault turns out to be non-fatal.
The architecture sigcontext-to-pt_regs copying code was repurposed to copy data out of the SEGV stack frame.
--
arch/um/include/common-offsets.h | 2 + arch/um/include/kern_util.h | 2 + arch/um/kernel/trap.c | 10 ++++++--- arch/um/os-Linux/skas/trap.c | 15 ++++++++++++-- arch/um/sys-i386/signal.c | 41 ++++++++++++++++++++++----------------- arch/um/sys-x86_64/signal.c | 30 ++++++++++++++++++++++++++++ 6 files changed, 78 insertions(+), 22 deletions(-)
arch/um/kernel/trap.c +7 -3
@@ -170,8 +170,10 @@ unsigned long segv(struct faultinfo fi,flush_tlb_kernel_vm ();return 0 ; } -else if (current->mm ==NULL ) -panic ("Segfault with no mm" ); +else if (current->mm ==NULL ) { +show_regs (container_of(regs ,struct pt_regs ,regs )); +panic ("Segfault with no mm" ); + }if (SEGV_IS_FIXABLE (&fi) ||SEGV_MAYBE_FIXABLE (&fi)) err =handle_page_fault (address, ip, is_write, is_user, &si.si_code);
@@ -194,9 +196,11 @@ unsigned long segv(struct faultinfo fi,else if (!is_user &&arch_fixup (ip, regs))return 0 ; -if (!is_user) +if (!is_user) { +show_regs (container_of(regs ,struct pt_regs ,regs ));panic ("Kernel mode fault at addr 0x%lx, ip 0x%lx" , address, ip); + }if (err == -EACCES ) { si.si_signo =SIGBUS ;
arch/um/include/kern_util.h +2 -0
@@ -116,4 +116,6 @@ extern void log_info(char *fmt, ...) __aextern int __cant_sleep (void );extern void sigio_handler (int sig,union uml_pt_regs *regs); +extern void copy_sc (union uml_pt_regs *regs,void *from); +#endif
arch/um/include/common-offsets.h +2 -0
@@ -24,5 +24,7 @@ DEFINE(UM_ELF_CLASS, ELF_CLASS);DEFINE (UM_ELFCLASS32 ,ELFCLASS32 );DEFINE (UM_ELFCLASS64 ,ELFCLASS64 ); +DEFINE (UM_NR_CPUS ,NR_CPUS ); +/* For crypto assembler code. */ DEFINE (crypto_tfm_ctx_offset, offsetof(struct crypto_tfm , __crt_ctx));
arch/um/os-Linux/skas/trap.c +13 -2
@@ -15,6 +15,8 @@#include "sysdep/ptrace_user.h" #include "os.h" +static union uml_pt_regs ksig_regs[UM_NR_CPUS ]; +void sig_handler_common_skas (int sig,void *sc_ptr) {struct sigcontext *sc = sc_ptr;
@@ -27,10 +29,19 @@ void sig_handler_common_skas(int sig, vo* the process will die. * XXX Figure out why this is better than SA_NODEFER */ -if (sig ==SIGSEGV ) +if (sig ==SIGSEGV ) {change_sig (SIGSEGV ,1 ); +/* For segfaults, we want the data from the +* sigcontext. In this case, we don't want to mangle +* the process registers, so use a static set of +* registers. For other signals, the process +* registers are OK. +*/ + r = &ksig_regs[cpu ()]; +copy_sc (r, sc_ptr); + } +else r =TASK_REGS (get_current ()); - r =TASK_REGS (get_current ()); save_user = r->skas.is_user; r->skas.is_user =0 ; if ( sig == SIGFPE || sig == SIGSEGV ||
arch/um/sys-i386/signal.c +24 -17
55 lines not on this page · raw message
arch/um/sys-x86_64/signal.c +30 -0
@@ -20,6 +20,36 @@#include "skas.h" +void copy_sc (union uml_pt_regs *regs,void *from) +{ +struct sigcontext *sc = from; + +#define GETREG (regs, regno, sc, regname) \ + (regs)->skas.regs[(regno) / sizeof(unsigned long)] = (sc)->regname + +GETREG (regs,R8 , sc, r8); +GETREG (regs,R9 , sc, r9); +GETREG (regs,R10 , sc, r10); +GETREG (regs,R11 , sc, r11); +GETREG (regs,R12 , sc, r12); +GETREG (regs,R13 , sc, r13); +GETREG (regs,R14 , sc, r14); +GETREG (regs,R15 , sc, r15); +GETREG (regs,RDI , sc, rdi); +GETREG (regs,RSI , sc, rsi); +GETREG (regs,RBP , sc, rbp); +GETREG (regs,RBX , sc, rbx); +GETREG (regs,RDX , sc, rdx); +GETREG (regs,RAX , sc, rax); +GETREG (regs,RCX , sc, rcx); +GETREG (regs,RSP , sc, rsp); +GETREG (regs,RIP , sc, rip); +GETREG (regs,EFLAGS , sc, eflags); +GETREG (regs,CS , sc, cs); + +#undef GETREG +} +static int copy_sc_from_user_skas (struct pt_regs *regs,struct sigcontext __user *from) {
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
User-mode-linux-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel