blob: ae2f2d31393061faa8215668706a91c974688a34 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/compat.h>
14#include <linux/sched.h>
15#include <linux/mm.h>
16#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/kernel.h>
18#include <linux/signal.h>
19#include <linux/errno.h>
20#include <linux/wait.h>
21#include <linux/ptrace.h>
22#include <linux/unistd.h>
23#include <linux/stddef.h>
24#include <linux/tty.h>
25#include <linux/personality.h>
26#include <linux/binfmts.h>
27#include <asm/ucontext.h>
28#include <asm/uaccess.h>
29#include <asm/lowcore.h>
30#include "compat_linux.h"
31#include "compat_ptrace.h"
32
33#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
34
35typedef struct
36{
37 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
38 struct sigcontext32 sc;
39 _sigregs32 sregs;
40 int signo;
41 __u8 retcode[S390_SYSCALL_SIZE];
42} sigframe32;
43
44typedef struct
45{
46 __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
47 __u8 retcode[S390_SYSCALL_SIZE];
48 compat_siginfo_t info;
49 struct ucontext32 uc;
50} rt_sigframe32;
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
53{
54 int err;
55
56 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
57 return -EFAULT;
58
59 /* If you change siginfo_t structure, please be sure
60 this code is fixed accordingly.
61 It should never copy any pad contained in the structure
62 to avoid security leaks, but must copy the generic
63 3 ints plus the relevant union member.
64 This routine must convert siginfo from 64bit to 32bit as well
65 at the same time. */
66 err = __put_user(from->si_signo, &to->si_signo);
67 err |= __put_user(from->si_errno, &to->si_errno);
68 err |= __put_user((short)from->si_code, &to->si_code);
69 if (from->si_code < 0)
70 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
71 else {
72 switch (from->si_code >> 16) {
73 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
74 case __SI_MESGQ >> 16:
75 err |= __put_user(from->si_int, &to->si_int);
76 /* fallthrough */
77 case __SI_KILL >> 16:
78 err |= __put_user(from->si_pid, &to->si_pid);
79 err |= __put_user(from->si_uid, &to->si_uid);
80 break;
81 case __SI_CHLD >> 16:
82 err |= __put_user(from->si_pid, &to->si_pid);
83 err |= __put_user(from->si_uid, &to->si_uid);
84 err |= __put_user(from->si_utime, &to->si_utime);
85 err |= __put_user(from->si_stime, &to->si_stime);
86 err |= __put_user(from->si_status, &to->si_status);
87 break;
88 case __SI_FAULT >> 16:
89 err |= __put_user((unsigned long) from->si_addr,
90 &to->si_addr);
91 break;
92 case __SI_POLL >> 16:
93 err |= __put_user(from->si_band, &to->si_band);
94 err |= __put_user(from->si_fd, &to->si_fd);
95 break;
96 case __SI_TIMER >> 16:
97 err |= __put_user(from->si_tid, &to->si_tid);
98 err |= __put_user(from->si_overrun, &to->si_overrun);
99 err |= __put_user(from->si_int, &to->si_int);
100 break;
101 default:
102 break;
103 }
104 }
105 return err;
106}
107
108int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
109{
110 int err;
111 u32 tmp;
112
113 if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
114 return -EFAULT;
115
116 err = __get_user(to->si_signo, &from->si_signo);
117 err |= __get_user(to->si_errno, &from->si_errno);
118 err |= __get_user(to->si_code, &from->si_code);
119
120 if (to->si_code < 0)
121 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
122 else {
123 switch (to->si_code >> 16) {
124 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
125 case __SI_MESGQ >> 16:
126 err |= __get_user(to->si_int, &from->si_int);
127 /* fallthrough */
128 case __SI_KILL >> 16:
129 err |= __get_user(to->si_pid, &from->si_pid);
130 err |= __get_user(to->si_uid, &from->si_uid);
131 break;
132 case __SI_CHLD >> 16:
133 err |= __get_user(to->si_pid, &from->si_pid);
134 err |= __get_user(to->si_uid, &from->si_uid);
135 err |= __get_user(to->si_utime, &from->si_utime);
136 err |= __get_user(to->si_stime, &from->si_stime);
137 err |= __get_user(to->si_status, &from->si_status);
138 break;
139 case __SI_FAULT >> 16:
140 err |= __get_user(tmp, &from->si_addr);
Al Viroc2814472005-09-29 00:16:02 +0100141 to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 break;
143 case __SI_POLL >> 16:
144 err |= __get_user(to->si_band, &from->si_band);
145 err |= __get_user(to->si_fd, &from->si_fd);
146 break;
147 case __SI_TIMER >> 16:
148 err |= __get_user(to->si_tid, &from->si_tid);
149 err |= __get_user(to->si_overrun, &from->si_overrun);
150 err |= __get_user(to->si_int, &from->si_int);
151 break;
152 default:
153 break;
154 }
155 }
156 return err;
157}
158
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159asmlinkage long
160sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
161 struct old_sigaction32 __user *oact)
162{
163 struct k_sigaction new_ka, old_ka;
164 unsigned long sa_handler, sa_restorer;
165 int ret;
166
167 if (act) {
168 compat_old_sigset_t mask;
169 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
170 __get_user(sa_handler, &act->sa_handler) ||
Heiko Carstens12bae232006-10-27 12:39:22 +0200171 __get_user(sa_restorer, &act->sa_restorer) ||
172 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
173 __get_user(mask, &act->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 return -EFAULT;
175 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
176 new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 siginitset(&new_ka.sa.sa_mask, mask);
178 }
179
180 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
181
182 if (!ret && oact) {
183 sa_handler = (unsigned long) old_ka.sa.sa_handler;
184 sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
185 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
186 __put_user(sa_handler, &oact->sa_handler) ||
Heiko Carstens12bae232006-10-27 12:39:22 +0200187 __put_user(sa_restorer, &oact->sa_restorer) ||
188 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
189 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 }
192
193 return ret;
194}
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196asmlinkage long
197sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
198 struct sigaction32 __user *oact, size_t sigsetsize)
199{
200 struct k_sigaction new_ka, old_ka;
201 unsigned long sa_handler;
202 int ret;
203 compat_sigset_t set32;
204
205 /* XXX: Don't preclude handling different sized sigset_t's. */
206 if (sigsetsize != sizeof(compat_sigset_t))
207 return -EINVAL;
208
209 if (act) {
210 ret = get_user(sa_handler, &act->sa_handler);
211 ret |= __copy_from_user(&set32, &act->sa_mask,
212 sizeof(compat_sigset_t));
213 switch (_NSIG_WORDS) {
214 case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
215 | (((long)set32.sig[7]) << 32);
216 case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
217 | (((long)set32.sig[5]) << 32);
218 case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
219 | (((long)set32.sig[3]) << 32);
220 case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
221 | (((long)set32.sig[1]) << 32);
222 }
223 ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
224
225 if (ret)
226 return -EFAULT;
227 new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
228 }
229
230 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
231
232 if (!ret && oact) {
233 switch (_NSIG_WORDS) {
234 case 4:
235 set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
236 set32.sig[6] = old_ka.sa.sa_mask.sig[3];
237 case 3:
238 set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
239 set32.sig[4] = old_ka.sa.sa_mask.sig[2];
240 case 2:
241 set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
242 set32.sig[2] = old_ka.sa.sa_mask.sig[1];
243 case 1:
244 set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
245 set32.sig[0] = old_ka.sa.sa_mask.sig[0];
246 }
247 ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
248 ret |= __copy_to_user(&oact->sa_mask, &set32,
249 sizeof(compat_sigset_t));
250 ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
251 }
252
253 return ret;
254}
255
256asmlinkage long
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200257sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258{
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200259 struct pt_regs *regs = task_pt_regs(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 stack_t kss, koss;
261 unsigned long ss_sp;
262 int ret, err = 0;
263 mm_segment_t old_fs = get_fs();
264
265 if (uss) {
266 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
267 return -EFAULT;
268 err |= __get_user(ss_sp, &uss->ss_sp);
269 err |= __get_user(kss.ss_size, &uss->ss_size);
270 err |= __get_user(kss.ss_flags, &uss->ss_flags);
271 if (err)
272 return -EFAULT;
Al Viroc2814472005-09-29 00:16:02 +0100273 kss.ss_sp = (void __user *) ss_sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 }
275
276 set_fs (KERNEL_DS);
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100277 ret = do_sigaltstack((stack_t __force __user *) (uss ? &kss : NULL),
278 (stack_t __force __user *) (uoss ? &koss : NULL),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 regs->gprs[15]);
280 set_fs (old_fs);
281
282 if (!ret && uoss) {
283 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
284 return -EFAULT;
285 ss_sp = (unsigned long) koss.ss_sp;
286 err |= __put_user(ss_sp, &uoss->ss_sp);
287 err |= __put_user(koss.ss_size, &uoss->ss_size);
288 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
289 if (err)
290 return -EFAULT;
291 }
292 return ret;
293}
294
295static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
296{
297 _s390_regs_common32 regs32;
298 int err, i;
299
Gerald Schaeferc1821c22007-02-05 21:18:17 +0100300 regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 (__u32)(regs->psw.mask >> 32));
302 regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
303 for (i = 0; i < NUM_GPRS; i++)
304 regs32.gprs[i] = (__u32) regs->gprs[i];
305 save_access_regs(current->thread.acrs);
306 memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs));
307 err = __copy_to_user(&sregs->regs, &regs32, sizeof(regs32));
308 if (err)
309 return err;
310 save_fp_regs(&current->thread.fp_regs);
311 /* s390_fp_regs and _s390_fp_regs32 are the same ! */
312 return __copy_to_user(&sregs->fpregs, &current->thread.fp_regs,
313 sizeof(_s390_fp_regs32));
314}
315
316static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
317{
318 _s390_regs_common32 regs32;
319 int err, i;
320
321 /* Alwys make any pending restarted system call return -EINTR */
322 current_thread_info()->restart_block.fn = do_no_restart_syscall;
323
324 err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
325 if (err)
326 return err;
327 regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
328 (__u64)regs32.psw.mask << 32);
329 regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
330 for (i = 0; i < NUM_GPRS; i++)
331 regs->gprs[i] = (__u64) regs32.gprs[i];
332 memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs));
333 restore_access_regs(current->thread.acrs);
334
335 err = __copy_from_user(&current->thread.fp_regs, &sregs->fpregs,
336 sizeof(_s390_fp_regs32));
337 current->thread.fp_regs.fpc &= FPC_VALID_MASK;
338 if (err)
339 return err;
340
341 restore_fp_regs(&current->thread.fp_regs);
342 regs->trap = -1; /* disable syscall checks */
343 return 0;
344}
345
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200346asmlinkage long sys32_sigreturn(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200348 struct pt_regs *regs = task_pt_regs(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15];
350 sigset_t set;
351
352 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
353 goto badframe;
354 if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
355 goto badframe;
356
357 sigdelsetmask(&set, ~_BLOCKABLE);
358 spin_lock_irq(&current->sighand->siglock);
359 current->blocked = set;
360 recalc_sigpending();
361 spin_unlock_irq(&current->sighand->siglock);
362
363 if (restore_sigregs32(regs, &frame->sregs))
364 goto badframe;
365
366 return regs->gprs[2];
367
368badframe:
369 force_sig(SIGSEGV, current);
370 return 0;
371}
372
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200373asmlinkage long sys32_rt_sigreturn(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374{
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200375 struct pt_regs *regs = task_pt_regs(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 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);
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100405 do_sigaltstack((stack_t __force __user *)&st, NULL, regs->gprs[15]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 set_fs (old_fs);
407
408 return regs->gprs[2];
409
410badframe:
Martin Schwidefsky03ff9a22007-04-27 16:01:40 +0200411 force_sig(SIGSEGV, current);
412 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413}
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
Heiko Carstensde553432008-04-17 07:45:57 +0200431 /* Overflow on alternate signal stack gives SIGSEGV. */
432 if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
433 return (void __user *) -1UL;
434
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 /* This is the X/Open sanctioned signal stack switching. */
436 if (ka->sa.sa_flags & SA_ONSTACK) {
Laurent Meyer28f22372006-04-27 18:40:07 -0700437 if (! sas_ss_flags(sp))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 sp = current->sas_ss_sp + current->sas_ss_size;
439 }
440
441 /* This is the legacy signal stack switching. */
442 else if (!user_mode(regs) &&
443 !(ka->sa.sa_flags & SA_RESTORER) &&
444 ka->sa.sa_restorer) {
445 sp = (unsigned long) ka->sa.sa_restorer;
446 }
447
448 return (void __user *)((sp - frame_size) & -8ul);
449}
450
451static inline int map_signal(int sig)
452{
453 if (current_thread_info()->exec_domain
454 && current_thread_info()->exec_domain->signal_invmap
455 && sig < 32)
456 return current_thread_info()->exec_domain->signal_invmap[sig];
457 else
458 return sig;
459}
460
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800461static int setup_frame32(int sig, struct k_sigaction *ka,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 sigset_t *set, struct pt_regs * regs)
463{
464 sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
465 if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32)))
466 goto give_sigsegv;
467
Heiko Carstensde553432008-04-17 07:45:57 +0200468 if (frame == (void __user *) -1UL)
469 goto give_sigsegv;
470
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
472 goto give_sigsegv;
473
474 if (save_sigregs32(regs, &frame->sregs))
475 goto give_sigsegv;
476 if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
477 goto give_sigsegv;
478
479 /* Set up to return from userspace. If provided, use a stub
480 already in userspace. */
481 if (ka->sa.sa_flags & SA_RESTORER) {
482 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
483 } else {
484 regs->gprs[14] = (__u64) frame->retcode;
485 if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
486 (u16 __user *)(frame->retcode)))
487 goto give_sigsegv;
488 }
489
490 /* Set up backchain. */
491 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
492 goto give_sigsegv;
493
494 /* Set up registers for signal handler */
495 regs->gprs[15] = (__u64) frame;
496 regs->psw.addr = (__u64) ka->sa.sa_handler;
497
498 regs->gprs[2] = map_signal(sig);
499 regs->gprs[3] = (__u64) &frame->sc;
500
501 /* We forgot to include these in the sigcontext.
502 To avoid breaking binary compatibility, they are passed as args. */
503 regs->gprs[4] = current->thread.trap_no;
504 regs->gprs[5] = current->thread.prot_addr;
505
506 /* Place signal number on stack to allow backtrace from handler. */
507 if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
508 goto give_sigsegv;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800509 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
511give_sigsegv:
512 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800513 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514}
515
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800516static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 sigset_t *set, struct pt_regs * regs)
518{
519 int err = 0;
520 rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
521 if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32)))
522 goto give_sigsegv;
523
Heiko Carstensde553432008-04-17 07:45:57 +0200524 if (frame == (void __user *) -1UL)
525 goto give_sigsegv;
526
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 if (copy_siginfo_to_user32(&frame->info, info))
528 goto give_sigsegv;
529
530 /* Create the ucontext. */
531 err |= __put_user(0, &frame->uc.uc_flags);
532 err |= __put_user(0, &frame->uc.uc_link);
533 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
534 err |= __put_user(sas_ss_flags(regs->gprs[15]),
535 &frame->uc.uc_stack.ss_flags);
536 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
537 err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
538 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
539 if (err)
540 goto give_sigsegv;
541
542 /* Set up to return from userspace. If provided, use a stub
543 already in userspace. */
544 if (ka->sa.sa_flags & SA_RESTORER) {
545 regs->gprs[14] = (__u64) ka->sa.sa_restorer;
546 } else {
547 regs->gprs[14] = (__u64) frame->retcode;
548 err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
549 (u16 __user *)(frame->retcode));
550 }
551
552 /* Set up backchain. */
553 if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
554 goto give_sigsegv;
555
556 /* Set up registers for signal handler */
557 regs->gprs[15] = (__u64) frame;
558 regs->psw.addr = (__u64) ka->sa.sa_handler;
559
560 regs->gprs[2] = map_signal(sig);
561 regs->gprs[3] = (__u64) &frame->info;
562 regs->gprs[4] = (__u64) &frame->uc;
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800563 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
565give_sigsegv:
566 force_sigsegv(sig, current);
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800567 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568}
569
570/*
571 * OK, we're invoking a handler
572 */
573
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800574int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575handle_signal32(unsigned long sig, struct k_sigaction *ka,
576 siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
577{
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800578 int ret;
579
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 /* Set up the stack frame */
581 if (ka->sa.sa_flags & SA_SIGINFO)
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800582 ret = setup_rt_frame32(sig, ka, info, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 else
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800584 ret = setup_frame32(sig, ka, oldset, regs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Heiko Carstens54dfe5d2006-02-01 03:06:38 -0800586 if (ret == 0) {
587 spin_lock_irq(&current->sighand->siglock);
588 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
589 if (!(ka->sa.sa_flags & SA_NODEFER))
590 sigaddset(&current->blocked,sig);
591 recalc_sigpending();
592 spin_unlock_irq(&current->sighand->siglock);
593 }
594 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595}
596