blob: 74b05e6ed44153e9b4d1841a43e64db948304237 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/arch/alpha/kernel/signal.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 *
6 * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson
7 */
8
9#include <linux/sched.h>
10#include <linux/kernel.h>
11#include <linux/signal.h>
12#include <linux/errno.h>
13#include <linux/wait.h>
14#include <linux/ptrace.h>
15#include <linux/unistd.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/stddef.h>
19#include <linux/tty.h>
20#include <linux/binfmts.h>
21#include <linux/bitops.h>
Ivan Kokshayskye5d9a902009-01-29 14:25:18 -080022#include <linux/syscalls.h>
David Howells733e5e42009-09-09 08:30:21 +010023#include <linux/tracehook.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#include <asm/uaccess.h>
26#include <asm/sigcontext.h>
27#include <asm/ucontext.h>
28
29#include "proto.h"
30
31
32#define DEBUG_SIG 0
33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35
36asmlinkage void ret_from_sys_call(void);
Richard Hendersonb927b3e2007-05-29 16:03:28 -070037static void do_signal(struct pt_regs *, struct switch_stack *,
38 unsigned long, unsigned long);
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40
41/*
42 * The OSF/1 sigprocmask calling sequence is different from the
43 * C sigprocmask() sequence..
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 */
Al Viroc52c2dd2010-09-26 19:28:12 +010045SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsigned long, newmask)
Linus Torvalds1da177e2005-04-16 15:20:36 -070046{
Al Viroc52c2dd2010-09-26 19:28:12 +010047 sigset_t oldmask;
48 sigset_t mask;
49 unsigned long res;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Linus Torvalds87400e52010-09-30 08:37:38 -070051 siginitset(&mask, newmask & _BLOCKABLE);
Linus Torvalds0f44fbd2010-09-28 13:26:57 -070052 res = sigprocmask(how, &mask, &oldmask);
Al Viroc52c2dd2010-09-26 19:28:12 +010053 if (!res) {
54 force_successful_syscall_return();
Linus Torvalds0f44fbd2010-09-28 13:26:57 -070055 res = oldmask.sig[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -070056 }
Al Viroc52c2dd2010-09-26 19:28:12 +010057 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -070058}
59
Ivan Kokshayskye5d9a902009-01-29 14:25:18 -080060SYSCALL_DEFINE3(osf_sigaction, int, sig,
61 const struct osf_sigaction __user *, act,
62 struct osf_sigaction __user *, oact)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063{
64 struct k_sigaction new_ka, old_ka;
65 int ret;
66
67 if (act) {
68 old_sigset_t mask;
69 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
70 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
Al Viro18e6bfa2010-09-26 19:28:22 +010071 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
72 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 siginitset(&new_ka.sa.sa_mask, mask);
75 new_ka.ka_restorer = NULL;
76 }
77
78 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
79
80 if (!ret && oact) {
81 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
82 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
Al Viro18e6bfa2010-09-26 19:28:22 +010083 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
84 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 }
87
88 return ret;
89}
90
Ivan Kokshayskye5d9a902009-01-29 14:25:18 -080091SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
92 struct sigaction __user *, oact,
93 size_t, sigsetsize, void __user *, restorer)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
95 struct k_sigaction new_ka, old_ka;
96 int ret;
97
98 /* XXX: Don't preclude handling different sized sigset_t's. */
99 if (sigsetsize != sizeof(sigset_t))
100 return -EINVAL;
101
102 if (act) {
103 new_ka.ka_restorer = restorer;
104 if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
105 return -EFAULT;
106 }
107
108 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
109
110 if (!ret && oact) {
111 if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
112 return -EFAULT;
113 }
114
115 return ret;
116}
117
118/*
119 * Atomically swap in the new signal mask, and wait for a signal.
120 */
Al Viro392fb6e2010-09-18 08:40:07 -0400121SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122{
Matt Fleming2561b062012-04-05 14:25:12 -0700123 sigset_t blocked;
Matt Fleming2561b062012-04-05 14:25:12 -0700124 siginitset(&blocked, mask);
Al Viro68f3f162012-05-21 21:42:32 -0400125 return sigsuspend(&blocked);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126}
127
128asmlinkage int
129sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
130{
131 return do_sigaltstack(uss, uoss, rdusp());
132}
133
134/*
135 * Do a signal return; undo the signal stack.
136 */
137
138#if _NSIG_WORDS > 1
139# error "Non SA_SIGINFO frame needs rearranging"
140#endif
141
142struct sigframe
143{
144 struct sigcontext sc;
145 unsigned int retcode[3];
146};
147
148struct rt_sigframe
149{
150 struct siginfo info;
151 struct ucontext uc;
152 unsigned int retcode[3];
153};
154
155/* If this changes, userland unwinders that Know Things about our signal
156 frame will break. Do not undertake lightly. It also implies an ABI
157 change wrt the size of siginfo_t, which may cause some pain. */
158extern char compile_time_assert
159 [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
160
161#define INSN_MOV_R30_R16 0x47fe0410
162#define INSN_LDI_R0 0x201f0000
163#define INSN_CALLSYS 0x00000083
164
165static long
166restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
167 struct switch_stack *sw)
168{
169 unsigned long usp;
170 long i, err = __get_user(regs->pc, &sc->sc_pc);
171
Al Viro2deba1b2010-09-18 08:38:47 -0400172 current_thread_info()->restart_block.fn = do_no_restart_syscall;
173
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 sw->r26 = (unsigned long) ret_from_sys_call;
175
176 err |= __get_user(regs->r0, sc->sc_regs+0);
177 err |= __get_user(regs->r1, sc->sc_regs+1);
178 err |= __get_user(regs->r2, sc->sc_regs+2);
179 err |= __get_user(regs->r3, sc->sc_regs+3);
180 err |= __get_user(regs->r4, sc->sc_regs+4);
181 err |= __get_user(regs->r5, sc->sc_regs+5);
182 err |= __get_user(regs->r6, sc->sc_regs+6);
183 err |= __get_user(regs->r7, sc->sc_regs+7);
184 err |= __get_user(regs->r8, sc->sc_regs+8);
185 err |= __get_user(sw->r9, sc->sc_regs+9);
186 err |= __get_user(sw->r10, sc->sc_regs+10);
187 err |= __get_user(sw->r11, sc->sc_regs+11);
188 err |= __get_user(sw->r12, sc->sc_regs+12);
189 err |= __get_user(sw->r13, sc->sc_regs+13);
190 err |= __get_user(sw->r14, sc->sc_regs+14);
191 err |= __get_user(sw->r15, sc->sc_regs+15);
192 err |= __get_user(regs->r16, sc->sc_regs+16);
193 err |= __get_user(regs->r17, sc->sc_regs+17);
194 err |= __get_user(regs->r18, sc->sc_regs+18);
195 err |= __get_user(regs->r19, sc->sc_regs+19);
196 err |= __get_user(regs->r20, sc->sc_regs+20);
197 err |= __get_user(regs->r21, sc->sc_regs+21);
198 err |= __get_user(regs->r22, sc->sc_regs+22);
199 err |= __get_user(regs->r23, sc->sc_regs+23);
200 err |= __get_user(regs->r24, sc->sc_regs+24);
201 err |= __get_user(regs->r25, sc->sc_regs+25);
202 err |= __get_user(regs->r26, sc->sc_regs+26);
203 err |= __get_user(regs->r27, sc->sc_regs+27);
204 err |= __get_user(regs->r28, sc->sc_regs+28);
205 err |= __get_user(regs->gp, sc->sc_regs+29);
206 err |= __get_user(usp, sc->sc_regs+30);
207 wrusp(usp);
208
209 for (i = 0; i < 31; i++)
210 err |= __get_user(sw->fp[i], sc->sc_fpregs+i);
211 err |= __get_user(sw->fp[31], &sc->sc_fpcr);
212
213 return err;
214}
215
216/* Note that this syscall is also used by setcontext(3) to install
217 a given sigcontext. This because it's impossible to set *all*
218 registers and transfer control from userland. */
219
220asmlinkage void
221do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
222 struct switch_stack *sw)
223{
224 sigset_t set;
225
226 /* Verify that it's a good sigcontext before using it */
227 if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
228 goto give_sigsegv;
229 if (__get_user(set.sig[0], &sc->sc_mask))
230 goto give_sigsegv;
231
232 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming2561b062012-04-05 14:25:12 -0700233 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
235 if (restore_sigcontext(sc, regs, sw))
236 goto give_sigsegv;
237
238 /* Send SIGTRAP if we're single-stepping: */
239 if (ptrace_cancel_bpt (current)) {
240 siginfo_t info;
241
242 info.si_signo = SIGTRAP;
243 info.si_errno = 0;
244 info.si_code = TRAP_BRKPT;
245 info.si_addr = (void __user *) regs->pc;
246 info.si_trapno = 0;
247 send_sig_info(SIGTRAP, &info, current);
248 }
249 return;
250
251give_sigsegv:
252 force_sig(SIGSEGV, current);
253}
254
255asmlinkage void
256do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
257 struct switch_stack *sw)
258{
259 sigset_t set;
260
261 /* Verify that it's a good ucontext_t before using it */
262 if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
263 goto give_sigsegv;
264 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
265 goto give_sigsegv;
266
267 sigdelsetmask(&set, ~_BLOCKABLE);
Matt Fleming2561b062012-04-05 14:25:12 -0700268 set_current_blocked(&set);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
270 if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
271 goto give_sigsegv;
272
273 /* Send SIGTRAP if we're single-stepping: */
274 if (ptrace_cancel_bpt (current)) {
275 siginfo_t info;
276
277 info.si_signo = SIGTRAP;
278 info.si_errno = 0;
279 info.si_code = TRAP_BRKPT;
280 info.si_addr = (void __user *) regs->pc;
281 info.si_trapno = 0;
282 send_sig_info(SIGTRAP, &info, current);
283 }
284 return;
285
286give_sigsegv:
287 force_sig(SIGSEGV, current);
288}
289
290
291/*
292 * Set up a signal frame.
293 */
294
295static inline void __user *
296get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
297{
Laurent MEYERd09042d2006-06-23 02:05:36 -0700298 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 sp = current->sas_ss_sp + current->sas_ss_size;
300
301 return (void __user *)((sp - frame_size) & -32ul);
302}
303
304static long
305setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
306 struct switch_stack *sw, unsigned long mask, unsigned long sp)
307{
308 long i, err = 0;
309
310 err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
311 err |= __put_user(mask, &sc->sc_mask);
312 err |= __put_user(regs->pc, &sc->sc_pc);
313 err |= __put_user(8, &sc->sc_ps);
314
315 err |= __put_user(regs->r0 , sc->sc_regs+0);
316 err |= __put_user(regs->r1 , sc->sc_regs+1);
317 err |= __put_user(regs->r2 , sc->sc_regs+2);
318 err |= __put_user(regs->r3 , sc->sc_regs+3);
319 err |= __put_user(regs->r4 , sc->sc_regs+4);
320 err |= __put_user(regs->r5 , sc->sc_regs+5);
321 err |= __put_user(regs->r6 , sc->sc_regs+6);
322 err |= __put_user(regs->r7 , sc->sc_regs+7);
323 err |= __put_user(regs->r8 , sc->sc_regs+8);
324 err |= __put_user(sw->r9 , sc->sc_regs+9);
325 err |= __put_user(sw->r10 , sc->sc_regs+10);
326 err |= __put_user(sw->r11 , sc->sc_regs+11);
327 err |= __put_user(sw->r12 , sc->sc_regs+12);
328 err |= __put_user(sw->r13 , sc->sc_regs+13);
329 err |= __put_user(sw->r14 , sc->sc_regs+14);
330 err |= __put_user(sw->r15 , sc->sc_regs+15);
331 err |= __put_user(regs->r16, sc->sc_regs+16);
332 err |= __put_user(regs->r17, sc->sc_regs+17);
333 err |= __put_user(regs->r18, sc->sc_regs+18);
334 err |= __put_user(regs->r19, sc->sc_regs+19);
335 err |= __put_user(regs->r20, sc->sc_regs+20);
336 err |= __put_user(regs->r21, sc->sc_regs+21);
337 err |= __put_user(regs->r22, sc->sc_regs+22);
338 err |= __put_user(regs->r23, sc->sc_regs+23);
339 err |= __put_user(regs->r24, sc->sc_regs+24);
340 err |= __put_user(regs->r25, sc->sc_regs+25);
341 err |= __put_user(regs->r26, sc->sc_regs+26);
342 err |= __put_user(regs->r27, sc->sc_regs+27);
343 err |= __put_user(regs->r28, sc->sc_regs+28);
344 err |= __put_user(regs->gp , sc->sc_regs+29);
345 err |= __put_user(sp, sc->sc_regs+30);
346 err |= __put_user(0, sc->sc_regs+31);
347
348 for (i = 0; i < 31; i++)
349 err |= __put_user(sw->fp[i], sc->sc_fpregs+i);
350 err |= __put_user(0, sc->sc_fpregs+31);
351 err |= __put_user(sw->fp[31], &sc->sc_fpcr);
352
353 err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
354 err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
355 err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
356
357 return err;
358}
359
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700360static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
362 struct pt_regs *regs, struct switch_stack * sw)
363{
364 unsigned long oldsp, r26, err = 0;
365 struct sigframe __user *frame;
366
367 oldsp = rdusp();
368 frame = get_sigframe(ka, oldsp, sizeof(*frame));
369 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
370 goto give_sigsegv;
371
372 err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
373 if (err)
374 goto give_sigsegv;
375
376 /* Set up to return from userspace. If provided, use a stub
377 already in userspace. */
378 if (ka->ka_restorer) {
379 r26 = (unsigned long) ka->ka_restorer;
380 } else {
381 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
382 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
383 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
384 imb();
385 r26 = (unsigned long) frame->retcode;
386 }
387
388 /* Check that everything was written properly. */
389 if (err)
390 goto give_sigsegv;
391
392 /* "Return" to the handler */
393 regs->r26 = r26;
394 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
395 regs->r16 = sig; /* a0: signal number */
396 regs->r17 = 0; /* a1: exception code */
397 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
398 wrusp((unsigned long) frame);
399
400#if DEBUG_SIG
401 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
402 current->comm, current->pid, frame, regs->pc, regs->r26);
403#endif
404
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700405 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
407give_sigsegv:
408 force_sigsegv(sig, current);
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700409 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410}
411
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700412static int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
414 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
415{
416 unsigned long oldsp, r26, err = 0;
417 struct rt_sigframe __user *frame;
418
419 oldsp = rdusp();
420 frame = get_sigframe(ka, oldsp, sizeof(*frame));
421 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
422 goto give_sigsegv;
423
424 err |= copy_siginfo_to_user(&frame->info, info);
425
426 /* Create the ucontext. */
427 err |= __put_user(0, &frame->uc.uc_flags);
428 err |= __put_user(0, &frame->uc.uc_link);
429 err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
430 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
431 err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
432 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
433 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
434 set->sig[0], oldsp);
435 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
436 if (err)
437 goto give_sigsegv;
438
439 /* Set up to return from userspace. If provided, use a stub
440 already in userspace. */
441 if (ka->ka_restorer) {
442 r26 = (unsigned long) ka->ka_restorer;
443 } else {
444 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
445 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
446 frame->retcode+1);
447 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
448 imb();
449 r26 = (unsigned long) frame->retcode;
450 }
451
452 if (err)
453 goto give_sigsegv;
454
455 /* "Return" to the handler */
456 regs->r26 = r26;
457 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
458 regs->r16 = sig; /* a0: signal number */
459 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
460 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
461 wrusp((unsigned long) frame);
462
463#if DEBUG_SIG
464 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
465 current->comm, current->pid, frame, regs->pc, regs->r26);
466#endif
467
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700468 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470give_sigsegv:
471 force_sigsegv(sig, current);
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700472 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473}
474
475
476/*
477 * OK, we're invoking a handler.
478 */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700479static inline int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
481 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
482{
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700483 int ret;
484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if (ka->sa.sa_flags & SA_SIGINFO)
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700486 ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 else
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700488 ret = setup_frame(sig, ka, oldset, regs, sw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Matt Fleming2561b062012-04-05 14:25:12 -0700490 if (ret == 0)
491 block_sigmask(ka, sig);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700493 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
496static inline void
497syscall_restart(unsigned long r0, unsigned long r19,
498 struct pt_regs *regs, struct k_sigaction *ka)
499{
500 switch (regs->r0) {
501 case ERESTARTSYS:
502 if (!(ka->sa.sa_flags & SA_RESTART)) {
503 case ERESTARTNOHAND:
504 regs->r0 = EINTR;
505 break;
506 }
507 /* fallthrough */
508 case ERESTARTNOINTR:
509 regs->r0 = r0; /* reset v0 and a3 and replay syscall */
510 regs->r19 = r19;
511 regs->pc -= 4;
512 break;
513 case ERESTART_RESTARTBLOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 regs->r0 = EINTR;
515 break;
516 }
517}
518
519
520/*
521 * Note that 'init' is a special process: it doesn't get signals it doesn't
522 * want to handle. Thus you cannot kill init even with a SIGKILL even by
523 * mistake.
524 *
525 * Note that we go through the signals twice: once to check the signals that
526 * the kernel can handle, and then we build all the user-level signal handling
527 * stack-frames in one go after that.
528 *
529 * "r0" and "r19" are the registers we need to restore for system call
530 * restart. "r0" is also used as an indicator whether we can restart at
531 * all (if we get here from anything but a syscall return, it will be 0)
532 */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700533static void
534do_signal(struct pt_regs * regs, struct switch_stack * sw,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 unsigned long r0, unsigned long r19)
536{
537 siginfo_t info;
538 int signr;
539 unsigned long single_stepping = ptrace_cancel_bpt(current);
540 struct k_sigaction ka;
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700541 sigset_t *oldset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700543 if (test_thread_flag(TIF_RESTORE_SIGMASK))
544 oldset = &current->saved_sigmask;
545 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 oldset = &current->blocked;
547
548 /* This lets the debugger run, ... */
549 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700550
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 /* ... so re-check the single stepping. */
552 single_stepping |= ptrace_cancel_bpt(current);
553
554 if (signr > 0) {
555 /* Whee! Actually deliver the signal. */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700556 if (r0)
557 syscall_restart(r0, r19, regs, &ka);
558 if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
559 /* A signal was successfully delivered, and the
560 saved sigmask was stored on the signal frame,
561 and will be restored by sigreturn. So we can
562 simply clear the restore sigmask flag. */
563 if (test_thread_flag(TIF_RESTORE_SIGMASK))
564 clear_thread_flag(TIF_RESTORE_SIGMASK);
565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 if (single_stepping)
567 ptrace_set_bpt(current); /* re-set bpt */
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700568 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 }
570
571 if (r0) {
572 switch (regs->r0) {
573 case ERESTARTNOHAND:
574 case ERESTARTSYS:
575 case ERESTARTNOINTR:
576 /* Reset v0 and a3 and replay syscall. */
577 regs->r0 = r0;
578 regs->r19 = r19;
579 regs->pc -= 4;
580 break;
581 case ERESTART_RESTARTBLOCK:
582 /* Force v0 to the restart syscall and reply. */
583 regs->r0 = __NR_restart_syscall;
584 regs->pc -= 4;
585 break;
586 }
587 }
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700588
589 /* If there's no signal to deliver, we just restore the saved mask. */
590 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
591 clear_thread_flag(TIF_RESTORE_SIGMASK);
592 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
593 }
594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 if (single_stepping)
596 ptrace_set_bpt(current); /* re-set breakpoint */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597}
598
599void
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700600do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
601 unsigned long thread_info_flags,
602 unsigned long r0, unsigned long r19)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Richard Hendersonb927b3e2007-05-29 16:03:28 -0700604 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
605 do_signal(regs, sw, r0, r19);
David Howellsd0420c82009-09-02 09:14:16 +0100606
607 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
608 clear_thread_flag(TIF_NOTIFY_RESUME);
609 tracehook_notify_resume(regs);
David Howellsee18d642009-09-02 09:14:21 +0100610 if (current->replacement_session_keyring)
611 key_replace_session_keyring();
David Howellsd0420c82009-09-02 09:14:16 +0100612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613}