blob: f2791a1e76097d7a18cd9efc616d9495ff700809 [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
36#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3)
37
38typedef struct compat_siginfo {
39 int si_signo;
40 int si_code;
41 int si_errno;
42
43 union {
44 int _pad[SI_PAD_SIZE32];
45
46 /* kill() */
47 struct {
48 compat_pid_t _pid; /* sender's pid */
49 compat_uid_t _uid; /* sender's uid */
50 } _kill;
51
52 /* SIGCHLD */
53 struct {
54 compat_pid_t _pid; /* which child */
55 compat_uid_t _uid; /* sender's uid */
56 int _status; /* exit code */
57 compat_clock_t _utime;
58 compat_clock_t _stime;
59 } _sigchld;
60
61 /* IRIX SIGCHLD */
62 struct {
63 compat_pid_t _pid; /* which child */
64 compat_clock_t _utime;
65 int _status; /* exit code */
66 compat_clock_t _stime;
67 } _irix_sigchld;
68
69 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
70 struct {
71 s32 _addr; /* faulting insn/memory ref. */
72 } _sigfault;
73
74 /* SIGPOLL, SIGXFSZ (To do ...) */
75 struct {
76 int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
77 int _fd;
78 } _sigpoll;
79
80 /* POSIX.1b timers */
81 struct {
Ralf Baechlea9820992005-02-16 21:24:16 +000082 timer_t _tid; /* timer id */
83 int _overrun; /* overrun count */
Ralf Baechle209ac8d2005-03-18 17:36:42 +000084 compat_sigval_t _sigval;/* same as below */
Ralf Baechlea9820992005-02-16 21:24:16 +000085 int _sys_private; /* not to be passed to user */
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 } _timer;
87
88 /* POSIX.1b signals */
89 struct {
90 compat_pid_t _pid; /* sender's pid */
91 compat_uid_t _uid; /* sender's uid */
92 compat_sigval_t _sigval;
93 } _rt;
94
95 } _sifields;
96} compat_siginfo_t;
97
98/*
99 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
100 */
101#define __NR_O32_sigreturn 4119
102#define __NR_O32_rt_sigreturn 4193
103#define __NR_O32_restart_syscall 4253
104
105#define DEBUG_SIG 0
106
107#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/* 32-bit compatibility types */
110
111#define _NSIG_BPW32 32
112#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32)
113
114typedef struct {
115 unsigned int sig[_NSIG_WORDS32];
116} sigset_t32;
117
118typedef unsigned int __sighandler32_t;
119typedef void (*vfptr_t)(void);
120
121struct sigaction32 {
122 unsigned int sa_flags;
123 __sighandler32_t sa_handler;
124 compat_sigset_t sa_mask;
125};
126
127/* IRIX compatible stack_t */
128typedef struct sigaltstack32 {
129 s32 ss_sp;
130 compat_size_t ss_size;
131 int ss_flags;
132} stack32_t;
133
134struct ucontext32 {
135 u32 uc_flags;
136 s32 uc_link;
137 stack32_t uc_stack;
138 struct sigcontext32 uc_mcontext;
139 sigset_t32 uc_sigmask; /* mask last for extensibility */
140};
141
142extern void __put_sigset_unknown_nsig(void);
143extern void __get_sigset_unknown_nsig(void);
144
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900145static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146{
147 int err = 0;
148
149 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
150 return -EFAULT;
151
152 switch (_NSIG_WORDS) {
153 default:
154 __put_sigset_unknown_nsig();
155 case 2:
156 err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
157 err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
158 case 1:
159 err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
160 err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
161 }
162
163 return err;
164}
165
166static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf)
167{
168 int err = 0;
169 unsigned long sig[4];
170
171 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
172 return -EFAULT;
173
174 switch (_NSIG_WORDS) {
175 default:
176 __get_sigset_unknown_nsig();
177 case 2:
178 err |= __get_user (sig[3], &ubuf->sig[3]);
179 err |= __get_user (sig[2], &ubuf->sig[2]);
180 kbuf->sig[1] = sig[2] | (sig[3] << 32);
181 case 1:
182 err |= __get_user (sig[1], &ubuf->sig[1]);
183 err |= __get_user (sig[0], &ubuf->sig[0]);
184 kbuf->sig[0] = sig[0] | (sig[1] << 32);
185 }
186
187 return err;
188}
189
190/*
191 * Atomically swap in the new signal mask, and wait for a signal.
192 */
193
194save_static_function(sys32_sigsuspend);
195__attribute_used__ noinline static int
196_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
197{
198 compat_sigset_t *uset;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000199 sigset_t newset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201 uset = (compat_sigset_t *) regs.regs[4];
202 if (get_sigset(&newset, uset))
203 return -EFAULT;
204 sigdelsetmask(&newset, ~_BLOCKABLE);
205
206 spin_lock_irq(&current->sighand->siglock);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000207 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 current->blocked = newset;
209 recalc_sigpending();
210 spin_unlock_irq(&current->sighand->siglock);
211
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000212 current->state = TASK_INTERRUPTIBLE;
213 schedule();
214 set_thread_flag(TIF_RESTORE_SIGMASK);
215 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216}
217
218save_static_function(sys32_rt_sigsuspend);
219__attribute_used__ noinline static int
220_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
221{
222 compat_sigset_t *uset;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000223 sigset_t newset;
Ralf Baechle304416d2006-02-18 18:20:47 +0000224 size_t sigsetsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 /* XXX Don't preclude handling different sized sigset_t's. */
227 sigsetsize = regs.regs[5];
228 if (sigsetsize != sizeof(compat_sigset_t))
229 return -EINVAL;
230
231 uset = (compat_sigset_t *) regs.regs[4];
232 if (get_sigset(&newset, uset))
233 return -EFAULT;
234 sigdelsetmask(&newset, ~_BLOCKABLE);
235
236 spin_lock_irq(&current->sighand->siglock);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000237 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 current->blocked = newset;
Martin Michlmayr62549442006-02-18 20:06:32 +0000239 recalc_sigpending();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 spin_unlock_irq(&current->sighand->siglock);
241
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000242 current->state = TASK_INTERRUPTIBLE;
243 schedule();
244 set_thread_flag(TIF_RESTORE_SIGMASK);
245 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246}
247
248asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
249 struct sigaction32 *oact)
250{
251 struct k_sigaction new_ka, old_ka;
252 int ret;
253 int err = 0;
254
255 if (act) {
256 old_sigset_t mask;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000257 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
260 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000261 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900262 new_ka.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
264 err |= __get_user(mask, &act->sa_mask.sig[0]);
265 if (err)
266 return -EFAULT;
267
268 siginitset(&new_ka.sa.sa_mask, mask);
269 }
270
271 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
272
273 if (!ret && oact) {
274 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
Martin Michlmayr62549442006-02-18 20:06:32 +0000275 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
277 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
278 &oact->sa_handler);
279 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
Martin Michlmayr62549442006-02-18 20:06:32 +0000280 err |= __put_user(0, &oact->sa_mask.sig[1]);
281 err |= __put_user(0, &oact->sa_mask.sig[2]);
282 err |= __put_user(0, &oact->sa_mask.sig[3]);
283 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 return -EFAULT;
285 }
286
287 return ret;
288}
289
290asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
291{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900292 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
293 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 unsigned long usp = regs.regs[29];
295 stack_t kss, koss;
296 int ret, err = 0;
297 mm_segment_t old_fs = get_fs();
298 s32 sp;
299
300 if (uss) {
301 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
302 return -EFAULT;
303 err |= __get_user(sp, &uss->ss_sp);
304 kss.ss_sp = (void *) (long) sp;
305 err |= __get_user(kss.ss_size, &uss->ss_size);
306 err |= __get_user(kss.ss_flags, &uss->ss_flags);
307 if (err)
308 return -EFAULT;
309 }
310
311 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900312 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
313 uoss ? (stack_t __user *)&koss : NULL, usp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 set_fs (old_fs);
315
316 if (!ret && uoss) {
317 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
318 return -EFAULT;
319 sp = (int) (long) koss.ss_sp;
320 err |= __put_user(sp, &uoss->ss_sp);
321 err |= __put_user(koss.ss_size, &uoss->ss_size);
322 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
323 if (err)
324 return -EFAULT;
325 }
326 return ret;
327}
328
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900329static int restore_sigcontext32(struct pt_regs *regs, struct sigcontext32 __user *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330{
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000331 u32 used_math;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 int err = 0;
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000333 s32 treg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335 /* Always make any pending restarted system calls return -EINTR */
336 current_thread_info()->restart_block.fn = do_no_restart_syscall;
337
338 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
339 err |= __get_user(regs->hi, &sc->sc_mdhi);
340 err |= __get_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000341 if (cpu_has_dsp) {
342 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
343 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
344 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
345 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
346 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
347 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
348 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351#define restore_gp_reg(i) do { \
352 err |= __get_user(regs->regs[i], &sc->sc_regs[i]); \
353} while(0)
354 restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
355 restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
356 restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
357 restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
358 restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
359 restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
360 restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
361 restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
362 restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
363 restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
364 restore_gp_reg(31);
365#undef restore_gp_reg
366
367 err |= __get_user(used_math, &sc->sc_used_math);
368 conditional_used_math(used_math);
369
370 preempt_disable();
371
372 if (used_math()) {
373 /* restore fpu context if we have used it before */
374 own_fpu();
375 err |= restore_fp_context32(sc);
376 } else {
377 /* signal handler may have used FPU. Give it up. */
378 lose_fpu();
379 }
380
381 preempt_enable();
382
383 return err;
384}
385
386struct sigframe {
387 u32 sf_ass[4]; /* argument save space for o32 */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000388#if ICACHE_REFILLS_WORKAROUND_WAR
389 u32 sf_pad[2];
390#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 u32 sf_code[2]; /* signal trampoline */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000392#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 struct sigcontext32 sf_sc;
394 sigset_t sf_mask;
Ralf Baechle02416dc2005-06-15 13:00:12 +0000395#if ICACHE_REFILLS_WORKAROUND_WAR
396 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
397#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398};
399
400struct rt_sigframe32 {
401 u32 rs_ass[4]; /* argument save space for o32 */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000402#if ICACHE_REFILLS_WORKAROUND_WAR
403 u32 rs_pad[2];
404#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 u32 rs_code[2]; /* signal trampoline */
Ralf Baechle02416dc2005-06-15 13:00:12 +0000406#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 compat_siginfo_t rs_info;
408 struct ucontext32 rs_uc;
Ralf Baechle02416dc2005-06-15 13:00:12 +0000409#if ICACHE_REFILLS_WORKAROUND_WAR
410 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
411#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412};
413
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900414int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415{
416 int err;
417
418 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
419 return -EFAULT;
420
421 /* If you change siginfo_t structure, please be sure
422 this code is fixed accordingly.
423 It should never copy any pad contained in the structure
424 to avoid security leaks, but must copy the generic
425 3 ints plus the relevant union member.
426 This routine must convert siginfo from 64bit to 32bit as well
427 at the same time. */
428 err = __put_user(from->si_signo, &to->si_signo);
429 err |= __put_user(from->si_errno, &to->si_errno);
430 err |= __put_user((short)from->si_code, &to->si_code);
431 if (from->si_code < 0)
432 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
433 else {
434 switch (from->si_code >> 16) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000435 case __SI_TIMER >> 16:
436 err |= __put_user(from->si_tid, &to->si_tid);
437 err |= __put_user(from->si_overrun, &to->si_overrun);
438 err |= __put_user(from->si_int, &to->si_int);
439 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 case __SI_CHLD >> 16:
441 err |= __put_user(from->si_utime, &to->si_utime);
442 err |= __put_user(from->si_stime, &to->si_stime);
443 err |= __put_user(from->si_status, &to->si_status);
444 default:
445 err |= __put_user(from->si_pid, &to->si_pid);
446 err |= __put_user(from->si_uid, &to->si_uid);
447 break;
448 case __SI_FAULT >> 16:
Atsushi Nemoto5665a0a2006-02-02 01:26:34 +0900449 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 break;
451 case __SI_POLL >> 16:
452 err |= __put_user(from->si_band, &to->si_band);
453 err |= __put_user(from->si_fd, &to->si_fd);
454 break;
455 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
456 case __SI_MESGQ >> 16:
457 err |= __put_user(from->si_pid, &to->si_pid);
458 err |= __put_user(from->si_uid, &to->si_uid);
459 err |= __put_user(from->si_int, &to->si_int);
460 break;
461 }
462 }
463 return err;
464}
465
466save_static_function(sys32_sigreturn);
467__attribute_used__ noinline static void
468_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
469{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900470 struct sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 sigset_t blocked;
472
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900473 frame = (struct sigframe __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
475 goto badframe;
476 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
477 goto badframe;
478
479 sigdelsetmask(&blocked, ~_BLOCKABLE);
480 spin_lock_irq(&current->sighand->siglock);
481 current->blocked = blocked;
482 recalc_sigpending();
483 spin_unlock_irq(&current->sighand->siglock);
484
485 if (restore_sigcontext32(&regs, &frame->sf_sc))
486 goto badframe;
487
488 /*
489 * Don't let your children do this ...
490 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 __asm__ __volatile__(
492 "move\t$29, %0\n\t"
493 "j\tsyscall_exit"
494 :/* no outputs */
495 :"r" (&regs));
496 /* Unreached */
497
498badframe:
499 force_sig(SIGSEGV, current);
500}
501
502save_static_function(sys32_rt_sigreturn);
503__attribute_used__ noinline static void
504_sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
505{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900506 struct rt_sigframe32 __user *frame;
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000507 mm_segment_t old_fs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 sigset_t set;
509 stack_t st;
510 s32 sp;
511
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900512 frame = (struct rt_sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
514 goto badframe;
515 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
516 goto badframe;
517
518 sigdelsetmask(&set, ~_BLOCKABLE);
519 spin_lock_irq(&current->sighand->siglock);
520 current->blocked = set;
521 recalc_sigpending();
522 spin_unlock_irq(&current->sighand->siglock);
523
524 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
525 goto badframe;
526
527 /* The ucontext contains a stack32_t, so we must convert! */
528 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
529 goto badframe;
Atsushi Nemoto4cbf8762006-02-14 22:40:45 +0900530 st.ss_sp = (void *)(long) sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
532 goto badframe;
533 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
534 goto badframe;
535
536 /* It is more difficult to avoid calling this function than to
537 call it and ignore errors. */
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000538 old_fs = get_fs();
539 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900540 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000541 set_fs (old_fs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542
543 /*
544 * Don't let your children do this ...
545 */
546 __asm__ __volatile__(
547 "move\t$29, %0\n\t"
548 "j\tsyscall_exit"
549 :/* no outputs */
550 :"r" (&regs));
551 /* Unreached */
552
553badframe:
554 force_sig(SIGSEGV, current);
555}
556
557static inline int setup_sigcontext32(struct pt_regs *regs,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900558 struct sigcontext32 __user *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559{
560 int err = 0;
561
562 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
563 err |= __put_user(regs->cp0_status, &sc->sc_status);
564
565#define save_gp_reg(i) { \
566 err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \
567} while(0)
568 __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
569 save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
570 save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
571 save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
572 save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
573 save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
574 save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
575 save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
576 save_gp_reg(31);
577#undef save_gp_reg
578
579 err |= __put_user(regs->hi, &sc->sc_mdhi);
580 err |= __put_user(regs->lo, &sc->sc_mdlo);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000581 if (cpu_has_dsp) {
Ralf Baechlec4fa6342005-12-07 17:50:48 +0000582 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
Ralf Baechlee50c0a82005-05-31 11:49:19 +0000583 err |= __put_user(mfhi1(), &sc->sc_hi1);
584 err |= __put_user(mflo1(), &sc->sc_lo1);
585 err |= __put_user(mfhi2(), &sc->sc_hi2);
586 err |= __put_user(mflo2(), &sc->sc_lo2);
587 err |= __put_user(mfhi3(), &sc->sc_hi3);
588 err |= __put_user(mflo3(), &sc->sc_lo3);
589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 err |= __put_user(!!used_math(), &sc->sc_used_math);
592
593 if (!used_math())
594 goto out;
595
Ralf Baechle42a3b4f2005-09-03 15:56:17 -0700596 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 * Save FPU state to signal context. Signal handler will "inherit"
598 * current FPU state.
599 */
600 preempt_disable();
601
602 if (!is_fpu_owner()) {
603 own_fpu();
604 restore_fp(current);
605 }
606 err |= save_fp_context32(sc);
607
608 preempt_enable();
609
610out:
611 return err;
612}
613
614/*
615 * Determine which stack to use..
616 */
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900617static inline void __user *get_sigframe(struct k_sigaction *ka,
618 struct pt_regs *regs,
619 size_t frame_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620{
621 unsigned long sp;
622
623 /* Default to using normal stack */
624 sp = regs->regs[29];
625
626 /*
627 * FPU emulator may have it's own trampoline active just
628 * above the user stack, 16-bytes before the next lowest
629 * 16 byte boundary. Try to avoid trashing it.
630 */
631 sp -= 32;
632
633 /* This is the X/Open sanctioned signal stack switching. */
634 if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
635 sp = current->sas_ss_sp + current->sas_ss_size;
636
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900637 return (void __user *)((sp - frame_size) & ALMASK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638}
639
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900640int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
641 int signr, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900643 struct sigframe __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 int err = 0;
645
646 frame = get_sigframe(ka, regs, sizeof(*frame));
647 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
648 goto give_sigsegv;
649
650 /*
651 * Set up the return code ...
652 *
653 * li v0, __NR_O32_sigreturn
654 * syscall
655 */
656 err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0);
657 err |= __put_user(0x0000000c , frame->sf_code + 1);
658 flush_cache_sigtramp((unsigned long) frame->sf_code);
659
660 err |= setup_sigcontext32(regs, &frame->sf_sc);
661 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
662 if (err)
663 goto give_sigsegv;
664
665 /*
666 * Arguments to signal handler:
667 *
668 * a0 = signal number
669 * a1 = 0 (should be cause)
670 * a2 = pointer to struct sigcontext
671 *
672 * $25 and c0_epc point to the signal handler, $29 points to the
673 * struct sigframe.
674 */
675 regs->regs[ 4] = signr;
676 regs->regs[ 5] = 0;
677 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
678 regs->regs[29] = (unsigned long) frame;
679 regs->regs[31] = (unsigned long) frame->sf_code;
680 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
681
682#if DEBUG_SIG
683 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
684 current->comm, current->pid,
685 frame, regs->cp0_epc, frame->sf_code);
686#endif
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000687 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
689give_sigsegv:
690 force_sigsegv(signr, current);
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000691 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692}
693
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900694int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
695 int signr, sigset_t *set, siginfo_t *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900697 struct rt_sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 int err = 0;
699 s32 sp;
700
701 frame = get_sigframe(ka, regs, sizeof(*frame));
702 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
703 goto give_sigsegv;
704
705 /* Set up to return from userspace. If provided, use a stub already
706 in userspace. */
707 /*
708 * Set up the return code ...
709 *
710 * li v0, __NR_O32_rt_sigreturn
711 * syscall
712 */
713 err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0);
714 err |= __put_user(0x0000000c , frame->rs_code + 1);
715 flush_cache_sigtramp((unsigned long) frame->rs_code);
716
717 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
718 err |= copy_siginfo_to_user32(&frame->rs_info, info);
719
720 /* Create the ucontext. */
721 err |= __put_user(0, &frame->rs_uc.uc_flags);
722 err |= __put_user(0, &frame->rs_uc.uc_link);
723 sp = (int) (long) current->sas_ss_sp;
724 err |= __put_user(sp,
725 &frame->rs_uc.uc_stack.ss_sp);
726 err |= __put_user(sas_ss_flags(regs->regs[29]),
727 &frame->rs_uc.uc_stack.ss_flags);
728 err |= __put_user(current->sas_ss_size,
729 &frame->rs_uc.uc_stack.ss_size);
730 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
731 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
732
733 if (err)
734 goto give_sigsegv;
735
736 /*
737 * Arguments to signal handler:
738 *
739 * a0 = signal number
740 * a1 = 0 (should be cause)
741 * a2 = pointer to ucontext
742 *
743 * $25 and c0_epc point to the signal handler, $29 points to
744 * the struct rt_sigframe32.
745 */
746 regs->regs[ 4] = signr;
747 regs->regs[ 5] = (unsigned long) &frame->rs_info;
748 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
749 regs->regs[29] = (unsigned long) frame;
750 regs->regs[31] = (unsigned long) frame->rs_code;
751 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
752
753#if DEBUG_SIG
754 printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
755 current->comm, current->pid,
756 frame, regs->cp0_epc, frame->rs_code);
757#endif
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000758 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
760give_sigsegv:
761 force_sigsegv(signr, current);
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000762 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763}
764
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000765static inline int handle_signal(unsigned long sig, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
767{
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000768 int ret;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 switch (regs->regs[0]) {
771 case ERESTART_RESTARTBLOCK:
772 case ERESTARTNOHAND:
773 regs->regs[2] = EINTR;
774 break;
775 case ERESTARTSYS:
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000776 if (!(ka->sa.sa_flags & SA_RESTART)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 regs->regs[2] = EINTR;
778 break;
779 }
780 /* fallthrough */
781 case ERESTARTNOINTR: /* Userland will reload $v0. */
782 regs->regs[7] = regs->regs[26];
783 regs->cp0_epc -= 8;
784 }
785
786 regs->regs[0] = 0; /* Don't deal with this again. */
787
788 if (ka->sa.sa_flags & SA_SIGINFO)
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000789 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 else
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000791 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Steven Rostedt69be8f12005-08-29 11:44:09 -0400793 spin_lock_irq(&current->sighand->siglock);
794 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
795 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400797 recalc_sigpending();
798 spin_unlock_irq(&current->sighand->siglock);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000799
800 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801}
802
Martin Michlmayrdda73d02006-02-18 15:21:30 +0000803void do_signal32(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804{
805 struct k_sigaction ka;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000806 sigset_t *oldset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 siginfo_t info;
808 int signr;
809
810 /*
811 * We want the common case to go fast, which is why we may in certain
812 * cases get here from kernel mode. Just return without doing anything
813 * if so.
814 */
815 if (!user_mode(regs))
Martin Michlmayrdda73d02006-02-18 15:21:30 +0000816 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Nigel Cunningham0e6c1f52005-07-27 11:43:34 -0700818 if (try_to_freeze())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 goto no_signal;
820
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000821 if (test_thread_flag(TIF_RESTORE_SIGMASK))
822 oldset = &current->saved_sigmask;
823 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 oldset = &current->blocked;
825
826 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000827 if (signr > 0) {
828 /* Whee! Actually deliver the signal. */
829 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
830 /*
831 * A signal was successfully delivered; the saved
832 * sigmask will have been stored in the signal frame,
833 * and will be restored by sigreturn, so we can simply
834 * clear the TIF_RESTORE_SIGMASK flag.
835 */
836 if (test_thread_flag(TIF_RESTORE_SIGMASK))
837 clear_thread_flag(TIF_RESTORE_SIGMASK);
838 }
839 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
841no_signal:
842 /*
843 * Who's code doesn't conform to the restartable syscall convention
844 * dies here!!! The li instruction, a single machine instruction,
845 * must directly be followed by the syscall instruction.
846 */
847 if (regs->regs[0]) {
848 if (regs->regs[2] == ERESTARTNOHAND ||
849 regs->regs[2] == ERESTARTSYS ||
850 regs->regs[2] == ERESTARTNOINTR) {
851 regs->regs[7] = regs->regs[26];
852 regs->cp0_epc -= 8;
853 }
854 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
855 regs->regs[2] = __NR_O32_restart_syscall;
856 regs->regs[7] = regs->regs[26];
857 regs->cp0_epc -= 4;
858 }
859 }
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000860
861 /*
862 * If there's no signal to deliver, we just put the saved sigmask
863 * back
864 */
865 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
866 clear_thread_flag(TIF_RESTORE_SIGMASK);
867 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869}
870
871asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900872 struct sigaction32 __user *oact,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 unsigned int sigsetsize)
874{
875 struct k_sigaction new_sa, old_sa;
876 int ret = -EINVAL;
877
878 /* XXX: Don't preclude handling different sized sigset_t's. */
879 if (sigsetsize != sizeof(sigset_t))
880 goto out;
881
882 if (act) {
Ralf Baechle77c728c2005-03-04 19:36:51 +0000883 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 int err = 0;
885
886 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
887 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000888 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900889 new_sa.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
891 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
892 if (err)
893 return -EFAULT;
894 }
895
896 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
897
898 if (!ret && oact) {
899 int err = 0;
900
901 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
902 return -EFAULT;
903
904 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
905 &oact->sa_handler);
906 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
907 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
908 if (err)
909 return -EFAULT;
910 }
911out:
912 return ret;
913}
914
915asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900916 compat_sigset_t __user *oset, unsigned int sigsetsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917{
918 sigset_t old_set, new_set;
919 int ret;
920 mm_segment_t old_fs = get_fs();
921
922 if (set && get_sigset(&new_set, set))
923 return -EFAULT;
924
925 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900926 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
927 oset ? (sigset_t __user *)&old_set : NULL,
928 sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 set_fs (old_fs);
930
931 if (!ret && oset && put_sigset(&old_set, oset))
932 return -EFAULT;
933
934 return ret;
935}
936
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900937asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 unsigned int sigsetsize)
939{
940 int ret;
941 sigset_t set;
942 mm_segment_t old_fs = get_fs();
943
944 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900945 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 set_fs (old_fs);
947
948 if (!ret && put_sigset(&set, uset))
949 return -EFAULT;
950
951 return ret;
952}
953
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900954asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955{
956 siginfo_t info;
957 int ret;
958 mm_segment_t old_fs = get_fs();
959
960 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
961 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
962 return -EFAULT;
963 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900964 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 set_fs (old_fs);
966 return ret;
967}
Ralf Baechle54f2da72005-02-16 21:21:29 +0000968
969asmlinkage long
970sys32_waitid(int which, compat_pid_t pid,
971 compat_siginfo_t __user *uinfo, int options,
972 struct compat_rusage __user *uru)
973{
974 siginfo_t info;
975 struct rusage ru;
976 long ret;
977 mm_segment_t old_fs = get_fs();
978
979 info.si_signo = 0;
980 set_fs (KERNEL_DS);
981 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
982 uru ? (struct rusage __user *) &ru : NULL);
983 set_fs (old_fs);
984
985 if (ret < 0 || info.si_signo == 0)
986 return ret;
987
988 if (uru && (ret = put_compat_rusage(&ru, uru)))
989 return ret;
990
991 BUG_ON(info.si_code & __SI_MASK);
992 info.si_code |= __SI_CHLD;
993 return copy_siginfo_to_user32(uinfo, &info);
994}