From: Martin P. <mar...@gm...> - 2012-06-07 21:00:05
|
Signal handlers in UML guest processes now get correct siginfo_t fields for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct where previously they were si_addr = NULL and si_code = 128. Signed-off-by: Martin Pärtel <mar...@gm...> --- diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/as-layout.h linux-3.4.1-mod/arch/um/include/shared/as-layout.h --- linux-3.4.1/arch/um/include/shared/as-layout.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/as-layout.h 2012-06-07 18:48:21.469563959 +0300 @@ -60,7 +60,8 @@ extern unsigned long host_task_size; extern int linux_main(int argc, char **argv); -extern void (*sig_info[])(int, struct uml_pt_regs *); +struct siginfo; +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); #endif diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/kern_util.h linux-3.4.1-mod/arch/um/include/shared/kern_util.h --- linux-3.4.1/arch/um/include/shared/kern_util.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/kern_util.h 2012-06-07 22:55:35.737822291 +0300 @@ -9,6 +9,8 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" +struct siginfo; + extern int uml_exitcode; extern int ncpus; @@ -22,7 +24,7 @@ extern void free_stack(unsigned long sta extern int do_signal(void); extern void interrupt_end(void); -extern void relay_signal(int sig, struct uml_pt_regs *regs); +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, struct uml_pt_regs *regs); @@ -33,7 +35,6 @@ extern unsigned int do_IRQ(int irq, stru extern int smp_sigio_handler(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int is_syscall(unsigned long addr); -extern void timer_handler(int sig, struct uml_pt_regs *regs); extern void timer_handler(int sig, struct uml_pt_regs *regs); @@ -60,7 +61,7 @@ extern void syscall_trace(struct uml_pt_ extern int singlestepping(void *t); extern void segv_handler(int sig, struct uml_pt_regs *regs); -extern void bus_handler(int sig, struct uml_pt_regs *regs); +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern void winch(int sig, struct uml_pt_regs *regs); extern void fatal_sigsegv(void) __attribute__ ((noreturn)); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/trap.c linux-3.4.1-mod/arch/um/kernel/trap.c --- linux-3.4.1/arch/um/kernel/trap.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/kernel/trap.c 2012-06-07 23:30:11.905858447 +0300 @@ -244,7 +244,7 @@ unsigned long segv(struct faultinfo fi, return 0; } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) { if (!UPT_IS_USER(regs)) { if (sig == SIGBUS) @@ -256,14 +256,15 @@ void relay_signal(int sig, struct uml_pt arch_examine_signal(sig, regs); current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); - force_sig(sig, current); + force_sig_info(sig, si, current); } -void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) { if (current->thread.fault_catcher != NULL) UML_LONGJMP(current->thread.fault_catcher, 1); - else relay_signal(sig, regs); + else + relay_signal(sig, si, regs); } void winch(int sig, struct uml_pt_regs *regs) diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/signal.c linux-3.4.1-mod/arch/um/os-Linux/signal.c --- linux-3.4.1/arch/um/os-Linux/signal.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/signal.c 2012-06-07 23:32:13.693860567 +0300 @@ -13,18 +13,55 @@ #include "kern_util.h" #include "os.h" #include "sysdep/mcontext.h" +#include "internal.h" -void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { +static void winch_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + winch(sig, regs); +} + +static void segv_handler_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + segv_handler(sig, regs); +} + +static void sigio_handler_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + sigio_handler(sig, regs); +} + +static void timer_handler_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + timer_handler(sig, regs); +} + +static void alarm_handler_ignore_siginfo(int sig, + siginfo_t *si, + mcontext_t *mc) +{ + alarm_handler(sig, mc); +} + + +void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { [SIGTRAP] = relay_signal, [SIGFPE] = relay_signal, [SIGILL] = relay_signal, - [SIGWINCH] = winch, + [SIGWINCH] = winch_ignore_siginfo, [SIGBUS] = bus_handler, - [SIGSEGV] = segv_handler, - [SIGIO] = sigio_handler, - [SIGVTALRM] = timer_handler }; + [SIGSEGV] = segv_handler_ignore_siginfo, + [SIGIO] = sigio_handler_ignore_siginfo, + [SIGVTALRM] = timer_handler_ignore_siginfo }; -static void sig_handler_common(int sig, mcontext_t *mc) +static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) { struct uml_pt_regs r; int save_errno = errno; @@ -40,7 +77,7 @@ static void sig_handler_common(int sig, if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) unblock_signals(); - (*sig_info[sig])(sig, &r); + (*sig_info[sig])(sig, si, &r); errno = save_errno; } @@ -60,7 +97,7 @@ static void sig_handler_common(int sig, static int signals_enabled; static unsigned int signals_pending; -void sig_handler(int sig, mcontext_t *mc) +void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) { int enabled; @@ -72,7 +109,7 @@ void sig_handler(int sig, mcontext_t *mc block_signals(); - sig_handler_common(sig, mc); + sig_handler_common(sig, si, mc); set_signals(enabled); } @@ -119,7 +156,7 @@ void set_sigstack(void *sig_stack, int s panic("enabling signal stack failed, errno = %d\n", errno); } -static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { +static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { [SIGSEGV] = sig_handler, [SIGBUS] = sig_handler, [SIGILL] = sig_handler, @@ -128,11 +165,11 @@ static void (*handlers[_NSIG])(int sig, [SIGIO] = sig_handler, [SIGWINCH] = sig_handler, - [SIGVTALRM] = alarm_handler + [SIGVTALRM] = alarm_handler_ignore_siginfo }; -static void hard_handler(int sig, siginfo_t *info, void *p) +static void hard_handler(int sig, siginfo_t *si, void *p) { struct ucontext *uc = p; mcontext_t *mc = &uc->uc_mcontext; @@ -161,7 +198,7 @@ static void hard_handler(int sig, siginf while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); - (*handlers[sig])(sig, mc); + (*handlers[sig])(sig, si, mc); } /* @@ -273,9 +310,12 @@ void unblock_signals(void) * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. + * + * SIGIO's handler doesn't use siginfo or mcontext, + * so they can be NULL. */ if (save_pending & SIGIO_MASK) - sig_handler_common(SIGIO, NULL); + sig_handler_common(SIGIO, NULL, NULL); if (save_pending & SIGVTALRM_MASK) real_alarm_handler(NULL); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/skas/process.c linux-3.4.1-mod/arch/um/os-Linux/skas/process.c --- linux-3.4.1/arch/um/os-Linux/skas/process.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/skas/process.c 2012-06-07 23:31:12.681859505 +0300 @@ -346,6 +346,7 @@ void userspace(struct uml_pt_regs *regs) int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; + siginfo_t si; if (getitimer(ITIMER_VIRTUAL, &timer)) printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); @@ -404,13 +405,17 @@ void userspace(struct uml_pt_regs *regs) if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); + + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); + switch (sig) { case SIGSEGV: if (PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); - (*sig_info[SIGSEGV])(SIGSEGV, regs); + (*sig_info[SIGSEGV])(SIGSEGV, &si, + regs); } else handle_segv(pid, regs); break; @@ -418,14 +423,14 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: - relay_signal(SIGTRAP, regs); + relay_signal(SIGTRAP, &si, regs); break; case SIGVTALRM: now = os_nsecs(); if (now < nsecs) break; block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + @@ -439,7 +444,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); break; default: |
From: Richard W. <ri...@no...> - 2012-06-07 21:26:41
Attachments:
signature.asc
|
Am 07.06.2012 22:59, schrieb Martin Pärtel: > Signal handlers in UML guest processes now get correct siginfo_t fields > for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code > are now correct where previously they were si_addr = NULL and si_code = 128. What exactly is broken? In my SIGSEGV test case si_addr is not NULL, it contains the correct faulting address. > + > + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); > + Doesn't this leak the host siginfo_t into the guest? Thanks, //richard |
From: Martin P. <mar...@gm...> - 2012-06-07 21:41:42
|
(ack, forgot to reply to list) On 06/08/2012 12:26 AM, Richard Weinberger wrote: > Am 07.06.2012 22:59, schrieb Martin Pärtel: >> Signal handlers in UML guest processes now get correct siginfo_t fields >> for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code >> are now correct where previously they were si_addr = NULL and si_code = 128. > > What exactly is broken? > In my SIGSEGV test case si_addr is not NULL, it contains the correct faulting address. > SIGSEGV is probably fine. At least SIGFPE is not. Test program below. >> + >> + ptrace(PTRACE_GETSIGINFO, pid, 0,&si); >> + > > Doesn't this leak the host siginfo_t into the guest? > Docs for PTRACE_GETSIGINFO say `si' gets a copy. After that, `si' is not used for anything other than giving it to the guest. But I really can't say I understand the surrounding code too well so please review carefully :) --- #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <signal.h> void handler(int num, siginfo_t *info, void *data) { printf("CAUGHT SIGNAL %d - si_addr = %p - si_code = %d\n", num, info->si_addr, info->si_code); _exit(1); } int main() { struct sigaction act; act.sa_sigaction = &handler; sigemptyset(&act.sa_mask); act.sa_flags = SA_SIGINFO; sigaction(SIGFPE, &act, NULL); printf("%d\n", 3 / 0); return 0; } |
From: Richard W. <ri...@no...> - 2012-06-07 22:08:04
Attachments:
signature.asc
|
Am 07.06.2012 23:39, schrieb Martin Pärtel: > On 06/08/2012 12:26 AM, Richard Weinberger wrote: > >> Am 07.06.2012 22:59, schrieb Martin Pärtel: >>> Signal handlers in UML guest processes now get correct siginfo_t fields >>> for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code >>> are now correct where previously they were si_addr = NULL and si_code = 128. >> >> What exactly is broken? >> In my SIGSEGV test case si_addr is not NULL, it contains the correct faulting address. >> > > > SIGSEGV is probably fine. At least SIGFPE is not. Test program below. > >>> + >>> + ptrace(PTRACE_GETSIGINFO, pid, 0,&si); >>> + >> >> Doesn't this leak the host siginfo_t into the guest? >> > > > Docs for PTRACE_GETSIGINFO say `si' gets a copy. After that, `si' is not used for anything other than giving it to the guest. But I really can't say I > understand the surrounding code too well so please review carefully :) I was not talking about a memory leak. What I meant was a information leak. Using the host siginfo_t a guest process may get it's UID, PID, memory location, etc... on the host side. Anyway, thanks for the test case! This seems to be really broken. I had only a few minutes to look at the issue but I think the correct way to fix is changing arch/um/kernel/trap.c:relay_signal() to use force_sig_info() instead of force_sig(). Create siginfo_t and fill by hand like segv() does. Thanks, //richard |
From: Martin P. <mar...@gm...> - 2012-06-07 22:42:14
|
On 06/08/2012 01:07 AM, Richard Weinberger wrote: > Am 07.06.2012 23:39, schrieb Martin Pärtel: >> On 06/08/2012 12:26 AM, Richard Weinberger wrote: >> >>> Am 07.06.2012 22:59, schrieb Martin Pärtel: >>>> Signal handlers in UML guest processes now get correct siginfo_t fields >>>> for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code >>>> are now correct where previously they were si_addr = NULL and si_code = 128. >>> >>> What exactly is broken? >>> In my SIGSEGV test case si_addr is not NULL, it contains the correct faulting address. >>> >> >> >> SIGSEGV is probably fine. At least SIGFPE is not. Test program below. >> >>>> + >>>> + ptrace(PTRACE_GETSIGINFO, pid, 0,&si); >>>> + >>> >>> Doesn't this leak the host siginfo_t into the guest? >>> >> >> >> Docs for PTRACE_GETSIGINFO say `si' gets a copy. After that, `si' is not used for anything other than giving it to the guest. But I really can't say I >> understand the surrounding code too well so please review carefully :) > > I was not talking about a memory leak. > What I meant was a information leak. > Using the host siginfo_t a guest process may get it's UID, PID, memory location, etc... on the host side. > Oh, darn, indeed. Well, getting si_code right fixed my immediate problem, but I might look at this again some time next week unless you've fixed it yourself by then. Thanks! |
From: Richard W. <ri...@no...> - 2012-06-07 22:47:24
Attachments:
signature.asc
|
Am 08.06.2012 00:42, schrieb Martin Pärtel: > Oh, darn, indeed. Well, getting si_code right fixed my immediate problem, but I might look at this again some time next week unless you've fixed it > yourself by then. Thanks! > I can wait for your patch. No need to hurry. :) Thanks, //richard |
From: Martin P. <mar...@gm...> - 2012-06-15 17:20:40
|
UML guest processes now get correct siginfo_t for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct where previously they were si_addr = NULL and si_code = 128. Signed-off-by: Martin Pärtel <mar...@gm...> --- Same as last time but put guest side faultaddr to si_addr in relay_signal(). Also some defensive clearing and checking. You decide if it's a good idea. diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/as-layout.h linux-3.4.1-mod/arch/um/include/shared/as-layout.h --- linux-3.4.1/arch/um/include/shared/as-layout.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/as-layout.h 2012-06-15 13:55:32.817111341 +0300 @@ -60,7 +60,8 @@ extern unsigned long host_task_size; extern int linux_main(int argc, char **argv); -extern void (*sig_info[])(int, struct uml_pt_regs *); +struct siginfo; +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); #endif diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/kern_util.h linux-3.4.1-mod/arch/um/include/shared/kern_util.h --- linux-3.4.1/arch/um/include/shared/kern_util.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/kern_util.h 2012-06-15 13:55:32.817111341 +0300 @@ -9,6 +9,8 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" +struct siginfo; + extern int uml_exitcode; extern int ncpus; @@ -22,7 +24,7 @@ extern void free_stack(unsigned long sta extern int do_signal(void); extern void interrupt_end(void); -extern void relay_signal(int sig, struct uml_pt_regs *regs); +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, struct uml_pt_regs *regs); @@ -33,7 +35,6 @@ extern unsigned int do_IRQ(int irq, stru extern int smp_sigio_handler(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int is_syscall(unsigned long addr); -extern void timer_handler(int sig, struct uml_pt_regs *regs); extern void timer_handler(int sig, struct uml_pt_regs *regs); @@ -60,7 +61,7 @@ extern void syscall_trace(struct uml_pt_ extern int singlestepping(void *t); extern void segv_handler(int sig, struct uml_pt_regs *regs); -extern void bus_handler(int sig, struct uml_pt_regs *regs); +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern void winch(int sig, struct uml_pt_regs *regs); extern void fatal_sigsegv(void) __attribute__ ((noreturn)); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/trap.c linux-3.4.1-mod/arch/um/kernel/trap.c --- linux-3.4.1/arch/um/kernel/trap.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/kernel/trap.c 2012-06-15 19:56:16.549060996 +0300 @@ -244,8 +244,11 @@ unsigned long segv(struct faultinfo fi, return 0; } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) { + struct faultinfo *fi; + struct siginfo clean_si; + if (!UPT_IS_USER(regs)) { if (sig == SIGBUS) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " @@ -255,15 +258,37 @@ void relay_signal(int sig, struct uml_pt arch_examine_signal(sig, regs); - current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); - force_sig(sig, current); + memset(&clean_si, 0, sizeof(clean_si)); + clean_si.si_signo = si->si_signo; + clean_si.si_errno = si->si_errno; + clean_si.si_code = si->si_code; + switch (sig) { + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + fi = UPT_FAULTINFO(regs); + clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); + current->thread.arch.faultinfo = *fi; +#ifdef __ARCH_SI_TRAPNO + clean_si.si_trapno = si->si_trapno; +#endif + break; + default: + printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", + sig, si->si_code); + } + + force_sig_info(sig, &clean_si, current); } -void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) { if (current->thread.fault_catcher != NULL) UML_LONGJMP(current->thread.fault_catcher, 1); - else relay_signal(sig, regs); + else + relay_signal(sig, si, regs); } void winch(int sig, struct uml_pt_regs *regs) diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/signal.c linux-3.4.1-mod/arch/um/os-Linux/signal.c --- linux-3.4.1/arch/um/os-Linux/signal.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/signal.c 2012-06-15 13:55:32.817111341 +0300 @@ -13,18 +13,55 @@ #include "kern_util.h" #include "os.h" #include "sysdep/mcontext.h" +#include "internal.h" -void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { +static void winch_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + winch(sig, regs); +} + +static void segv_handler_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + segv_handler(sig, regs); +} + +static void sigio_handler_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + sigio_handler(sig, regs); +} + +static void timer_handler_ignore_siginfo(int sig, + siginfo_t *si, + struct uml_pt_regs *regs) +{ + timer_handler(sig, regs); +} + +static void alarm_handler_ignore_siginfo(int sig, + siginfo_t *si, + mcontext_t *mc) +{ + alarm_handler(sig, mc); +} + + +void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { [SIGTRAP] = relay_signal, [SIGFPE] = relay_signal, [SIGILL] = relay_signal, - [SIGWINCH] = winch, + [SIGWINCH] = winch_ignore_siginfo, [SIGBUS] = bus_handler, - [SIGSEGV] = segv_handler, - [SIGIO] = sigio_handler, - [SIGVTALRM] = timer_handler }; + [SIGSEGV] = segv_handler_ignore_siginfo, + [SIGIO] = sigio_handler_ignore_siginfo, + [SIGVTALRM] = timer_handler_ignore_siginfo }; -static void sig_handler_common(int sig, mcontext_t *mc) +static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) { struct uml_pt_regs r; int save_errno = errno; @@ -40,7 +77,7 @@ static void sig_handler_common(int sig, if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) unblock_signals(); - (*sig_info[sig])(sig, &r); + (*sig_info[sig])(sig, si, &r); errno = save_errno; } @@ -60,7 +97,7 @@ static void sig_handler_common(int sig, static int signals_enabled; static unsigned int signals_pending; -void sig_handler(int sig, mcontext_t *mc) +void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) { int enabled; @@ -72,7 +109,7 @@ void sig_handler(int sig, mcontext_t *mc block_signals(); - sig_handler_common(sig, mc); + sig_handler_common(sig, si, mc); set_signals(enabled); } @@ -119,7 +156,7 @@ void set_sigstack(void *sig_stack, int s panic("enabling signal stack failed, errno = %d\n", errno); } -static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { +static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { [SIGSEGV] = sig_handler, [SIGBUS] = sig_handler, [SIGILL] = sig_handler, @@ -128,11 +165,11 @@ static void (*handlers[_NSIG])(int sig, [SIGIO] = sig_handler, [SIGWINCH] = sig_handler, - [SIGVTALRM] = alarm_handler + [SIGVTALRM] = alarm_handler_ignore_siginfo }; -static void hard_handler(int sig, siginfo_t *info, void *p) +static void hard_handler(int sig, siginfo_t *si, void *p) { struct ucontext *uc = p; mcontext_t *mc = &uc->uc_mcontext; @@ -161,7 +198,7 @@ static void hard_handler(int sig, siginf while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); - (*handlers[sig])(sig, mc); + (*handlers[sig])(sig, si, mc); } /* @@ -273,9 +310,12 @@ void unblock_signals(void) * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. + * + * SIGIO's handler doesn't use siginfo or mcontext, + * so they can be NULL. */ if (save_pending & SIGIO_MASK) - sig_handler_common(SIGIO, NULL); + sig_handler_common(SIGIO, NULL, NULL); if (save_pending & SIGVTALRM_MASK) real_alarm_handler(NULL); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/skas/process.c linux-3.4.1-mod/arch/um/os-Linux/skas/process.c --- linux-3.4.1/arch/um/os-Linux/skas/process.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/skas/process.c 2012-06-15 13:56:58.261111142 +0300 @@ -346,6 +346,7 @@ void userspace(struct uml_pt_regs *regs) int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; + siginfo_t si; if (getitimer(ITIMER_VIRTUAL, &timer)) printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); @@ -404,13 +405,17 @@ void userspace(struct uml_pt_regs *regs) if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); + + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); + switch (sig) { case SIGSEGV: if (PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); - (*sig_info[SIGSEGV])(SIGSEGV, regs); + (*sig_info[SIGSEGV])(SIGSEGV, &si, + regs); } else handle_segv(pid, regs); break; @@ -418,14 +423,14 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: - relay_signal(SIGTRAP, regs); + relay_signal(SIGTRAP, &si, regs); break; case SIGVTALRM: now = os_nsecs(); if (now < nsecs) break; block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + @@ -439,7 +444,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); break; default: |
From: richard -r. w. <ric...@gm...> - 2012-06-20 21:20:00
|
On Fri, Jun 15, 2012 at 7:20 PM, Martin Pärtel <mar...@gm...> wrote: > UML guest processes now get correct siginfo_t for SIGTRAP, SIGFPE, > SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct > where previously they were si_addr = NULL and si_code = 128. > > Signed-off-by: Martin Pärtel <mar...@gm...> Do we really need the _ignore_siginfo wrappers? Can't you add siginto to all handlers (where it's needed) and set it to NULL if the information is not available/used. -- Thanks, //richard |
From: Martin P. <mar...@gm...> - 2012-06-21 08:09:57
|
UML guest processes now get correct siginfo_t for SIGTRAP, SIGFPE, SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct where previously they were si_addr = NULL and si_code = 128. Signed-off-by: Martin Pärtel <mar...@gm...> --- Removed _ignore_siginfo wrappers as requested. diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/as-layout.h linux-3.4.1-mod/arch/um/include/shared/as-layout.h --- linux-3.4.1/arch/um/include/shared/as-layout.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/as-layout.h 2012-06-15 13:55:32.817111341 +0300 @@ -60,7 +60,8 @@ extern unsigned long host_task_size; extern int linux_main(int argc, char **argv); -extern void (*sig_info[])(int, struct uml_pt_regs *); +struct siginfo; +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); #endif diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/irq_user.h linux-3.4.1-mod/arch/um/include/shared/irq_user.h --- linux-3.4.1/arch/um/include/shared/irq_user.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/irq_user.h 2012-06-21 10:40:17.579071501 +0300 @@ -20,7 +20,8 @@ struct irq_fd { enum { IRQ_READ, IRQ_WRITE }; -extern void sigio_handler(int sig, struct uml_pt_regs *regs); +struct siginfo; +extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void free_irq_by_fd(int fd); extern void reactivate_fd(int fd, int irqnum); extern void deactivate_fd(int fd, int irqnum); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/kern_util.h linux-3.4.1-mod/arch/um/include/shared/kern_util.h --- linux-3.4.1/arch/um/include/shared/kern_util.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/include/shared/kern_util.h 2012-06-21 10:31:23.204318601 +0300 @@ -9,6 +9,8 @@ #include "sysdep/ptrace.h" #include "sysdep/faultinfo.h" +struct siginfo; + extern int uml_exitcode; extern int ncpus; @@ -22,7 +24,7 @@ extern void free_stack(unsigned long sta extern int do_signal(void); extern void interrupt_end(void); -extern void relay_signal(int sig, struct uml_pt_regs *regs); +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, struct uml_pt_regs *regs); @@ -33,9 +35,8 @@ extern unsigned int do_IRQ(int irq, stru extern int smp_sigio_handler(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int is_syscall(unsigned long addr); -extern void timer_handler(int sig, struct uml_pt_regs *regs); -extern void timer_handler(int sig, struct uml_pt_regs *regs); +extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern int start_uml(void); extern void paging_init(void); @@ -59,9 +60,9 @@ extern unsigned long from_irq_stack(int extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); extern int singlestepping(void *t); -extern void segv_handler(int sig, struct uml_pt_regs *regs); -extern void bus_handler(int sig, struct uml_pt_regs *regs); -extern void winch(int sig, struct uml_pt_regs *regs); +extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); +extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void fatal_sigsegv(void) __attribute__ ((noreturn)); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/irq.c linux-3.4.1-mod/arch/um/kernel/irq.c --- linux-3.4.1/arch/um/kernel/irq.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/kernel/irq.c 2012-06-21 10:30:42.036317885 +0300 @@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &a extern void free_irqs(void); -void sigio_handler(int sig, struct uml_pt_regs *regs) +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct irq_fd *irq_fd; int n; diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/time.c linux-3.4.1-mod/arch/um/kernel/time.c --- linux-3.4.1/arch/um/kernel/time.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/kernel/time.c 2012-06-21 10:31:15.852318471 +0300 @@ -13,7 +13,7 @@ #include "kern_util.h" #include "os.h" -void timer_handler(int sig, struct uml_pt_regs *regs) +void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { unsigned long flags; diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/trap.c linux-3.4.1-mod/arch/um/kernel/trap.c --- linux-3.4.1/arch/um/kernel/trap.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/kernel/trap.c 2012-06-21 10:30:13.880317394 +0300 @@ -158,7 +158,7 @@ void fatal_sigsegv(void) os_dump_core(); } -void segv_handler(int sig, struct uml_pt_regs *regs) +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); @@ -244,8 +244,11 @@ unsigned long segv(struct faultinfo fi, return 0; } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) { + struct faultinfo *fi; + struct siginfo clean_si; + if (!UPT_IS_USER(regs)) { if (sig == SIGBUS) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " @@ -255,18 +258,40 @@ void relay_signal(int sig, struct uml_pt arch_examine_signal(sig, regs); - current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); - force_sig(sig, current); + memset(&clean_si, 0, sizeof(clean_si)); + clean_si.si_signo = si->si_signo; + clean_si.si_errno = si->si_errno; + clean_si.si_code = si->si_code; + switch (sig) { + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + fi = UPT_FAULTINFO(regs); + clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); + current->thread.arch.faultinfo = *fi; +#ifdef __ARCH_SI_TRAPNO + clean_si.si_trapno = si->si_trapno; +#endif + break; + default: + printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", + sig, si->si_code); + } + + force_sig_info(sig, &clean_si, current); } -void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) { if (current->thread.fault_catcher != NULL) UML_LONGJMP(current->thread.fault_catcher, 1); - else relay_signal(sig, regs); + else + relay_signal(sig, si, regs); } -void winch(int sig, struct uml_pt_regs *regs) +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { do_IRQ(WINCH_IRQ, regs); } diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/internal.h linux-3.4.1-mod/arch/um/os-Linux/internal.h --- linux-3.4.1/arch/um/os-Linux/internal.h 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/internal.h 2012-06-21 10:32:11.956319450 +0300 @@ -1 +1 @@ -void alarm_handler(int, mcontext_t *); +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/signal.c linux-3.4.1-mod/arch/um/os-Linux/signal.c --- linux-3.4.1/arch/um/os-Linux/signal.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/signal.c 2012-06-21 10:34:42.668322074 +0300 @@ -13,8 +13,9 @@ #include "kern_util.h" #include "os.h" #include "sysdep/mcontext.h" +#include "internal.h" -void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { +void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { [SIGTRAP] = relay_signal, [SIGFPE] = relay_signal, [SIGILL] = relay_signal, @@ -24,7 +25,7 @@ void (*sig_info[NSIG])(int, struct uml_p [SIGIO] = sigio_handler, [SIGVTALRM] = timer_handler }; -static void sig_handler_common(int sig, mcontext_t *mc) +static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) { struct uml_pt_regs r; int save_errno = errno; @@ -40,7 +41,7 @@ static void sig_handler_common(int sig, if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) unblock_signals(); - (*sig_info[sig])(sig, &r); + (*sig_info[sig])(sig, si, &r); errno = save_errno; } @@ -60,7 +61,7 @@ static void sig_handler_common(int sig, static int signals_enabled; static unsigned int signals_pending; -void sig_handler(int sig, mcontext_t *mc) +void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) { int enabled; @@ -72,7 +73,7 @@ void sig_handler(int sig, mcontext_t *mc block_signals(); - sig_handler_common(sig, mc); + sig_handler_common(sig, si, mc); set_signals(enabled); } @@ -85,10 +86,10 @@ static void real_alarm_handler(mcontext_ get_regs_from_mc(®s, mc); regs.is_user = 0; unblock_signals(); - timer_handler(SIGVTALRM, ®s); + timer_handler(SIGVTALRM, NULL, ®s); } -void alarm_handler(int sig, mcontext_t *mc) +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) { int enabled; @@ -119,7 +120,7 @@ void set_sigstack(void *sig_stack, int s panic("enabling signal stack failed, errno = %d\n", errno); } -static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { +static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { [SIGSEGV] = sig_handler, [SIGBUS] = sig_handler, [SIGILL] = sig_handler, @@ -132,7 +133,7 @@ static void (*handlers[_NSIG])(int sig, }; -static void hard_handler(int sig, siginfo_t *info, void *p) +static void hard_handler(int sig, siginfo_t *si, void *p) { struct ucontext *uc = p; mcontext_t *mc = &uc->uc_mcontext; @@ -161,7 +162,7 @@ static void hard_handler(int sig, siginf while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); - (*handlers[sig])(sig, mc); + (*handlers[sig])(sig, si, mc); } /* @@ -273,9 +274,12 @@ void unblock_signals(void) * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. + * + * SIGIO's handler doesn't use siginfo or mcontext, + * so they can be NULL. */ if (save_pending & SIGIO_MASK) - sig_handler_common(SIGIO, NULL); + sig_handler_common(SIGIO, NULL, NULL); if (save_pending & SIGVTALRM_MASK) real_alarm_handler(NULL); diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/skas/process.c linux-3.4.1-mod/arch/um/os-Linux/skas/process.c --- linux-3.4.1/arch/um/os-Linux/skas/process.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/skas/process.c 2012-06-15 13:56:58.261111142 +0300 @@ -346,6 +346,7 @@ void userspace(struct uml_pt_regs *regs) int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; + siginfo_t si; if (getitimer(ITIMER_VIRTUAL, &timer)) printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); @@ -404,13 +405,17 @@ void userspace(struct uml_pt_regs *regs) if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); + + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); + switch (sig) { case SIGSEGV: if (PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); - (*sig_info[SIGSEGV])(SIGSEGV, regs); + (*sig_info[SIGSEGV])(SIGSEGV, &si, + regs); } else handle_segv(pid, regs); break; @@ -418,14 +423,14 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: - relay_signal(SIGTRAP, regs); + relay_signal(SIGTRAP, &si, regs); break; case SIGVTALRM: now = os_nsecs(); if (now < nsecs) break; block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + @@ -439,7 +444,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, &si, regs); unblock_signals(); break; default: diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/time.c linux-3.4.1-mod/arch/um/os-Linux/time.c --- linux-3.4.1/arch/um/os-Linux/time.c 2012-06-01 10:18:44.000000000 +0300 +++ linux-3.4.1-mod/arch/um/os-Linux/time.c 2012-06-21 10:33:21.748320666 +0300 @@ -87,7 +87,7 @@ static int after_sleep_interval(struct t static void deliver_alarm(void) { - alarm_handler(SIGVTALRM, NULL); + alarm_handler(SIGVTALRM, NULL, NULL); } static unsigned long long sleep_time(unsigned long long nsecs) |
From: Martin P. <mar...@gm...> - 2012-07-31 12:05:25
|
What's the status with this? On 06/21/2012 11:09 AM, Martin Pärtel wrote: > UML guest processes now get correct siginfo_t for SIGTRAP, SIGFPE, > SIGILL and SIGBUS. Specifically, si_addr and si_code are now correct > where previously they were si_addr = NULL and si_code = 128. > > Signed-off-by: Martin Pärtel <mar...@gm...> > --- > Removed _ignore_siginfo wrappers as requested. > > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/as-layout.h linux-3.4.1-mod/arch/um/include/shared/as-layout.h > --- linux-3.4.1/arch/um/include/shared/as-layout.h 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/include/shared/as-layout.h 2012-06-15 13:55:32.817111341 +0300 > @@ -60,7 +60,8 @@ extern unsigned long host_task_size; > > extern int linux_main(int argc, char **argv); > > -extern void (*sig_info[])(int, struct uml_pt_regs *); > +struct siginfo; > +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); > > #endif > > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/irq_user.h linux-3.4.1-mod/arch/um/include/shared/irq_user.h > --- linux-3.4.1/arch/um/include/shared/irq_user.h 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/include/shared/irq_user.h 2012-06-21 10:40:17.579071501 +0300 > @@ -20,7 +20,8 @@ struct irq_fd { > > enum { IRQ_READ, IRQ_WRITE }; > > -extern void sigio_handler(int sig, struct uml_pt_regs *regs); > +struct siginfo; > +extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); > extern void free_irq_by_fd(int fd); > extern void reactivate_fd(int fd, int irqnum); > extern void deactivate_fd(int fd, int irqnum); > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/include/shared/kern_util.h linux-3.4.1-mod/arch/um/include/shared/kern_util.h > --- linux-3.4.1/arch/um/include/shared/kern_util.h 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/include/shared/kern_util.h 2012-06-21 10:31:23.204318601 +0300 > @@ -9,6 +9,8 @@ > #include "sysdep/ptrace.h" > #include "sysdep/faultinfo.h" > > +struct siginfo; > + > extern int uml_exitcode; > > extern int ncpus; > @@ -22,7 +24,7 @@ extern void free_stack(unsigned long sta > > extern int do_signal(void); > extern void interrupt_end(void); > -extern void relay_signal(int sig, struct uml_pt_regs *regs); > +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); > > extern unsigned long segv(struct faultinfo fi, unsigned long ip, > int is_user, struct uml_pt_regs *regs); > @@ -33,9 +35,8 @@ extern unsigned int do_IRQ(int irq, stru > extern int smp_sigio_handler(void); > extern void initial_thread_cb(void (*proc)(void *), void *arg); > extern int is_syscall(unsigned long addr); > -extern void timer_handler(int sig, struct uml_pt_regs *regs); > > -extern void timer_handler(int sig, struct uml_pt_regs *regs); > +extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); > > extern int start_uml(void); > extern void paging_init(void); > @@ -59,9 +60,9 @@ extern unsigned long from_irq_stack(int > extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); > extern int singlestepping(void *t); > > -extern void segv_handler(int sig, struct uml_pt_regs *regs); > -extern void bus_handler(int sig, struct uml_pt_regs *regs); > -extern void winch(int sig, struct uml_pt_regs *regs); > +extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); > +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); > +extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); > extern void fatal_sigsegv(void) __attribute__ ((noreturn)); > > > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/irq.c linux-3.4.1-mod/arch/um/kernel/irq.c > --- linux-3.4.1/arch/um/kernel/irq.c 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/kernel/irq.c 2012-06-21 10:30:42.036317885 +0300 > @@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &a > > extern void free_irqs(void); > > -void sigio_handler(int sig, struct uml_pt_regs *regs) > +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) > { > struct irq_fd *irq_fd; > int n; > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/time.c linux-3.4.1-mod/arch/um/kernel/time.c > --- linux-3.4.1/arch/um/kernel/time.c 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/kernel/time.c 2012-06-21 10:31:15.852318471 +0300 > @@ -13,7 +13,7 @@ > #include "kern_util.h" > #include "os.h" > > -void timer_handler(int sig, struct uml_pt_regs *regs) > +void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) > { > unsigned long flags; > > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/kernel/trap.c linux-3.4.1-mod/arch/um/kernel/trap.c > --- linux-3.4.1/arch/um/kernel/trap.c 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/kernel/trap.c 2012-06-21 10:30:13.880317394 +0300 > @@ -158,7 +158,7 @@ void fatal_sigsegv(void) > os_dump_core(); > } > > -void segv_handler(int sig, struct uml_pt_regs *regs) > +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) > { > struct faultinfo * fi = UPT_FAULTINFO(regs); > > @@ -244,8 +244,11 @@ unsigned long segv(struct faultinfo fi, > return 0; > } > > -void relay_signal(int sig, struct uml_pt_regs *regs) > +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) > { > + struct faultinfo *fi; > + struct siginfo clean_si; > + > if (!UPT_IS_USER(regs)) { > if (sig == SIGBUS) > printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " > @@ -255,18 +258,40 @@ void relay_signal(int sig, struct uml_pt > > arch_examine_signal(sig, regs); > > - current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); > - force_sig(sig, current); > + memset(&clean_si, 0, sizeof(clean_si)); > + clean_si.si_signo = si->si_signo; > + clean_si.si_errno = si->si_errno; > + clean_si.si_code = si->si_code; > + switch (sig) { > + case SIGILL: > + case SIGFPE: > + case SIGSEGV: > + case SIGBUS: > + case SIGTRAP: > + fi = UPT_FAULTINFO(regs); > + clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); > + current->thread.arch.faultinfo = *fi; > +#ifdef __ARCH_SI_TRAPNO > + clean_si.si_trapno = si->si_trapno; > +#endif > + break; > + default: > + printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", > + sig, si->si_code); > + } > + > + force_sig_info(sig, &clean_si, current); > } > > -void bus_handler(int sig, struct uml_pt_regs *regs) > +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) > { > if (current->thread.fault_catcher != NULL) > UML_LONGJMP(current->thread.fault_catcher, 1); > - else relay_signal(sig, regs); > + else > + relay_signal(sig, si, regs); > } > > -void winch(int sig, struct uml_pt_regs *regs) > +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) > { > do_IRQ(WINCH_IRQ, regs); > } > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/internal.h linux-3.4.1-mod/arch/um/os-Linux/internal.h > --- linux-3.4.1/arch/um/os-Linux/internal.h 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/os-Linux/internal.h 2012-06-21 10:32:11.956319450 +0300 > @@ -1 +1 @@ > -void alarm_handler(int, mcontext_t *); > +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc); > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/signal.c linux-3.4.1-mod/arch/um/os-Linux/signal.c > --- linux-3.4.1/arch/um/os-Linux/signal.c 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/os-Linux/signal.c 2012-06-21 10:34:42.668322074 +0300 > @@ -13,8 +13,9 @@ > #include "kern_util.h" > #include "os.h" > #include "sysdep/mcontext.h" > +#include "internal.h" > > -void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { > +void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = { > [SIGTRAP] = relay_signal, > [SIGFPE] = relay_signal, > [SIGILL] = relay_signal, > @@ -24,7 +25,7 @@ void (*sig_info[NSIG])(int, struct uml_p > [SIGIO] = sigio_handler, > [SIGVTALRM] = timer_handler }; > > -static void sig_handler_common(int sig, mcontext_t *mc) > +static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc) > { > struct uml_pt_regs r; > int save_errno = errno; > @@ -40,7 +41,7 @@ static void sig_handler_common(int sig, > if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) > unblock_signals(); > > - (*sig_info[sig])(sig, &r); > + (*sig_info[sig])(sig, si, &r); > > errno = save_errno; > } > @@ -60,7 +61,7 @@ static void sig_handler_common(int sig, > static int signals_enabled; > static unsigned int signals_pending; > > -void sig_handler(int sig, mcontext_t *mc) > +void sig_handler(int sig, siginfo_t *si, mcontext_t *mc) > { > int enabled; > > @@ -72,7 +73,7 @@ void sig_handler(int sig, mcontext_t *mc > > block_signals(); > > - sig_handler_common(sig, mc); > + sig_handler_common(sig, si, mc); > > set_signals(enabled); > } > @@ -85,10 +86,10 @@ static void real_alarm_handler(mcontext_ > get_regs_from_mc(®s, mc); > regs.is_user = 0; > unblock_signals(); > - timer_handler(SIGVTALRM, ®s); > + timer_handler(SIGVTALRM, NULL, ®s); > } > > -void alarm_handler(int sig, mcontext_t *mc) > +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) > { > int enabled; > > @@ -119,7 +120,7 @@ void set_sigstack(void *sig_stack, int s > panic("enabling signal stack failed, errno = %d\n", errno); > } > > -static void (*handlers[_NSIG])(int sig, mcontext_t *mc) = { > +static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = { > [SIGSEGV] = sig_handler, > [SIGBUS] = sig_handler, > [SIGILL] = sig_handler, > @@ -132,7 +133,7 @@ static void (*handlers[_NSIG])(int sig, > }; > > > -static void hard_handler(int sig, siginfo_t *info, void *p) > +static void hard_handler(int sig, siginfo_t *si, void *p) > { > struct ucontext *uc = p; > mcontext_t *mc = &uc->uc_mcontext; > @@ -161,7 +162,7 @@ static void hard_handler(int sig, siginf > while ((sig = ffs(pending)) != 0){ > sig--; > pending &= ~(1 << sig); > - (*handlers[sig])(sig, mc); > + (*handlers[sig])(sig, si, mc); > } > > /* > @@ -273,9 +274,12 @@ void unblock_signals(void) > * Deal with SIGIO first because the alarm handler might > * schedule, leaving the pending SIGIO stranded until we come > * back here. > + * > + * SIGIO's handler doesn't use siginfo or mcontext, > + * so they can be NULL. > */ > if (save_pending & SIGIO_MASK) > - sig_handler_common(SIGIO, NULL); > + sig_handler_common(SIGIO, NULL, NULL); > > if (save_pending & SIGVTALRM_MASK) > real_alarm_handler(NULL); > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/skas/process.c linux-3.4.1-mod/arch/um/os-Linux/skas/process.c > --- linux-3.4.1/arch/um/os-Linux/skas/process.c 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/os-Linux/skas/process.c 2012-06-15 13:56:58.261111142 +0300 > @@ -346,6 +346,7 @@ void userspace(struct uml_pt_regs *regs) > int err, status, op, pid = userspace_pid[0]; > /* To prevent races if using_sysemu changes under us.*/ > int local_using_sysemu; > + siginfo_t si; > > if (getitimer(ITIMER_VIRTUAL, &timer)) > printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); > @@ -404,13 +405,17 @@ void userspace(struct uml_pt_regs *regs) > > if (WIFSTOPPED(status)) { > int sig = WSTOPSIG(status); > + > + ptrace(PTRACE_GETSIGINFO, pid, 0, &si); > + > switch (sig) { > case SIGSEGV: > if (PTRACE_FULL_FAULTINFO || > !ptrace_faultinfo) { > get_skas_faultinfo(pid, > ®s->faultinfo); > - (*sig_info[SIGSEGV])(SIGSEGV, regs); > + (*sig_info[SIGSEGV])(SIGSEGV, &si, > + regs); > } > else handle_segv(pid, regs); > break; > @@ -418,14 +423,14 @@ void userspace(struct uml_pt_regs *regs) > handle_trap(pid, regs, local_using_sysemu); > break; > case SIGTRAP: > - relay_signal(SIGTRAP, regs); > + relay_signal(SIGTRAP, &si, regs); > break; > case SIGVTALRM: > now = os_nsecs(); > if (now < nsecs) > break; > block_signals(); > - (*sig_info[sig])(sig, regs); > + (*sig_info[sig])(sig, &si, regs); > unblock_signals(); > nsecs = timer.it_value.tv_sec * > UM_NSEC_PER_SEC + > @@ -439,7 +444,7 @@ void userspace(struct uml_pt_regs *regs) > case SIGFPE: > case SIGWINCH: > block_signals(); > - (*sig_info[sig])(sig, regs); > + (*sig_info[sig])(sig, &si, regs); > unblock_signals(); > break; > default: > diff -uprN -X linux-3.4.1/Documentation/dontdiff -x config.c -x config.tmp linux-3.4.1/arch/um/os-Linux/time.c linux-3.4.1-mod/arch/um/os-Linux/time.c > --- linux-3.4.1/arch/um/os-Linux/time.c 2012-06-01 10:18:44.000000000 +0300 > +++ linux-3.4.1-mod/arch/um/os-Linux/time.c 2012-06-21 10:33:21.748320666 +0300 > @@ -87,7 +87,7 @@ static int after_sleep_interval(struct t > > static void deliver_alarm(void) > { > - alarm_handler(SIGVTALRM, NULL); > + alarm_handler(SIGVTALRM, NULL, NULL); > } > > static unsigned long long sleep_time(unsigned long long nsecs) > |
From: Richard W. <ri...@no...> - 2012-07-31 12:11:48
|
On 31.07.2012 14:05, Martin Pärtel wrote: > What's the status with this? > Oh sorry, I forgot you to answer. It's queued for 3.6 and will be pushed to Linus tomorrow with all other patches. Thanks, //richard |
From: Martin P. <mar...@gm...> - 2012-07-31 12:12:40
|
On 07/31/2012 03:11 PM, Richard Weinberger wrote: > On 31.07.2012 14:05, Martin Pärtel wrote: >> What's the status with this? >> > > Oh sorry, I forgot you to answer. > It's queued for 3.6 and will be pushed to Linus tomorrow with all other > patches. > Cool, thanks! |