blob: 804a074a94a876ea5f2684613323cce54ee5b755 [file] [log] [blame]
Michal Simek2148daa92009-03-27 14:25:14 +01001/*
2 * Signal handling
3 *
4 * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
5 * Copyright (C) 2008-2009 PetaLogix
6 * Copyright (C) 2003,2004 John Williams <jwilliams@itee.uq.edu.au>
7 * Copyright (C) 2001 NEC Corporation
8 * Copyright (C) 2001 Miles Bader <miles@gnu.org>
9 * Copyright (C) 1999,2000 Niibe Yutaka & Kaz Kojima
10 * Copyright (C) 1991,1992 Linus Torvalds
11 *
12 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
13 *
14 * This file was was derived from the sh version, arch/sh/kernel/signal.c
15 *
16 * This file is subject to the terms and conditions of the GNU General
17 * Public License. See the file COPYING in the main directory of this
18 * archive for more details.
19 */
20
21#include <linux/sched.h>
22#include <linux/mm.h>
23#include <linux/smp.h>
24#include <linux/smp_lock.h>
25#include <linux/kernel.h>
26#include <linux/signal.h>
27#include <linux/errno.h>
28#include <linux/wait.h>
29#include <linux/ptrace.h>
30#include <linux/unistd.h>
31#include <linux/stddef.h>
32#include <linux/personality.h>
33#include <linux/percpu.h>
34#include <linux/linkage.h>
35#include <asm/entry.h>
36#include <asm/ucontext.h>
37#include <linux/uaccess.h>
38#include <asm/pgtable.h>
39#include <asm/pgalloc.h>
Michal Simek2148daa92009-03-27 14:25:14 +010040#include <linux/syscalls.h>
41#include <asm/cacheflush.h>
42#include <asm/syscalls.h>
43
44#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
45
46asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
47
48/*
49 * Atomically swap in the new signal mask, and wait for a signal.
50 */
51asmlinkage int
52sys_sigsuspend(old_sigset_t mask, struct pt_regs *regs)
53{
54 sigset_t saveset;
55
56 mask &= _BLOCKABLE;
57 spin_lock_irq(&current->sighand->siglock);
58 saveset = current->blocked;
59 siginitset(&current->blocked, mask);
60 recalc_sigpending();
61 spin_unlock_irq(&current->sighand->siglock);
62
63 regs->r3 = -EINTR;
64 while (1) {
65 current->state = TASK_INTERRUPTIBLE;
66 schedule();
67 if (do_signal(regs, &saveset, 1))
68 return -EINTR;
69 }
70}
71
72asmlinkage int
73sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize,
74 struct pt_regs *regs)
75{
76 sigset_t saveset, newset;
77
78 /* XXX: Don't preclude handling different sized sigset_t's. */
79 if (sigsetsize != sizeof(sigset_t))
80 return -EINVAL;
81
82 if (copy_from_user(&newset, unewset, sizeof(newset)))
83 return -EFAULT;
84 sigdelsetmask(&newset, ~_BLOCKABLE);
85 spin_lock_irq(&current->sighand->siglock);
86 saveset = current->blocked;
87 current->blocked = newset;
88 recalc_sigpending();
89 spin_unlock_irq(&current->sighand->siglock);
90
91 regs->r3 = -EINTR;
92 while (1) {
93 current->state = TASK_INTERRUPTIBLE;
94 schedule();
95 if (do_signal(regs, &saveset, 1))
96 return -EINTR;
97 }
98}
99
100asmlinkage int
101sys_sigaction(int sig, const struct old_sigaction *act,
102 struct old_sigaction *oact)
103{
104 struct k_sigaction new_ka, old_ka;
105 int ret;
106
107 if (act) {
108 old_sigset_t mask;
109 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
110 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
111 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
112 return -EFAULT;
113 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
114 __get_user(mask, &act->sa_mask);
115 siginitset(&new_ka.sa.sa_mask, mask);
116 }
117
118 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
119
120 if (!ret && oact) {
121 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
122 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
123 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
124 return -EFAULT;
125 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
126 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
127 }
128
129 return ret;
130}
131
132asmlinkage int
133sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
134 struct pt_regs *regs)
135{
136 return do_sigaltstack(uss, uoss, regs->r1);
137}
138
139/*
140 * Do a signal return; undo the signal stack.
141 */
142
143struct sigframe {
144 struct sigcontext sc;
145 unsigned long extramask[_NSIG_WORDS-1];
146 unsigned long tramp[2]; /* signal trampoline */
147};
148
149struct rt_sigframe {
150 struct siginfo info;
151 struct ucontext uc;
152 unsigned long tramp[2]; /* signal trampoline */
153};
154
Arnd Bergmann353b4312009-05-01 13:37:46 +0000155static int restore_sigcontext(struct pt_regs *regs,
156 struct sigcontext __user *sc, int *rval_p)
Michal Simek2148daa92009-03-27 14:25:14 +0100157{
158 unsigned int err = 0;
159
160#define COPY(x) {err |= __get_user(regs->x, &sc->regs.x); }
161 COPY(r0);
162 COPY(r1);
163 COPY(r2); COPY(r3); COPY(r4); COPY(r5);
164 COPY(r6); COPY(r7); COPY(r8); COPY(r9);
165 COPY(r10); COPY(r11); COPY(r12); COPY(r13);
166 COPY(r14); COPY(r15); COPY(r16); COPY(r17);
167 COPY(r18); COPY(r19); COPY(r20); COPY(r21);
168 COPY(r22); COPY(r23); COPY(r24); COPY(r25);
169 COPY(r26); COPY(r27); COPY(r28); COPY(r29);
170 COPY(r30); COPY(r31);
171 COPY(pc); COPY(ear); COPY(esr); COPY(fsr);
172#undef COPY
173
174 *rval_p = regs->r3;
175
176 return err;
177}
178
179asmlinkage int sys_sigreturn(struct pt_regs *regs)
180{
Michal Simek2921e2b2009-04-21 14:08:47 +0200181 struct sigframe *frame =
182 (struct sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE);
183
Michal Simek2148daa92009-03-27 14:25:14 +0100184 sigset_t set;
185 int rval;
186
187 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
188 goto badframe;
189
190 if (__get_user(set.sig[0], &frame->sc.oldmask)
191 || (_NSIG_WORDS > 1
192 && __copy_from_user(&set.sig[1], &frame->extramask,
193 sizeof(frame->extramask))))
194 goto badframe;
195
196 sigdelsetmask(&set, ~_BLOCKABLE);
197
198 spin_lock_irq(&current->sighand->siglock);
199 current->blocked = set;
200 recalc_sigpending();
201 spin_unlock_irq(&current->sighand->siglock);
202
203 if (restore_sigcontext(regs, &frame->sc, &rval))
204 goto badframe;
205 return rval;
206
207badframe:
208 force_sig(SIGSEGV, current);
209 return 0;
210}
211
212asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
213{
Arnd Bergmann353b4312009-05-01 13:37:46 +0000214 struct rt_sigframe __user *frame =
215 (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
Michal Simek2921e2b2009-04-21 14:08:47 +0200216
Michal Simek2148daa92009-03-27 14:25:14 +0100217 sigset_t set;
Michal Simek2148daa92009-03-27 14:25:14 +0100218 int rval;
219
220 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
221 goto badframe;
222
223 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
224 goto badframe;
225
226 sigdelsetmask(&set, ~_BLOCKABLE);
227 spin_lock_irq(&current->sighand->siglock);
228 current->blocked = set;
229 recalc_sigpending();
230 spin_unlock_irq(&current->sighand->siglock);
231
232 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
233 goto badframe;
234
Michal Simek2148daa92009-03-27 14:25:14 +0100235 /* It is more difficult to avoid calling this function than to
236 call it and ignore errors. */
Arnd Bergmann353b4312009-05-01 13:37:46 +0000237 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1))
238 goto badframe;
Michal Simek2148daa92009-03-27 14:25:14 +0100239
240 return rval;
241
242badframe:
243 force_sig(SIGSEGV, current);
244 return 0;
245}
246
247/*
248 * Set up a signal frame.
249 */
250
251static int
Arnd Bergmann353b4312009-05-01 13:37:46 +0000252setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
Michal Simek2148daa92009-03-27 14:25:14 +0100253 unsigned long mask)
254{
255 int err = 0;
256
257#define COPY(x) {err |= __put_user(regs->x, &sc->regs.x); }
258 COPY(r0);
259 COPY(r1);
260 COPY(r2); COPY(r3); COPY(r4); COPY(r5);
261 COPY(r6); COPY(r7); COPY(r8); COPY(r9);
262 COPY(r10); COPY(r11); COPY(r12); COPY(r13);
263 COPY(r14); COPY(r15); COPY(r16); COPY(r17);
264 COPY(r18); COPY(r19); COPY(r20); COPY(r21);
265 COPY(r22); COPY(r23); COPY(r24); COPY(r25);
266 COPY(r26); COPY(r27); COPY(r28); COPY(r29);
267 COPY(r30); COPY(r31);
268 COPY(pc); COPY(ear); COPY(esr); COPY(fsr);
269#undef COPY
270
271 err |= __put_user(mask, &sc->oldmask);
272
273 return err;
274}
275
276/*
277 * Determine which stack to use..
278 */
Arnd Bergmann353b4312009-05-01 13:37:46 +0000279static inline void __user *
Michal Simek2148daa92009-03-27 14:25:14 +0100280get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
281{
282 /* Default to using normal stack */
283 unsigned long sp = regs->r1;
284
285 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
286 sp = current->sas_ss_sp + current->sas_ss_size;
287
Arnd Bergmann353b4312009-05-01 13:37:46 +0000288 return (void __user *)((sp - frame_size) & -8UL);
Michal Simek2148daa92009-03-27 14:25:14 +0100289}
290
291static void setup_frame(int sig, struct k_sigaction *ka,
292 sigset_t *set, struct pt_regs *regs)
293{
294 struct sigframe *frame;
295 int err = 0;
296 int signal;
297
298 frame = get_sigframe(ka, regs, sizeof(*frame));
299
300 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
301 goto give_sigsegv;
302
303 signal = current_thread_info()->exec_domain
304 && current_thread_info()->exec_domain->signal_invmap
305 && sig < 32
306 ? current_thread_info()->exec_domain->signal_invmap[sig]
307 : sig;
308
309 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
310
311 if (_NSIG_WORDS > 1) {
312 err |= __copy_to_user(frame->extramask, &set->sig[1],
313 sizeof(frame->extramask));
314 }
315
316 /* Set up to return from userspace. If provided, use a stub
317 already in userspace. */
318 /* minus 8 is offset to cater for "rtsd r15,8" offset */
319 if (ka->sa.sa_flags & SA_RESTORER) {
320 regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
321 } else {
322 /* Note, these encodings are _big endian_! */
323
324 /* addi r12, r0, __NR_sigreturn */
325 err |= __put_user(0x31800000 | __NR_sigreturn ,
326 frame->tramp + 0);
327 /* brki r14, 0x8 */
328 err |= __put_user(0xb9cc0008, frame->tramp + 1);
329
330 /* Return from sighandler will jump to the tramp.
331 Negative 8 offset because return is rtsd r15, 8 */
332 regs->r15 = ((unsigned long)frame->tramp)-8;
333
334 __invalidate_cache_sigtramp((unsigned long)frame->tramp);
335 }
336
337 if (err)
338 goto give_sigsegv;
339
340 /* Set up registers for signal handler */
Michal Simek2921e2b2009-04-21 14:08:47 +0200341 regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
342
Michal Simek2148daa92009-03-27 14:25:14 +0100343 /* Signal handler args: */
344 regs->r5 = signal; /* Arg 0: signum */
345 regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */
346
347 /* Offset of 4 to handle microblaze rtid r14, 0 */
348 regs->pc = (unsigned long)ka->sa.sa_handler;
349
350 set_fs(USER_DS);
351
352#ifdef DEBUG_SIG
353 printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
354 current->comm, current->pid, frame, regs->pc);
355#endif
356
357 return;
358
359give_sigsegv:
360 if (sig == SIGSEGV)
361 ka->sa.sa_handler = SIG_DFL;
362 force_sig(SIGSEGV, current);
363}
364
365static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
366 sigset_t *set, struct pt_regs *regs)
367{
Arnd Bergmann353b4312009-05-01 13:37:46 +0000368 struct rt_sigframe __user *frame;
Michal Simek2148daa92009-03-27 14:25:14 +0100369 int err = 0;
370 int signal;
371
372 frame = get_sigframe(ka, regs, sizeof(*frame));
373
374 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
375 goto give_sigsegv;
376
377 signal = current_thread_info()->exec_domain
378 && current_thread_info()->exec_domain->signal_invmap
379 && sig < 32
380 ? current_thread_info()->exec_domain->signal_invmap[sig]
381 : sig;
382
383 err |= copy_siginfo_to_user(&frame->info, info);
384
385 /* Create the ucontext. */
386 err |= __put_user(0, &frame->uc.uc_flags);
387 err |= __put_user(0, &frame->uc.uc_link);
388 err |= __put_user((void *)current->sas_ss_sp,
389 &frame->uc.uc_stack.ss_sp);
390 err |= __put_user(sas_ss_flags(regs->r1),
391 &frame->uc.uc_stack.ss_flags);
392 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
393 err |= setup_sigcontext(&frame->uc.uc_mcontext,
394 regs, set->sig[0]);
395 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
396
397 /* Set up to return from userspace. If provided, use a stub
398 already in userspace. */
399 /* minus 8 is offset to cater for "rtsd r15,8" */
400 if (ka->sa.sa_flags & SA_RESTORER) {
401 regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
402 } else {
403 /* addi r12, r0, __NR_sigreturn */
404 err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
405 frame->tramp + 0);
406 /* brki r14, 0x8 */
407 err |= __put_user(0xb9cc0008, frame->tramp + 1);
408
409 /* Return from sighandler will jump to the tramp.
410 Negative 8 offset because return is rtsd r15, 8 */
411 regs->r15 = ((unsigned long)frame->tramp)-8;
412
413 __invalidate_cache_sigtramp((unsigned long)frame->tramp);
414 }
415
416 if (err)
417 goto give_sigsegv;
418
419 /* Set up registers for signal handler */
Michal Simek2921e2b2009-04-21 14:08:47 +0200420 regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
421
Michal Simek2148daa92009-03-27 14:25:14 +0100422 /* Signal handler args: */
423 regs->r5 = signal; /* arg 0: signum */
424 regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
425 regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
426 /* Offset to handle microblaze rtid r14, 0 */
427 regs->pc = (unsigned long)ka->sa.sa_handler;
428
429 set_fs(USER_DS);
430
431#ifdef DEBUG_SIG
432 printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
433 current->comm, current->pid, frame, regs->pc);
434#endif
435
436 return;
437
438give_sigsegv:
439 if (sig == SIGSEGV)
440 ka->sa.sa_handler = SIG_DFL;
441 force_sig(SIGSEGV, current);
442}
443
444/* Handle restarting system calls */
445static inline void
446handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
447{
448 switch (regs->r3) {
449 case -ERESTART_RESTARTBLOCK:
450 case -ERESTARTNOHAND:
451 if (!has_handler)
452 goto do_restart;
453 regs->r3 = -EINTR;
454 break;
455 case -ERESTARTSYS:
456 if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
457 regs->r3 = -EINTR;
458 break;
459 }
460 /* fallthrough */
461 case -ERESTARTNOINTR:
462do_restart:
463 /* offset of 4 bytes to re-execute trap (brki) instruction */
464 regs->pc -= 4;
465 break;
466 }
467}
468
469/*
470 * OK, we're invoking a handler
471 */
472
473static void
474handle_signal(unsigned long sig, struct k_sigaction *ka,
475 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
476{
477 /* Set up the stack frame */
478 if (ka->sa.sa_flags & SA_SIGINFO)
479 setup_rt_frame(sig, ka, info, oldset, regs);
480 else
481 setup_frame(sig, ka, oldset, regs);
482
483 if (ka->sa.sa_flags & SA_ONESHOT)
484 ka->sa.sa_handler = SIG_DFL;
485
486 if (!(ka->sa.sa_flags & SA_NODEFER)) {
487 spin_lock_irq(&current->sighand->siglock);
488 sigorsets(&current->blocked,
489 &current->blocked, &ka->sa.sa_mask);
490 sigaddset(&current->blocked, sig);
491 recalc_sigpending();
492 spin_unlock_irq(&current->sighand->siglock);
493 }
494}
495
496/*
497 * Note that 'init' is a special process: it doesn't get signals it doesn't
498 * want to handle. Thus you cannot kill init even with a SIGKILL even by
499 * mistake.
500 *
501 * Note that we go through the signals twice: once to check the signals that
502 * the kernel can handle, and then we build all the user-level signal handling
503 * stack-frames in one go after that.
504 */
505int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
506{
507 siginfo_t info;
508 int signr;
509 struct k_sigaction ka;
510#ifdef DEBUG_SIG
511 printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall);
512 printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
513 regs->r12, current_thread_info()->flags);
514#endif
515 /*
516 * We want the common case to go fast, which
517 * is why we may in certain cases get here from
518 * kernel mode. Just return without doing anything
519 * if so.
520 */
521 if (kernel_mode(regs))
522 return 1;
523
524 if (!oldset)
525 oldset = &current->blocked;
526
527 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
528 if (signr > 0) {
529 /* Whee! Actually deliver the signal. */
530 if (in_syscall)
531 handle_restart(regs, &ka, 1);
532 handle_signal(signr, &ka, &info, oldset, regs);
533 return 1;
534 }
535
536 if (in_syscall)
537 handle_restart(regs, NULL, 0);
538
539 /* Did we come from a system call? */
540 return 0;
541}