blob: ef706694a0c1d3897ab28330576901214d8d3a62 [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
198int
199do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
200
201asmlinkage long
202sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
203 struct sigaction32 __user *oact, size_t sigsetsize)
204{
205 struct k_sigaction new_ka, old_ka;
206 unsigned long sa_handler;
207 int ret;
208 compat_sigset_t set32;
209
210 /* XXX: Don't preclude handling different sized sigset_t's. */
211 if (sigsetsize != sizeof(compat_sigset_t))
212 return -EINVAL;
213
214 if (act) {
215 ret = get_user(sa_handler, &act->sa_handler);
216 ret |= __copy_from_user(&set32, &act->sa_mask,
217 sizeof(compat_sigset_t));
218 switch (_NSIG_WORDS) {
219 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
220 | (((long)set32.sig[7]) << 32);
221 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
222 | (((long)set32.sig[5]) << 32);
223 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
224 | (((long)set32.sig[3]) << 32);
225 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
226 | (((long)set32.sig[1]) << 32);
227 }
228 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
229
230 if (ret)
231 return -EFAULT;
232 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
233 }
234
235 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
236
237 if (!ret && oact) {
238 switch (_NSIG_WORDS) {
239 case 4:
240 set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
241 set32.sig[6] = old_ka.sa.sa_mask.sig[3];
242 case 3:
243 set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
244 set32.sig[4] = old_ka.sa.sa_mask.sig[2];
245 case 2:
246 set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
247 set32.sig[2] = old_ka.sa.sa_mask.sig[1];
248 case 1:
249 set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
250 set32.sig[0] = old_ka.sa.sa_mask.sig[0];
251 }
252 ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
253 ret |= __copy_to_user(&oact->sa_mask, &set32,
254 sizeof(compat_sigset_t));
255 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
256 }
257
258 return ret;
259}
260
261asmlinkage long
262sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
263 struct pt_regs *regs)
264{
265 stack_t kss, koss;
266 unsigned long ss_sp;
267 int ret, err = 0;
268 mm_segment_t old_fs = get_fs();
269
270 if (uss) {
271 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
272 return -EFAULT;
273 err |= __get_user(ss_sp, &uss->ss_sp);
274 err |= __get_user(kss.ss_size, &uss->ss_size);
275 err |= __get_user(kss.ss_flags, &uss->ss_flags);
276 if (err)
277 return -EFAULT;
Al Viroc2814472005-09-29 00:16:02 +0100278 kss.ss_sp = (void __user *) ss_sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280
281 set_fs (KERNEL_DS);
282 ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL),
283 (stack_t __user *) (uoss ? &koss : NULL),
284 regs->gprs[15]);
285 set_fs (old_fs);
286
287 if (!ret && uoss) {
288 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
289 return -EFAULT;
290 ss_sp = (unsigned long) koss.ss_sp;
291 err |= __put_user(ss_sp, &uoss->ss_sp);
292 err |= __put_user(koss.ss_size, &uoss->ss_size);
293 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
294 if (err)
295 return -EFAULT;
296 }
297 return ret;
298}
299
300static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
301{
302 _s390_regs_common32 regs32;
303 int err, i;
304
305 regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS,
306 (__u32)(regs->psw.mask >> 32));
307 regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
308 for (i = 0; i < NUM_GPRS; i++)
309 regs32.gprs[i] = (__u32) regs->gprs[i];
310 save_access_regs(current->thread.acrs);
311 memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
312 err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
313 if (err)
314 return err;
315 save_fp_regs(&current->thread.fp_regs);
316 /* s390_fp_regs and _s390_fp_regs32 are the same ! */
317 return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
318 sizeof(_s390_fp_regs32));
319}
320
321static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
322{
323 _s390_regs_common32 regs32;
324 int err, i;
325
326 /* Alwys make any pending restarted system call return -EINTR */
327 current_thread_info()->restart_block.fn = do_no_restart_syscall;
328
329 err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
330 if (err)
331 return err;
332 regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
333 (__u64)regs32.psw.mask << 32);
334 regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
335 for (i = 0; i < NUM_GPRS; i++)
336 regs->gprs[i] = (__u64) regs32.gprs[i];
337 memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
338 restore_access_regs(current->thread.acrs);
339
340 err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
341 sizeof(_s390_fp_regs32));
342 current->thread.fp_regs.fpc &= FPC_VALID_MASK;
343 if (err)
344 return err;
345
346 restore_fp_regs(&current->thread.fp_regs);
347 regs->trap = -1; /* disable syscall checks */
348 return 0;
349}
350
351asmlinkage long sys32_sigreturn(struct pt_regs *regs)
352{
353 sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
354 sigset_t set;
355
356 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
357 goto badframe;
358 if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
359 goto badframe;
360
361 sigdelsetmask(&set, ~_BLOCKABLE);
362 spin_lock_irq(&current->sighand->siglock);
363 current->blocked = set;
364 recalc_sigpending();
365 spin_unlock_irq(&current->sighand->siglock);
366
367 if (restore_sigregs32(regs, &frame->sregs))
368 goto badframe;
369
370 return regs->gprs[2];
371
372badframe:
373 force_sig(SIGSEGV, current);
374 return 0;
375}
376
377asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
378{
379 rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15];
380 sigset_t set;
381 stack_t st;
382 __u32 ss_sp;
383 int err;
384 mm_segment_t old_fs = get_fs();
385
386 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
387 goto badframe;
388 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
389 goto badframe;
390
391 sigdelsetmask(&set, ~_BLOCKABLE);
392 spin_lock_irq(&current->sighand->siglock);
393 current->blocked = set;
394 recalc_sigpending();
395 spin_unlock_irq(&current->sighand->siglock);
396
397 if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
398 goto badframe;
399
400 err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
Al Viroc2814472005-09-29 00:16:02 +0100401 st.ss_sp = compat_ptr(ss_sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
403 err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
404 if (err)
405 goto badframe;
406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 set_fs (KERNEL_DS);
408 do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
409 set_fs (old_fs);
410
411 return regs->gprs[2];
412
413badframe:
414 force_sig(SIGSEGV, current);
415 return 0;
416}
417
418/*
419 * Set up a signal frame.
420 */
421
422
423/*
424 * Determine which stack to use..
425 */
426static inline void __user *
427get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
428{
429 unsigned long sp;
430
431 /* Default to using normal stack */
432 sp = (unsigned long) A(regs->gprs[15]);
433
434 /* This is the X/Open sanctioned signal stack switching. */
435 if (ka->sa.sa_flags & SA_ONSTACK) {
436 if (! on_sig_stack(sp))
437 sp = current->sas_ss_sp + current->sas_ss_size;
438 }
439
440 /* This is the legacy signal stack switching. */
441 else if (!user_mode(regs) &&
442 !(ka->sa.sa_flags & SA_RESTORER) &&
443 ka->sa.sa_restorer) {
444 sp = (unsigned long) ka->sa.sa_restorer;
445 }
446
447 return (void __user *)((sp - frame_size) & -8ul);
448}
449
450static inline int map_signal(int sig)
451{
452 if (current_thread_info()->exec_domain
453 && current_thread_info()->exec_domain->signal_invmap
454 && sig < 32)
455 return current_thread_info()->exec_domain->signal_invmap[sig];
456 else
457 return sig;
458}
459
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800460static int setup_frame32(int sig, struct k_sigaction *ka,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 sigset_t *set, struct pt_regs * regs)
462{
463 sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
464 if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
465 goto give_sigsegv;
466
467 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
468 goto give_sigsegv;
469
470 if (save_sigregs32(regs, &frame->sregs))
471 goto give_sigsegv;
472 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
473 goto give_sigsegv;
474
475 /* Set up to return from userspace. If provided, use a stub
476 already in userspace. */
477 if (ka->sa.sa_flags & SA_RESTORER) {
478 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
479 } else {
480 regs->gprs[14] = (__u64) frame->retcode;
481 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
482 (u16 __user *)(frame->retcode)))
483 goto give_sigsegv;
484 }
485
486 /* Set up backchain. */
487 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
488 goto give_sigsegv;
489
490 /* Set up registers for signal handler */
491 regs->gprs[15] = (__u64) frame;
492 regs->psw.addr = (__u64) ka->sa.sa_handler;
493
494 regs->gprs[2] = map_signal(sig);
495 regs->gprs[3] = (__u64) &frame->sc;
496
497 /* We forgot to include these in the sigcontext.
498 To avoid breaking binary compatibility, they are passed as args. */
499 regs->gprs[4] = current->thread.trap_no;
500 regs->gprs[5] = current->thread.prot_addr;
501
502 /* Place signal number on stack to allow backtrace from handler. */
503 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
504 goto give_sigsegv;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800505 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507give_sigsegv:
508 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800509 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510}
511
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800512static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 sigset_t *set, struct pt_regs * regs)
514{
515 int err = 0;
516 rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
517 if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
518 goto give_sigsegv;
519
520 if (copy_siginfo_to_user32(&frame->info, info))
521 goto give_sigsegv;
522
523 /* Create the ucontext. */
524 err |= __put_user(0, &frame->uc.uc_flags);
525 err |= __put_user(0, &frame->uc.uc_link);
526 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
527 err |= __put_user(sas_ss_flags(regs->gprs[15]),
528 &frame->uc.uc_stack.ss_flags);
529 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
530 err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
531 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
532 if (err)
533 goto give_sigsegv;
534
535 /* Set up to return from userspace. If provided, use a stub
536 already in userspace. */
537 if (ka->sa.sa_flags & SA_RESTORER) {
538 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
539 } else {
540 regs->gprs[14] = (__u64) frame->retcode;
541 err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
542 (u16 __user *)(frame->retcode));
543 }
544
545 /* Set up backchain. */
546 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
547 goto give_sigsegv;
548
549 /* Set up registers for signal handler */
550 regs->gprs[15] = (__u64) frame;
551 regs->psw.addr = (__u64) ka->sa.sa_handler;
552
553 regs->gprs[2] = map_signal(sig);
554 regs->gprs[3] = (__u64) &frame->info;
555 regs->gprs[4] = (__u64) &frame->uc;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800556 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
558give_sigsegv:
559 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800560 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561}
562
563/*
564 * OK, we're invoking a handler
565 */
566
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800567int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568handle_signal32(unsigned long sig, struct k_sigaction *ka,
569 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
570{
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800571 int ret;
572
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 /* Set up the stack frame */
574 if (ka->sa.sa_flags & SA_SIGINFO)
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800575 ret = setup_rt_frame32(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 else
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800577 ret = setup_frame32(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800579 if (ret == 0) {
580 spin_lock_irq(&current->sighand->siglock);
581 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
582 if (!(ka->sa.sa_flags & SA_NODEFER))
583 sigaddset(&current->blocked,sig);
584 recalc_sigpending();
585 spin_unlock_irq(&current->sighand->siglock);
586 }
587 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588}
589