blob: b4c815d8ef75f0e00dc2cf94a599440709f9e584 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Heiko Carstens54dfe5d2006-02-01 03:06:38 -08002 * arch/s390/kernel/compat_signal.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Heiko Carstens54dfe5d2006-02-01 03:06:38 -08004 * Copyright (C) IBM Corp. 2000,2006
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
6 * Gerhard Tonn (ton@de.ibm.com)
7 *
8 * Copyright (C) 1991, 1992 Linus Torvalds
9 *
10 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
11 */
12
13#include <linux/config.h>
14#include <linux/compat.h>
15#include <linux/sched.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
18#include <linux/smp_lock.h>
19#include <linux/kernel.h>
20#include <linux/signal.h>
21#include <linux/errno.h>
22#include <linux/wait.h>
23#include <linux/ptrace.h>
24#include <linux/unistd.h>
25#include <linux/stddef.h>
26#include <linux/tty.h>
27#include <linux/personality.h>
28#include <linux/binfmts.h>
29#include <asm/ucontext.h>
30#include <asm/uaccess.h>
31#include <asm/lowcore.h>
32#include "compat_linux.h"
33#include "compat_ptrace.h"
34
35#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
36
37typedef struct
38{
39 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
40 struct sigcontext32 sc;
41 _sigregs32 sregs;
42 int signo;
43 __u8 retcode[S390_SYSCALL_SIZE];
44} sigframe32;
45
46typedef struct
47{
48 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
49 __u8 retcode[S390_SYSCALL_SIZE];
50 compat_siginfo_t info;
51 struct ucontext32 uc;
52} rt_sigframe32;
53
Linus Torvalds1da177e2005-04-16 15:20:36 -070054int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
55{
56 int err;
57
58 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
59 return -EFAULT;
60
61 /* If you change siginfo_t structure, please be sure
62 this code is fixed accordingly.
63 It should never copy any pad contained in the structure
64 to avoid security leaks, but must copy the generic
65 3 ints plus the relevant union member.
66 This routine must convert siginfo from 64bit to 32bit as well
67 at the same time. */
68 err = __put_user(from->si_signo, &to->si_signo);
69 err |= __put_user(from->si_errno, &to->si_errno);
70 err |= __put_user((short)from->si_code, &to->si_code);
71 if (from->si_code < 0)
72 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
73 else {
74 switch (from->si_code >> 16) {
75 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
76 case __SI_MESGQ >> 16:
77 err |= __put_user(from->si_int, &to->si_int);
78 /* fallthrough */
79 case __SI_KILL >> 16:
80 err |= __put_user(from->si_pid, &to->si_pid);
81 err |= __put_user(from->si_uid, &to->si_uid);
82 break;
83 case __SI_CHLD >> 16:
84 err |= __put_user(from->si_pid, &to->si_pid);
85 err |= __put_user(from->si_uid, &to->si_uid);
86 err |= __put_user(from->si_utime, &to->si_utime);
87 err |= __put_user(from->si_stime, &to->si_stime);
88 err |= __put_user(from->si_status, &to->si_status);
89 break;
90 case __SI_FAULT >> 16:
91 err |= __put_user((unsigned long) from->si_addr,
92 &to->si_addr);
93 break;
94 case __SI_POLL >> 16:
95 err |= __put_user(from->si_band, &to->si_band);
96 err |= __put_user(from->si_fd, &to->si_fd);
97 break;
98 case __SI_TIMER >> 16:
99 err |= __put_user(from->si_tid, &to->si_tid);
100 err |= __put_user(from->si_overrun, &to->si_overrun);
101 err |= __put_user(from->si_int, &to->si_int);
102 break;
103 default:
104 break;
105 }
106 }
107 return err;
108}
109
110int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
111{
112 int err;
113 u32 tmp;
114
115 if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
116 return -EFAULT;
117
118 err = __get_user(to->si_signo, &from->si_signo);
119 err |= __get_user(to->si_errno, &from->si_errno);
120 err |= __get_user(to->si_code, &from->si_code);
121
122 if (to->si_code < 0)
123 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
124 else {
125 switch (to->si_code >> 16) {
126 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
127 case __SI_MESGQ >> 16:
128 err |= __get_user(to->si_int, &from->si_int);
129 /* fallthrough */
130 case __SI_KILL >> 16:
131 err |= __get_user(to->si_pid, &from->si_pid);
132 err |= __get_user(to->si_uid, &from->si_uid);
133 break;
134 case __SI_CHLD >> 16:
135 err |= __get_user(to->si_pid, &from->si_pid);
136 err |= __get_user(to->si_uid, &from->si_uid);
137 err |= __get_user(to->si_utime, &from->si_utime);
138 err |= __get_user(to->si_stime, &from->si_stime);
139 err |= __get_user(to->si_status, &from->si_status);
140 break;
141 case __SI_FAULT >> 16:
142 err |= __get_user(tmp, &from->si_addr);
Al Viroc2814472005-09-29 00:16:02 +0100143 to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 break;
145 case __SI_POLL >> 16:
146 err |= __get_user(to->si_band, &from->si_band);
147 err |= __get_user(to->si_fd, &from->si_fd);
148 break;
149 case __SI_TIMER >> 16:
150 err |= __get_user(to->si_tid, &from->si_tid);
151 err |= __get_user(to->si_overrun, &from->si_overrun);
152 err |= __get_user(to->si_int, &from->si_int);
153 break;
154 default:
155 break;
156 }
157 }
158 return err;
159}
160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161asmlinkage long
162sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
163 struct old_sigaction32 __user *oact)
164{
165 struct k_sigaction new_ka, old_ka;
166 unsigned long sa_handler, sa_restorer;
167 int ret;
168
169 if (act) {
170 compat_old_sigset_t mask;
171 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
172 __get_user(sa_handler, &act->sa_handler) ||
173 __get_user(sa_restorer, &act->sa_restorer))
174 return -EFAULT;
175 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
176 new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
177 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
178 __get_user(mask, &act->sa_mask);
179 siginitset(&new_ka.sa.sa_mask, mask);
180 }
181
182 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
183
184 if (!ret && oact) {
185 sa_handler = (unsigned long) old_ka.sa.sa_handler;
186 sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
187 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
188 __put_user(sa_handler, &oact->sa_handler) ||
189 __put_user(sa_restorer, &oact->sa_restorer))
190 return -EFAULT;
191 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
192 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
193 }
194
195 return ret;
196}
197
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198asmlinkage long
199sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
200 struct sigaction32 __user *oact, size_t sigsetsize)
201{
202 struct k_sigaction new_ka, old_ka;
203 unsigned long sa_handler;
204 int ret;
205 compat_sigset_t set32;
206
207 /* XXX: Don't preclude handling different sized sigset_t's. */
208 if (sigsetsize != sizeof(compat_sigset_t))
209 return -EINVAL;
210
211 if (act) {
212 ret = get_user(sa_handler, &act->sa_handler);
213 ret |= __copy_from_user(&set32, &act->sa_mask,
214 sizeof(compat_sigset_t));
215 switch (_NSIG_WORDS) {
216 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
217 | (((long)set32.sig[7]) << 32);
218 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
219 | (((long)set32.sig[5]) << 32);
220 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
221 | (((long)set32.sig[3]) << 32);
222 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
223 | (((long)set32.sig[1]) << 32);
224 }
225 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
226
227 if (ret)
228 return -EFAULT;
229 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
230 }
231
232 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
233
234 if (!ret && oact) {
235 switch (_NSIG_WORDS) {
236 case 4:
237 set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
238 set32.sig[6] = old_ka.sa.sa_mask.sig[3];
239 case 3:
240 set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
241 set32.sig[4] = old_ka.sa.sa_mask.sig[2];
242 case 2:
243 set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
244 set32.sig[2] = old_ka.sa.sa_mask.sig[1];
245 case 1:
246 set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
247 set32.sig[0] = old_ka.sa.sa_mask.sig[0];
248 }
249 ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
250 ret |= __copy_to_user(&oact->sa_mask, &set32,
251 sizeof(compat_sigset_t));
252 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
253 }
254
255 return ret;
256}
257
258asmlinkage long
259sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
260 struct pt_regs *regs)
261{
262 stack_t kss, koss;
263 unsigned long ss_sp;
264 int ret, err = 0;
265 mm_segment_t old_fs = get_fs();
266
267 if (uss) {
268 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
269 return -EFAULT;
270 err |= __get_user(ss_sp, &uss->ss_sp);
271 err |= __get_user(kss.ss_size, &uss->ss_size);
272 err |= __get_user(kss.ss_flags, &uss->ss_flags);
273 if (err)
274 return -EFAULT;
Al Viroc2814472005-09-29 00:16:02 +0100275 kss.ss_sp = (void __user *) ss_sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
277
278 set_fs (KERNEL_DS);
279 ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL),
280 (stack_t __user *) (uoss ? &koss : NULL),
281 regs->gprs[15]);
282 set_fs (old_fs);
283
284 if (!ret && uoss) {
285 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
286 return -EFAULT;
287 ss_sp = (unsigned long) koss.ss_sp;
288 err |= __put_user(ss_sp, &uoss->ss_sp);
289 err |= __put_user(koss.ss_size, &uoss->ss_size);
290 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
291 if (err)
292 return -EFAULT;
293 }
294 return ret;
295}
296
297static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
298{
299 _s390_regs_common32 regs32;
300 int err, i;
301
302 regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS,
303 (__u32)(regs->psw.mask >> 32));
304 regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
305 for (i = 0; i < NUM_GPRS; i++)
306 regs32.gprs[i] = (__u32) regs->gprs[i];
307 save_access_regs(current->thread.acrs);
308 memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
309 err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
310 if (err)
311 return err;
312 save_fp_regs(&current->thread.fp_regs);
313 /* s390_fp_regs and _s390_fp_regs32 are the same ! */
314 return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
315 sizeof(_s390_fp_regs32));
316}
317
318static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
319{
320 _s390_regs_common32 regs32;
321 int err, i;
322
323 /* Alwys make any pending restarted system call return -EINTR */
324 current_thread_info()->restart_block.fn = do_no_restart_syscall;
325
326 err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
327 if (err)
328 return err;
329 regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
330 (__u64)regs32.psw.mask << 32);
331 regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
332 for (i = 0; i < NUM_GPRS; i++)
333 regs->gprs[i] = (__u64) regs32.gprs[i];
334 memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
335 restore_access_regs(current->thread.acrs);
336
337 err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
338 sizeof(_s390_fp_regs32));
339 current->thread.fp_regs.fpc &= FPC_VALID_MASK;
340 if (err)
341 return err;
342
343 restore_fp_regs(&current->thread.fp_regs);
344 regs->trap = -1; /* disable syscall checks */
345 return 0;
346}
347
348asmlinkage long sys32_sigreturn(struct pt_regs *regs)
349{
350 sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
351 sigset_t set;
352
353 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
354 goto badframe;
355 if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
356 goto badframe;
357
358 sigdelsetmask(&set, ~_BLOCKABLE);
359 spin_lock_irq(&current->sighand->siglock);
360 current->blocked = set;
361 recalc_sigpending();
362 spin_unlock_irq(&current->sighand->siglock);
363
364 if (restore_sigregs32(regs, &frame->sregs))
365 goto badframe;
366
367 return regs->gprs[2];
368
369badframe:
370 force_sig(SIGSEGV, current);
371 return 0;
372}
373
374asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
375{
376 rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
377 sigset_t set;
378 stack_t st;
379 __u32 ss_sp;
380 int err;
381 mm_segment_t old_fs = get_fs();
382
383 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
384 goto badframe;
385 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
386 goto badframe;
387
388 sigdelsetmask(&set, ~_BLOCKABLE);
389 spin_lock_irq(&current->sighand->siglock);
390 current->blocked = set;
391 recalc_sigpending();
392 spin_unlock_irq(&current->sighand->siglock);
393
394 if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
395 goto badframe;
396
397 err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
Al Viroc2814472005-09-29 00:16:02 +0100398 st.ss_sp = compat_ptr(ss_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
400 err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
401 if (err)
402 goto badframe;
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 set_fs (KERNEL_DS);
405 do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
406 set_fs (old_fs);
407
408 return regs->gprs[2];
409
410badframe:
411 force_sig(SIGSEGV, current);
412 return 0;
413}
414
415/*
416 * Set up a signal frame.
417 */
418
419
420/*
421 * Determine which stack to use..
422 */
423static inline void __user *
424get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
425{
426 unsigned long sp;
427
428 /* Default to using normal stack */
429 sp = (unsigned long) A(regs->gprs[15]);
430
431 /* This is the X/Open sanctioned signal stack switching. */
432 if (ka->sa.sa_flags & SA_ONSTACK) {
Laurent Meyer28f22372006-04-27 18:40:07 -0700433 if (! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 sp = current->sas_ss_sp + current->sas_ss_size;
435 }
436
437 /* This is the legacy signal stack switching. */
438 else if (!user_mode(regs) &&
439 !(ka->sa.sa_flags & SA_RESTORER) &&
440 ka->sa.sa_restorer) {
441 sp = (unsigned long) ka->sa.sa_restorer;
442 }
443
444 return (void __user *)((sp - frame_size) & -8ul);
445}
446
447static inline int map_signal(int sig)
448{
449 if (current_thread_info()->exec_domain
450 && current_thread_info()->exec_domain->signal_invmap
451 && sig < 32)
452 return current_thread_info()->exec_domain->signal_invmap[sig];
453 else
454 return sig;
455}
456
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800457static int setup_frame32(int sig, struct k_sigaction *ka,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 sigset_t *set, struct pt_regs * regs)
459{
460 sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
461 if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
462 goto give_sigsegv;
463
464 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
465 goto give_sigsegv;
466
467 if (save_sigregs32(regs, &frame->sregs))
468 goto give_sigsegv;
469 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
470 goto give_sigsegv;
471
472 /* Set up to return from userspace. If provided, use a stub
473 already in userspace. */
474 if (ka->sa.sa_flags & SA_RESTORER) {
475 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
476 } else {
477 regs->gprs[14] = (__u64) frame->retcode;
478 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
479 (u16 __user *)(frame->retcode)))
480 goto give_sigsegv;
481 }
482
483 /* Set up backchain. */
484 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
485 goto give_sigsegv;
486
487 /* Set up registers for signal handler */
488 regs->gprs[15] = (__u64) frame;
489 regs->psw.addr = (__u64) ka->sa.sa_handler;
490
491 regs->gprs[2] = map_signal(sig);
492 regs->gprs[3] = (__u64) &frame->sc;
493
494 /* We forgot to include these in the sigcontext.
495 To avoid breaking binary compatibility, they are passed as args. */
496 regs->gprs[4] = current->thread.trap_no;
497 regs->gprs[5] = current->thread.prot_addr;
498
499 /* Place signal number on stack to allow backtrace from handler. */
500 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
501 goto give_sigsegv;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800502 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504give_sigsegv:
505 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800506 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507}
508
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800509static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 sigset_t *set, struct pt_regs * regs)
511{
512 int err = 0;
513 rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
514 if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
515 goto give_sigsegv;
516
517 if (copy_siginfo_to_user32(&frame->info, info))
518 goto give_sigsegv;
519
520 /* Create the ucontext. */
521 err |= __put_user(0, &frame->uc.uc_flags);
522 err |= __put_user(0, &frame->uc.uc_link);
523 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
524 err |= __put_user(sas_ss_flags(regs->gprs[15]),
525 &frame->uc.uc_stack.ss_flags);
526 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
527 err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
528 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
529 if (err)
530 goto give_sigsegv;
531
532 /* Set up to return from userspace. If provided, use a stub
533 already in userspace. */
534 if (ka->sa.sa_flags & SA_RESTORER) {
535 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
536 } else {
537 regs->gprs[14] = (__u64) frame->retcode;
538 err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
539 (u16 __user *)(frame->retcode));
540 }
541
542 /* Set up backchain. */
543 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
544 goto give_sigsegv;
545
546 /* Set up registers for signal handler */
547 regs->gprs[15] = (__u64) frame;
548 regs->psw.addr = (__u64) ka->sa.sa_handler;
549
550 regs->gprs[2] = map_signal(sig);
551 regs->gprs[3] = (__u64) &frame->info;
552 regs->gprs[4] = (__u64) &frame->uc;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800553 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
555give_sigsegv:
556 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800557 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558}
559
560/*
561 * OK, we're invoking a handler
562 */
563
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800564int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565handle_signal32(unsigned long sig, struct k_sigaction *ka,
566 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
567{
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800568 int ret;
569
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 /* Set up the stack frame */
571 if (ka->sa.sa_flags & SA_SIGINFO)
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800572 ret = setup_rt_frame32(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 else
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800574 ret = setup_frame32(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800576 if (ret == 0) {
577 spin_lock_irq(&current->sighand->siglock);
578 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
579 if (!(ka->sa.sa_flags & SA_NODEFER))
580 sigaddset(&current->blocked,sig);
581 recalc_sigpending();
582 spin_unlock_irq(&current->sighand->siglock);
583 }
584 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585}
586