aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/kernel
diff options
context:
space:
mode:
authorMartin Pärtel <martin.partel@gmail.com>2012-08-01 18:49:17 -0400
committerRichard Weinberger <richard@nod.at>2012-08-01 18:49:17 -0400
commitd3c1cfcdb43e023ab1b1c7a555cd9e929026500a (patch)
treead79f90d97a0316ae4058e4501e7b6ad54540ff4 /arch/um/kernel
parentd4afcba95fca4dd0f831fe72c1fa4f0638f23765 (diff)
um: pass siginfo to guest process
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 <martin.partel@gmail.com> Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/kernel')
-rw-r--r--arch/um/kernel/irq.c2
-rw-r--r--arch/um/kernel/time.c2
-rw-r--r--arch/um/kernel/trap.c39
3 files changed, 34 insertions, 9 deletions
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 00506c3d5d6e..9883026f0730 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &active_fds;
30 30
31extern void free_irqs(void); 31extern void free_irqs(void);
32 32
33void sigio_handler(int sig, struct uml_pt_regs *regs) 33void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
34{ 34{
35 struct irq_fd *irq_fd; 35 struct irq_fd *irq_fd;
36 int n; 36 int n;
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index d1a23fb3190d..5f76d4ba151c 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -13,7 +13,7 @@
13#include "kern_util.h" 13#include "kern_util.h"
14#include "os.h" 14#include "os.h"
15 15
16void timer_handler(int sig, struct uml_pt_regs *regs) 16void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
17{ 17{
18 unsigned long flags; 18 unsigned long flags;
19 19
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 3be60765c0e2..0353b98ae35a 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -172,7 +172,7 @@ void fatal_sigsegv(void)
172 os_dump_core(); 172 os_dump_core();
173} 173}
174 174
175void segv_handler(int sig, struct uml_pt_regs *regs) 175void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
176{ 176{
177 struct faultinfo * fi = UPT_FAULTINFO(regs); 177 struct faultinfo * fi = UPT_FAULTINFO(regs);
178 178
@@ -258,8 +258,11 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
258 return 0; 258 return 0;
259} 259}
260 260
261void relay_signal(int sig, struct uml_pt_regs *regs) 261void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
262{ 262{
263 struct faultinfo *fi;
264 struct siginfo clean_si;
265
263 if (!UPT_IS_USER(regs)) { 266 if (!UPT_IS_USER(regs)) {
264 if (sig == SIGBUS) 267 if (sig == SIGBUS)
265 printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " 268 printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -269,18 +272,40 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
269 272
270 arch_examine_signal(sig, regs); 273 arch_examine_signal(sig, regs);
271 274
272 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); 275 memset(&clean_si, 0, sizeof(clean_si));
273 force_sig(sig, current); 276 clean_si.si_signo = si->si_signo;
277 clean_si.si_errno = si->si_errno;
278 clean_si.si_code = si->si_code;
279 switch (sig) {
280 case SIGILL:
281 case SIGFPE:
282 case SIGSEGV:
283 case SIGBUS:
284 case SIGTRAP:
285 fi = UPT_FAULTINFO(regs);
286 clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi);
287 current->thread.arch.faultinfo = *fi;
288#ifdef __ARCH_SI_TRAPNO
289 clean_si.si_trapno = si->si_trapno;
290#endif
291 break;
292 default:
293 printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n",
294 sig, si->si_code);
295 }
296
297 force_sig_info(sig, &clean_si, current);
274} 298}
275 299
276void bus_handler(int sig, struct uml_pt_regs *regs) 300void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs)
277{ 301{
278 if (current->thread.fault_catcher != NULL) 302 if (current->thread.fault_catcher != NULL)
279 UML_LONGJMP(current->thread.fault_catcher, 1); 303 UML_LONGJMP(current->thread.fault_catcher, 1);
280 else relay_signal(sig, regs); 304 else
305 relay_signal(sig, si, regs);
281} 306}
282 307
283void winch(int sig, struct uml_pt_regs *regs) 308void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
284{ 309{
285 do_IRQ(WINCH_IRQ, regs); 310 do_IRQ(WINCH_IRQ, regs);
286} 311}