aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-04 18:23:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-04 18:23:48 -0400
commit93e95fa57441b6976b39029bd658b6bbe7ccfe28 (patch)
tree8b39587ea741e18a6d6b95deb864069d502839e6 /arch/um
parentd8aed8415b861d5b829742608400f772559b6739 (diff)
parent26da35010c6d6ce317d511c8186585bdd8ab6629 (diff)
Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull siginfo updates from Eric Biederman: "This set of changes close the known issues with setting si_code to an invalid value, and with not fully initializing struct siginfo. There remains work to do on nds32, arc, unicore32, powerpc, arm, arm64, ia64 and x86 to get the code that generates siginfo into a simpler and more maintainable state. Most of that work involves refactoring the signal handling code and thus careful code review. Also not included is the work to shrink the in kernel version of struct siginfo. That depends on getting the number of places that directly manipulate struct siginfo under control, as it requires the introduction of struct kernel_siginfo for the in kernel things. Overall this set of changes looks like it is making good progress, and with a little luck I will be wrapping up the siginfo work next development cycle" * 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (46 commits) signal/sh: Stop gcc warning about an impossible case in do_divide_error signal/mips: Report FPE_FLTUNK for undiagnosed floating point exceptions signal/um: More carefully relay signals in relay_signal. signal: Extend siginfo_layout with SIL_FAULT_{MCEERR|BNDERR|PKUERR} signal: Remove unncessary #ifdef SEGV_PKUERR in 32bit compat code signal/signalfd: Add support for SIGSYS signal/signalfd: Remove __put_user from signalfd_copyinfo signal/xtensa: Use force_sig_fault where appropriate signal/xtensa: Consistenly use SIGBUS in do_unaligned_user signal/um: Use force_sig_fault where appropriate signal/sparc: Use force_sig_fault where appropriate signal/sparc: Use send_sig_fault where appropriate signal/sh: Use force_sig_fault where appropriate signal/s390: Use force_sig_fault where appropriate signal/riscv: Replace do_trap_siginfo with force_sig_fault signal/riscv: Use force_sig_fault where appropriate signal/parisc: Use force_sig_fault where appropriate signal/parisc: Use force_sig_mceerr where appropriate signal/openrisc: Use force_sig_fault where appropriate signal/nios2: Use force_sig_fault where appropriate ...
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/kernel/ptrace.c13
-rw-r--r--arch/um/kernel/trap.c62
2 files changed, 25 insertions, 50 deletions
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index bc2a516c190f..1a1d88a4d940 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -115,17 +115,10 @@ long arch_ptrace(struct task_struct *child, long request,
115static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, 115static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
116 int error_code) 116 int error_code)
117{ 117{
118 struct siginfo info;
119
120 memset(&info, 0, sizeof(info));
121 info.si_signo = SIGTRAP;
122 info.si_code = TRAP_BRKPT;
123
124 /* User-mode eip? */
125 info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL;
126
127 /* Send us the fake SIGTRAP */ 118 /* Send us the fake SIGTRAP */
128 force_sig_info(SIGTRAP, &info, tsk); 119 force_sig_fault(SIGTRAP, TRAP_BRKPT,
120 /* User-mode eip? */
121 UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL, tsk);
129} 122}
130 123
131/* 124/*
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index b2b02df9896e..ec9a42c14c56 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -162,13 +162,9 @@ static void show_segv_info(struct uml_pt_regs *regs)
162 162
163static void bad_segv(struct faultinfo fi, unsigned long ip) 163static void bad_segv(struct faultinfo fi, unsigned long ip)
164{ 164{
165 struct siginfo si;
166
167 si.si_signo = SIGSEGV;
168 si.si_code = SEGV_ACCERR;
169 si.si_addr = (void __user *) FAULT_ADDRESS(fi);
170 current->thread.arch.faultinfo = fi; 165 current->thread.arch.faultinfo = fi;
171 force_sig_info(SIGSEGV, &si, current); 166 force_sig_fault(SIGSEGV, SEGV_ACCERR, (void __user *) FAULT_ADDRESS(fi),
167 current);
172} 168}
173 169
174void fatal_sigsegv(void) 170void fatal_sigsegv(void)
@@ -214,8 +210,8 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
214unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, 210unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
215 struct uml_pt_regs *regs) 211 struct uml_pt_regs *regs)
216{ 212{
217 struct siginfo si;
218 jmp_buf *catcher; 213 jmp_buf *catcher;
214 int si_code;
219 int err; 215 int err;
220 int is_write = FAULT_WRITE(fi); 216 int is_write = FAULT_WRITE(fi);
221 unsigned long address = FAULT_ADDRESS(fi); 217 unsigned long address = FAULT_ADDRESS(fi);
@@ -239,7 +235,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
239 235
240 if (SEGV_IS_FIXABLE(&fi)) 236 if (SEGV_IS_FIXABLE(&fi))
241 err = handle_page_fault(address, ip, is_write, is_user, 237 err = handle_page_fault(address, ip, is_write, is_user,
242 &si.si_code); 238 &si_code);
243 else { 239 else {
244 err = -EFAULT; 240 err = -EFAULT;
245 /* 241 /*
@@ -271,18 +267,14 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
271 show_segv_info(regs); 267 show_segv_info(regs);
272 268
273 if (err == -EACCES) { 269 if (err == -EACCES) {
274 si.si_signo = SIGBUS;
275 si.si_errno = 0;
276 si.si_code = BUS_ADRERR;
277 si.si_addr = (void __user *)address;
278 current->thread.arch.faultinfo = fi; 270 current->thread.arch.faultinfo = fi;
279 force_sig_info(SIGBUS, &si, current); 271 force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address,
272 current);
280 } else { 273 } else {
281 BUG_ON(err != -EFAULT); 274 BUG_ON(err != -EFAULT);
282 si.si_signo = SIGSEGV;
283 si.si_addr = (void __user *) address;
284 current->thread.arch.faultinfo = fi; 275 current->thread.arch.faultinfo = fi;
285 force_sig_info(SIGSEGV, &si, current); 276 force_sig_fault(SIGSEGV, si_code, (void __user *) address,
277 current);
286 } 278 }
287 279
288out: 280out:
@@ -294,9 +286,7 @@ out:
294 286
295void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) 287void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
296{ 288{
297 struct faultinfo *fi; 289 int code, err;
298 struct siginfo clean_si;
299
300 if (!UPT_IS_USER(regs)) { 290 if (!UPT_IS_USER(regs)) {
301 if (sig == SIGBUS) 291 if (sig == SIGBUS)
302 printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " 292 printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
@@ -306,29 +296,21 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
306 296
307 arch_examine_signal(sig, regs); 297 arch_examine_signal(sig, regs);
308 298
309 clear_siginfo(&clean_si); 299 /* Is the signal layout for the signal known?
310 clean_si.si_signo = si->si_signo; 300 * Signal data must be scrubbed to prevent information leaks.
311 clean_si.si_errno = si->si_errno; 301 */
312 clean_si.si_code = si->si_code; 302 code = si->si_code;
313 switch (sig) { 303 err = si->si_errno;
314 case SIGILL: 304 if ((err == 0) && (siginfo_layout(sig, code) == SIL_FAULT)) {
315 case SIGFPE: 305 struct faultinfo *fi = UPT_FAULTINFO(regs);
316 case SIGSEGV:
317 case SIGBUS:
318 case SIGTRAP:
319 fi = UPT_FAULTINFO(regs);
320 clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi);
321 current->thread.arch.faultinfo = *fi; 306 current->thread.arch.faultinfo = *fi;
322#ifdef __ARCH_SI_TRAPNO 307 force_sig_fault(sig, code, (void __user *)FAULT_ADDRESS(*fi),
323 clean_si.si_trapno = si->si_trapno; 308 current);
324#endif 309 } else {
325 break; 310 printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d) with errno %d\n",
326 default: 311 sig, code, err);
327 printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", 312 force_sig(sig, current);
328 sig, si->si_code);
329 } 313 }
330
331 force_sig_info(sig, &clean_si, current);
332} 314}
333 315
334void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) 316void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs)