blob: 5934f33224f8b63eb14e78c1bcc6633b2c8d89c1 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 1991, 1992 Linus Torvalds
Martin Michlmayrdda73d02006-02-18 15:21:30 +00007 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
Ralf Baechle02416dc2005-06-15 13:00:12 +000010#include <linux/cache.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/smp.h>
14#include <linux/smp_lock.h>
15#include <linux/kernel.h>
16#include <linux/signal.h>
17#include <linux/syscalls.h>
18#include <linux/errno.h>
19#include <linux/wait.h>
20#include <linux/ptrace.h>
21#include <linux/compat.h>
22#include <linux/suspend.h>
23#include <linux/compiler.h>
24
Ralf Baechlee50c0a82005-05-31 11:49:19 +000025#include <asm/abi.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <asm/asm.h>
27#include <linux/bitops.h>
28#include <asm/cacheflush.h>
29#include <asm/sim.h>
30#include <asm/uaccess.h>
31#include <asm/ucontext.h>
32#include <asm/system.h>
33#include <asm/fpu.h>
Ralf Baechle02416dc2005-06-15 13:00:12 +000034#include <asm/war.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Franck Bui-Huu36a1f2c22007-02-05 15:24:22 +010036#include "signal-common.h"
37
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
39
40typedef struct compat_siginfo {
41 int si_signo;
42 int si_code;
43 int si_errno;
44
45 union {
46 int _pad[SI_PAD_SIZE32];
47
48 /* kill() */
49 struct {
50 compat_pid_t _pid; /* sender's pid */
51 compat_uid_t _uid; /* sender's uid */
52 } _kill;
53
54 /* SIGCHLD */
55 struct {
56 compat_pid_t _pid; /* which child */
57 compat_uid_t _uid; /* sender's uid */
58 int _status; /* exit code */
59 compat_clock_t _utime;
60 compat_clock_t _stime;
61 } _sigchld;
62
63 /* IRIX SIGCHLD */
64 struct {
65 compat_pid_t _pid; /* which child */
66 compat_clock_t _utime;
67 int _status; /* exit code */
68 compat_clock_t _stime;
69 } _irix_sigchld;
70
71 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
72 struct {
73 s32 _addr; /* faulting insn/memory ref. */
74 } _sigfault;
75
76 /* SIGPOLL, SIGXFSZ (To do ...) */
77 struct {
78 int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
79 int _fd;
80 } _sigpoll;
81
82 /* POSIX.1b timers */
83 struct {
Ralf Baechlea9820992005-02-16 21:24:16 +000084 timer_t _tid; /* timer id */
85 int _overrun; /* overrun count */
Ralf Baechle209ac8d2005-03-18 17:36:42 +000086 compat_sigval_t _sigval;/* same as below */
Ralf Baechlea9820992005-02-16 21:24:16 +000087 int _sys_private; /* not to be passed to user */
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 } _timer;
89
90 /* POSIX.1b signals */
91 struct {
92 compat_pid_t _pid; /* sender's pid */
93 compat_uid_t _uid; /* sender's uid */
94 compat_sigval_t _sigval;
95 } _rt;
96
97 } _sifields;
98} compat_siginfo_t;
99
100/*
101 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
102 */
103#define __NR_O32_sigreturn 4119
104#define __NR_O32_rt_sigreturn 4193
105#define __NR_O32_restart_syscall 4253
106
107#define DEBUG_SIG 0
108
109#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111/* 32-bit compatibility types */
112
113#define _NSIG_BPW32 32
114#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
115
116typedef struct {
117 unsigned int sig[_NSIG_WORDS32];
118} sigset_t32;
119
120typedef unsigned int __sighandler32_t;
121typedef void (*vfptr_t)(void);
122
123struct sigaction32 {
124 unsigned int sa_flags;
125 __sighandler32_t sa_handler;
126 compat_sigset_t sa_mask;
127};
128
129/* IRIX compatible stack_t */
130typedef struct sigaltstack32 {
131 s32 ss_sp;
132 compat_size_t ss_size;
133 int ss_flags;
134} stack32_t;
135
136struct ucontext32 {
137 u32 uc_flags;
138 s32 uc_link;
139 stack32_t uc_stack;
140 struct sigcontext32 uc_mcontext;
141 sigset_t32 uc_sigmask; /* mask last for extensibility */
142};
143
Franck Bui-Huuc0b9bae2007-02-05 15:24:21 +0100144#if ICACHE_REFILLS_WORKAROUND_WAR == 0
145
146struct rt_sigframe32 {
147 u32 rs_ass[4]; /* argument save space for o32 */
148 u32 rs_code[2]; /* signal trampoline */
149 compat_siginfo_t rs_info;
150 struct ucontext32 rs_uc;
151};
152
153#else /* ICACHE_REFILLS_WORKAROUND_WAR */
154
155struct rt_sigframe32 {
156 u32 rs_ass[4]; /* argument save space for o32 */
157 u32 rs_pad[2];
158 compat_siginfo_t rs_info;
159 struct ucontext32 rs_uc;
160 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
161};
162
163#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165extern void __put_sigset_unknown_nsig(void);
166extern void __get_sigset_unknown_nsig(void);
167
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900168static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169{
170 int err = 0;
171
172 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
173 return -EFAULT;
174
175 switch (_NSIG_WORDS) {
176 default:
177 __put_sigset_unknown_nsig();
178 case 2:
179 err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
180 err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
181 case 1:
182 err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
183 err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
184 }
185
186 return err;
187}
188
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900189static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190{
191 int err = 0;
192 unsigned long sig[4];
193
194 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
195 return -EFAULT;
196
197 switch (_NSIG_WORDS) {
198 default:
199 __get_sigset_unknown_nsig();
200 case 2:
201 err |= __get_user (sig[3], &ubuf->sig[3]);
202 err |= __get_user (sig[2], &ubuf->sig[2]);
203 kbuf->sig[1] = sig[2] | (sig[3] << 32);
204 case 1:
205 err |= __get_user (sig[1], &ubuf->sig[1]);
206 err |= __get_user (sig[0], &ubuf->sig[0]);
207 kbuf->sig[0] = sig[0] | (sig[1] << 32);
208 }
209
210 return err;
211}
212
213/*
214 * Atomically swap in the new signal mask, and wait for a signal.
215 */
216
217save_static_function(sys32_sigsuspend);
218__attribute_used__ noinline static int
219_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
220{
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900221 compat_sigset_t __user *uset;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000222 sigset_t newset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900224 uset = (compat_sigset_t __user *) regs.regs[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 if (get_sigset(&newset, uset))
226 return -EFAULT;
227 sigdelsetmask(&newset, ~_BLOCKABLE);
228
229 spin_lock_irq(&current->sighand->siglock);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000230 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 current->blocked = newset;
232 recalc_sigpending();
233 spin_unlock_irq(&current->sighand->siglock);
234
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000235 current->state = TASK_INTERRUPTIBLE;
236 schedule();
237 set_thread_flag(TIF_RESTORE_SIGMASK);
238 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239}
240
241save_static_function(sys32_rt_sigsuspend);
242__attribute_used__ noinline static int
243_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
244{
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900245 compat_sigset_t __user *uset;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000246 sigset_t newset;
Ralf Baechle304416d2006-02-18 18:20:47 +0000247 size_t sigsetsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
249 /* XXX Don't preclude handling different sized sigset_t's. */
250 sigsetsize = regs.regs[5];
251 if (sigsetsize != sizeof(compat_sigset_t))
252 return -EINVAL;
253
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900254 uset = (compat_sigset_t __user *) regs.regs[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 if (get_sigset(&newset, uset))
256 return -EFAULT;
257 sigdelsetmask(&newset, ~_BLOCKABLE);
258
259 spin_lock_irq(&current->sighand->siglock);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000260 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 current->blocked = newset;
Martin Michlmayr62549442006-02-18 20:06:32 +0000262 recalc_sigpending();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 spin_unlock_irq(&current->sighand->siglock);
264
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000265 current->state = TASK_INTERRUPTIBLE;
266 schedule();
267 set_thread_flag(TIF_RESTORE_SIGMASK);
268 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269}
270
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900271asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
272 struct sigaction32 __user *oact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273{
274 struct k_sigaction new_ka, old_ka;
275 int ret;
276 int err = 0;
277
278 if (act) {
279 old_sigset_t mask;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000280 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
282 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
283 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000284 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900285 new_ka.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
287 err |= __get_user(mask, &act->sa_mask.sig[0]);
288 if (err)
289 return -EFAULT;
290
291 siginitset(&new_ka.sa.sa_mask, mask);
292 }
293
294 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
295
296 if (!ret && oact) {
297 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
Martin Michlmayr62549442006-02-18 20:06:32 +0000298 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
300 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
301 &oact->sa_handler);
302 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
Martin Michlmayr62549442006-02-18 20:06:32 +0000303 err |= __put_user(0, &oact->sa_mask.sig[1]);
304 err |= __put_user(0, &oact->sa_mask.sig[2]);
305 err |= __put_user(0, &oact->sa_mask.sig[3]);
306 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 return -EFAULT;
308 }
309
310 return ret;
311}
312
313asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
314{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900315 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
316 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 unsigned long usp = regs.regs[29];
318 stack_t kss, koss;
319 int ret, err = 0;
320 mm_segment_t old_fs = get_fs();
321 s32 sp;
322
323 if (uss) {
324 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
325 return -EFAULT;
326 err |= __get_user(sp, &uss->ss_sp);
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900327 kss.ss_sp = (void __user *) (long) sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 err |= __get_user(kss.ss_size, &uss->ss_size);
329 err |= __get_user(kss.ss_flags, &uss->ss_flags);
330 if (err)
331 return -EFAULT;
332 }
333
334 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900335 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
336 uoss ? (stack_t __user *)&koss : NULL, usp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 set_fs (old_fs);
338
339 if (!ret && uoss) {
340 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
341 return -EFAULT;
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900342 sp = (int) (unsigned long) koss.ss_sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 err |= __put_user(sp, &uoss->ss_sp);
344 err |= __put_user(koss.ss_size, &uoss->ss_size);
345 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
346 if (err)
347 return -EFAULT;
348 }
349 return ret;
350}
351
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900352static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353{
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000354 u32 used_math;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 int err = 0;
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000356 s32 treg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
358 /* Always make any pending restarted system calls return -EINTR */
359 current_thread_info()->restart_block.fn = do_no_restart_syscall;
360
361 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
362 err |= __get_user(regs->hi, &sc->sc_mdhi);
363 err |= __get_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000364 if (cpu_has_dsp) {
365 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
366 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
367 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
368 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
369 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
370 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
371 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
374#define restore_gp_reg(i) do { \
375 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
376} while(0)
377 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
378 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
379 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
380 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
381 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
382 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
383 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
384 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
385 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
386 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
387 restore_gp_reg(31);
388#undef restore_gp_reg
389
390 err |= __get_user(used_math, &sc->sc_used_math);
391 conditional_used_math(used_math);
392
393 preempt_disable();
394
395 if (used_math()) {
396 /* restore fpu context if we have used it before */
397 own_fpu();
398 err |= restore_fp_context32(sc);
399 } else {
400 /* signal handler may have used FPU. Give it up. */
401 lose_fpu();
402 }
403
404 preempt_enable();
405
406 return err;
407}
408
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900409int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410{
411 int err;
412
413 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
414 return -EFAULT;
415
416 /* If you change siginfo_t structure, please be sure
417 this code is fixed accordingly.
418 It should never copy any pad contained in the structure
419 to avoid security leaks, but must copy the generic
420 3 ints plus the relevant union member.
421 This routine must convert siginfo from 64bit to 32bit as well
422 at the same time. */
423 err = __put_user(from->si_signo, &to->si_signo);
424 err |= __put_user(from->si_errno, &to->si_errno);
425 err |= __put_user((short)from->si_code, &to->si_code);
426 if (from->si_code < 0)
427 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
428 else {
429 switch (from->si_code >> 16) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000430 case __SI_TIMER >> 16:
431 err |= __put_user(from->si_tid, &to->si_tid);
432 err |= __put_user(from->si_overrun, &to->si_overrun);
433 err |= __put_user(from->si_int, &to->si_int);
434 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 case __SI_CHLD >> 16:
436 err |= __put_user(from->si_utime, &to->si_utime);
437 err |= __put_user(from->si_stime, &to->si_stime);
438 err |= __put_user(from->si_status, &to->si_status);
439 default:
440 err |= __put_user(from->si_pid, &to->si_pid);
441 err |= __put_user(from->si_uid, &to->si_uid);
442 break;
443 case __SI_FAULT >> 16:
Atsushi Nemoto5665a0a2006-02-02 01:26:34 +0900444 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445 break;
446 case __SI_POLL >> 16:
447 err |= __put_user(from->si_band, &to->si_band);
448 err |= __put_user(from->si_fd, &to->si_fd);
449 break;
450 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
451 case __SI_MESGQ >> 16:
452 err |= __put_user(from->si_pid, &to->si_pid);
453 err |= __put_user(from->si_uid, &to->si_uid);
454 err |= __put_user(from->si_int, &to->si_int);
455 break;
456 }
457 }
458 return err;
459}
460
461save_static_function(sys32_sigreturn);
462__attribute_used__ noinline static void
463_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
464{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900465 struct sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 sigset_t blocked;
467
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900468 frame = (struct sigframe __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
470 goto badframe;
471 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
472 goto badframe;
473
474 sigdelsetmask(&blocked, ~_BLOCKABLE);
475 spin_lock_irq(&current->sighand->siglock);
476 current->blocked = blocked;
477 recalc_sigpending();
478 spin_unlock_irq(&current->sighand->siglock);
479
480 if (restore_sigcontext32(&regs, &frame->sf_sc))
481 goto badframe;
482
483 /*
484 * Don't let your children do this ...
485 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 __asm__ __volatile__(
487 "move\t$29, %0\n\t"
488 "j\tsyscall_exit"
489 :/* no outputs */
490 :"r" (&regs));
491 /* Unreached */
492
493badframe:
494 force_sig(SIGSEGV, current);
495}
496
497save_static_function(sys32_rt_sigreturn);
498__attribute_used__ noinline static void
499_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
500{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900501 struct rt_sigframe32 __user *frame;
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000502 mm_segment_t old_fs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 sigset_t set;
504 stack_t st;
505 s32 sp;
506
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900507 frame = (struct rt_sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
509 goto badframe;
510 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
511 goto badframe;
512
513 sigdelsetmask(&set, ~_BLOCKABLE);
514 spin_lock_irq(&current->sighand->siglock);
515 current->blocked = set;
516 recalc_sigpending();
517 spin_unlock_irq(&current->sighand->siglock);
518
519 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
520 goto badframe;
521
522 /* The ucontext contains a stack32_t, so we must convert! */
523 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
524 goto badframe;
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900525 st.ss_sp = (void __user *)(long) sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
527 goto badframe;
528 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
529 goto badframe;
530
531 /* It is more difficult to avoid calling this function than to
532 call it and ignore errors. */
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000533 old_fs = get_fs();
534 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900535 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000536 set_fs (old_fs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
538 /*
539 * Don't let your children do this ...
540 */
541 __asm__ __volatile__(
542 "move\t$29, %0\n\t"
543 "j\tsyscall_exit"
544 :/* no outputs */
545 :"r" (&regs));
546 /* Unreached */
547
548badframe:
549 force_sig(SIGSEGV, current);
550}
551
552static inline int setup_sigcontext32(struct pt_regs *regs,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900553 struct sigcontext32 __user *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554{
555 int err = 0;
556
557 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
558 err |= __put_user(regs->cp0_status, &sc->sc_status);
559
560#define save_gp_reg(i) { \
561 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
562} while(0)
563 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
564 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
565 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
566 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
567 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
568 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
569 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
570 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
571 save_gp_reg(31);
572#undef save_gp_reg
573
574 err |= __put_user(regs->hi, &sc->sc_mdhi);
575 err |= __put_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000576 if (cpu_has_dsp) {
Ralf Baechlec4fa6342005-12-07 17:50:48 +0000577 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000578 err |= __put_user(mfhi1(), &sc->sc_hi1);
579 err |= __put_user(mflo1(), &sc->sc_lo1);
580 err |= __put_user(mfhi2(), &sc->sc_hi2);
581 err |= __put_user(mflo2(), &sc->sc_lo2);
582 err |= __put_user(mfhi3(), &sc->sc_hi3);
583 err |= __put_user(mflo3(), &sc->sc_lo3);
584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
586 err |= __put_user(!!used_math(), &sc->sc_used_math);
587
588 if (!used_math())
589 goto out;
590
Ralf Baechle42a3b4f2005-09-03 15:56:17 -0700591 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 * Save FPU state to signal context. Signal handler will "inherit"
593 * current FPU state.
594 */
595 preempt_disable();
596
597 if (!is_fpu_owner()) {
598 own_fpu();
599 restore_fp(current);
600 }
601 err |= save_fp_context32(sc);
602
603 preempt_enable();
604
605out:
606 return err;
607}
608
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900609int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
610 int signr, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900612 struct sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 int err = 0;
614
615 frame = get_sigframe(ka, regs, sizeof(*frame));
616 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
617 goto give_sigsegv;
618
Franck Bui-Huu36a1f2c22007-02-05 15:24:22 +0100619 err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 err |= setup_sigcontext32(regs, &frame->sf_sc);
622 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
623 if (err)
624 goto give_sigsegv;
625
626 /*
627 * Arguments to signal handler:
628 *
629 * a0 = signal number
630 * a1 = 0 (should be cause)
631 * a2 = pointer to struct sigcontext
632 *
633 * $25 and c0_epc point to the signal handler, $29 points to the
634 * struct sigframe.
635 */
636 regs->regs[ 4] = signr;
637 regs->regs[ 5] = 0;
638 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
639 regs->regs[29] = (unsigned long) frame;
640 regs->regs[31] = (unsigned long) frame->sf_code;
641 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
642
643#if DEBUG_SIG
644 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
645 current->comm, current->pid,
646 frame, regs->cp0_epc, frame->sf_code);
647#endif
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000648 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
650give_sigsegv:
651 force_sigsegv(signr, current);
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000652 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653}
654
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900655int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
656 int signr, sigset_t *set, siginfo_t *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900658 struct rt_sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 int err = 0;
660 s32 sp;
661
662 frame = get_sigframe(ka, regs, sizeof(*frame));
663 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
664 goto give_sigsegv;
665
Franck Bui-Huu36a1f2c22007-02-05 15:24:22 +0100666 err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
668 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
669 err |= copy_siginfo_to_user32(&frame->rs_info, info);
670
671 /* Create the ucontext. */
672 err |= __put_user(0, &frame->rs_uc.uc_flags);
673 err |= __put_user(0, &frame->rs_uc.uc_link);
674 sp = (int) (long) current->sas_ss_sp;
675 err |= __put_user(sp,
676 &frame->rs_uc.uc_stack.ss_sp);
677 err |= __put_user(sas_ss_flags(regs->regs[29]),
678 &frame->rs_uc.uc_stack.ss_flags);
679 err |= __put_user(current->sas_ss_size,
680 &frame->rs_uc.uc_stack.ss_size);
681 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
682 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
683
684 if (err)
685 goto give_sigsegv;
686
687 /*
688 * Arguments to signal handler:
689 *
690 * a0 = signal number
691 * a1 = 0 (should be cause)
692 * a2 = pointer to ucontext
693 *
694 * $25 and c0_epc point to the signal handler, $29 points to
695 * the struct rt_sigframe32.
696 */
697 regs->regs[ 4] = signr;
698 regs->regs[ 5] = (unsigned long) &frame->rs_info;
699 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
700 regs->regs[29] = (unsigned long) frame;
701 regs->regs[31] = (unsigned long) frame->rs_code;
702 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
703
704#if DEBUG_SIG
705 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
706 current->comm, current->pid,
707 frame, regs->cp0_epc, frame->rs_code);
708#endif
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000709 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711give_sigsegv:
712 force_sigsegv(signr, current);
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000713 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
715
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000716static inline int handle_signal(unsigned long sig, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
718{
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000719 int ret;
720
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 switch (regs->regs[0]) {
722 case ERESTART_RESTARTBLOCK:
723 case ERESTARTNOHAND:
724 regs->regs[2] = EINTR;
725 break;
726 case ERESTARTSYS:
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000727 if (!(ka->sa.sa_flags & SA_RESTART)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 regs->regs[2] = EINTR;
729 break;
730 }
731 /* fallthrough */
732 case ERESTARTNOINTR: /* Userland will reload $v0. */
733 regs->regs[7] = regs->regs[26];
734 regs->cp0_epc -= 8;
735 }
736
737 regs->regs[0] = 0; /* Don't deal with this again. */
738
739 if (ka->sa.sa_flags & SA_SIGINFO)
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000740 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 else
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000742 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Steven Rostedt69be8f12005-08-29 11:44:09 -0400744 spin_lock_irq(&current->sighand->siglock);
745 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
746 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400748 recalc_sigpending();
749 spin_unlock_irq(&current->sighand->siglock);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000750
751 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752}
753
Martin Michlmayrdda73d02006-02-18 15:21:30 +0000754void do_signal32(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755{
756 struct k_sigaction ka;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000757 sigset_t *oldset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 siginfo_t info;
759 int signr;
760
761 /*
762 * We want the common case to go fast, which is why we may in certain
763 * cases get here from kernel mode. Just return without doing anything
764 * if so.
765 */
766 if (!user_mode(regs))
Martin Michlmayrdda73d02006-02-18 15:21:30 +0000767 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000769 if (test_thread_flag(TIF_RESTORE_SIGMASK))
770 oldset = &current->saved_sigmask;
771 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 oldset = &current->blocked;
773
774 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000775 if (signr > 0) {
776 /* Whee! Actually deliver the signal. */
777 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
778 /*
779 * A signal was successfully delivered; the saved
780 * sigmask will have been stored in the signal frame,
781 * and will be restored by sigreturn, so we can simply
782 * clear the TIF_RESTORE_SIGMASK flag.
783 */
784 if (test_thread_flag(TIF_RESTORE_SIGMASK))
785 clear_thread_flag(TIF_RESTORE_SIGMASK);
786 }
Ralf Baechle45887e12006-08-03 21:54:13 +0100787
788 return;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000789 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 /*
792 * Who's code doesn't conform to the restartable syscall convention
793 * dies here!!! The li instruction, a single machine instruction,
794 * must directly be followed by the syscall instruction.
795 */
796 if (regs->regs[0]) {
797 if (regs->regs[2] == ERESTARTNOHAND ||
798 regs->regs[2] == ERESTARTSYS ||
799 regs->regs[2] == ERESTARTNOINTR) {
800 regs->regs[7] = regs->regs[26];
801 regs->cp0_epc -= 8;
802 }
803 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
804 regs->regs[2] = __NR_O32_restart_syscall;
805 regs->regs[7] = regs->regs[26];
806 regs->cp0_epc -= 4;
807 }
Ralf Baechle13fdd312006-08-08 03:47:01 +0100808 regs->regs[0] = 0; /* Don't deal with this again. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 }
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000810
811 /*
812 * If there's no signal to deliver, we just put the saved sigmask
813 * back
814 */
815 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
816 clear_thread_flag(TIF_RESTORE_SIGMASK);
817 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819}
820
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900821asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900822 struct sigaction32 __user *oact,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 unsigned int sigsetsize)
824{
825 struct k_sigaction new_sa, old_sa;
826 int ret = -EINVAL;
827
828 /* XXX: Don't preclude handling different sized sigset_t's. */
829 if (sigsetsize != sizeof(sigset_t))
830 goto out;
831
832 if (act) {
Ralf Baechle77c728c2005-03-04 19:36:51 +0000833 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 int err = 0;
835
836 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
837 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000838 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900839 new_sa.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
841 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
842 if (err)
843 return -EFAULT;
844 }
845
846 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
847
848 if (!ret && oact) {
849 int err = 0;
850
851 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
852 return -EFAULT;
853
854 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
855 &oact->sa_handler);
856 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
857 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
858 if (err)
859 return -EFAULT;
860 }
861out:
862 return ret;
863}
864
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900865asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900866 compat_sigset_t __user *oset, unsigned int sigsetsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867{
868 sigset_t old_set, new_set;
869 int ret;
870 mm_segment_t old_fs = get_fs();
871
872 if (set && get_sigset(&new_set, set))
873 return -EFAULT;
874
875 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900876 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
877 oset ? (sigset_t __user *)&old_set : NULL,
878 sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 set_fs (old_fs);
880
881 if (!ret && oset && put_sigset(&old_set, oset))
882 return -EFAULT;
883
884 return ret;
885}
886
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900887asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 unsigned int sigsetsize)
889{
890 int ret;
891 sigset_t set;
892 mm_segment_t old_fs = get_fs();
893
894 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900895 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 set_fs (old_fs);
897
898 if (!ret && put_sigset(&set, uset))
899 return -EFAULT;
900
901 return ret;
902}
903
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900904asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
906 siginfo_t info;
907 int ret;
908 mm_segment_t old_fs = get_fs();
909
910 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
911 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
912 return -EFAULT;
913 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900914 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 set_fs (old_fs);
916 return ret;
917}
Ralf Baechle54f2da72005-02-16 21:21:29 +0000918
919asmlinkage long
920sys32_waitid(int which, compat_pid_t pid,
921 compat_siginfo_t __user *uinfo, int options,
922 struct compat_rusage __user *uru)
923{
924 siginfo_t info;
925 struct rusage ru;
926 long ret;
927 mm_segment_t old_fs = get_fs();
928
929 info.si_signo = 0;
930 set_fs (KERNEL_DS);
931 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
932 uru ? (struct rusage __user *) &ru : NULL);
933 set_fs (old_fs);
934
935 if (ret < 0 || info.si_signo == 0)
936 return ret;
937
938 if (uru && (ret = put_compat_rusage(&ru, uru)))
939 return ret;
940
941 BUG_ON(info.si_code & __SI_MASK);
942 info.si_code |= __SI_CHLD;
943 return copy_siginfo_to_user32(uinfo, &info);
944}