blob: 1b9262d3fd2313884958c87aadbd844e877e25e1 [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 Baechlee50c0a8f2005-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-Huu36a1f2c2007-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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107#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
Ralf Baechledd02f062007-02-13 00:50:57 +0000142/*
143 * Horribly complicated - with the bloody RM9000 workarounds enabled
144 * the signal trampolines is moving to the end of the structure so we can
145 * increase the alignment without breaking software compatibility.
146 */
Franck Bui-Huuc0b9bae2007-02-05 15:24:21 +0100147#if ICACHE_REFILLS_WORKAROUND_WAR == 0
148
Ralf Baechledd02f062007-02-13 00:50:57 +0000149struct sigframe32 {
150 u32 sf_ass[4]; /* argument save space for o32 */
151 u32 sf_code[2]; /* signal trampoline */
152 struct sigcontext32 sf_sc;
153 sigset_t sf_mask;
154};
155
Franck Bui-Huuc0b9bae2007-02-05 15:24:21 +0100156struct rt_sigframe32 {
157 u32 rs_ass[4]; /* argument save space for o32 */
158 u32 rs_code[2]; /* signal trampoline */
159 compat_siginfo_t rs_info;
160 struct ucontext32 rs_uc;
161};
162
163#else /* ICACHE_REFILLS_WORKAROUND_WAR */
164
Ralf Baechledd02f062007-02-13 00:50:57 +0000165struct sigframe32 {
166 u32 sf_ass[4]; /* argument save space for o32 */
167 u32 sf_pad[2];
168 struct sigcontext32 sf_sc; /* hw context */
169 sigset_t sf_mask;
170 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
171};
172
Franck Bui-Huuc0b9bae2007-02-05 15:24:21 +0100173struct rt_sigframe32 {
174 u32 rs_ass[4]; /* argument save space for o32 */
175 u32 rs_pad[2];
176 compat_siginfo_t rs_info;
177 struct ucontext32 rs_uc;
178 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
179};
180
181#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
182
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +0100183/*
184 * sigcontext handlers
185 */
186static int setup_sigcontext32(struct pt_regs *regs,
187 struct sigcontext32 __user *sc)
188{
189 int err = 0;
190 int i;
191
192 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +0100193
194 err |= __put_user(0, &sc->sc_regs[0]);
195 for (i = 1; i < 32; i++)
196 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
197
198 err |= __put_user(regs->hi, &sc->sc_mdhi);
199 err |= __put_user(regs->lo, &sc->sc_mdlo);
200 if (cpu_has_dsp) {
201 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
202 err |= __put_user(mfhi1(), &sc->sc_hi1);
203 err |= __put_user(mflo1(), &sc->sc_lo1);
204 err |= __put_user(mfhi2(), &sc->sc_hi2);
205 err |= __put_user(mflo2(), &sc->sc_lo2);
206 err |= __put_user(mfhi3(), &sc->sc_hi3);
207 err |= __put_user(mflo3(), &sc->sc_lo3);
208 }
209
210 err |= __put_user(!!used_math(), &sc->sc_used_math);
211
212 if (used_math()) {
213 /*
214 * Save FPU state to signal context. Signal handler
215 * will "inherit" current FPU state.
216 */
217 preempt_disable();
218
219 if (!is_fpu_owner()) {
220 own_fpu();
221 restore_fp(current);
222 }
223 err |= save_fp_context32(sc);
224
225 preempt_enable();
226 }
227 return err;
228}
229
230static int restore_sigcontext32(struct pt_regs *regs,
231 struct sigcontext32 __user *sc)
232{
233 u32 used_math;
234 int err = 0;
235 s32 treg;
236 int i;
237
238 /* Always make any pending restarted system calls return -EINTR */
239 current_thread_info()->restart_block.fn = do_no_restart_syscall;
240
241 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
242 err |= __get_user(regs->hi, &sc->sc_mdhi);
243 err |= __get_user(regs->lo, &sc->sc_mdlo);
244 if (cpu_has_dsp) {
245 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
246 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
247 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
248 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
249 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
250 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
251 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
252 }
253
254 for (i = 1; i < 32; i++)
255 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
256
257 err |= __get_user(used_math, &sc->sc_used_math);
258 conditional_used_math(used_math);
259
260 preempt_disable();
261
262 if (used_math()) {
263 /* restore fpu context if we have used it before */
264 own_fpu();
265 err |= restore_fp_context32(sc);
266 } else {
267 /* signal handler may have used FPU. Give it up. */
268 lose_fpu();
269 }
270
271 preempt_enable();
272
273 return err;
274}
275
276/*
277 *
278 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279extern void __put_sigset_unknown_nsig(void);
280extern void __get_sigset_unknown_nsig(void);
281
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900282static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283{
284 int err = 0;
285
286 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
287 return -EFAULT;
288
289 switch (_NSIG_WORDS) {
290 default:
291 __put_sigset_unknown_nsig();
292 case 2:
293 err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
294 err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
295 case 1:
296 err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
297 err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
298 }
299
300 return err;
301}
302
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900303static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304{
305 int err = 0;
306 unsigned long sig[4];
307
308 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
309 return -EFAULT;
310
311 switch (_NSIG_WORDS) {
312 default:
313 __get_sigset_unknown_nsig();
314 case 2:
315 err |= __get_user (sig[3], &ubuf->sig[3]);
316 err |= __get_user (sig[2], &ubuf->sig[2]);
317 kbuf->sig[1] = sig[2] | (sig[3] << 32);
318 case 1:
319 err |= __get_user (sig[1], &ubuf->sig[1]);
320 err |= __get_user (sig[0], &ubuf->sig[0]);
321 kbuf->sig[0] = sig[0] | (sig[1] << 32);
322 }
323
324 return err;
325}
326
327/*
328 * Atomically swap in the new signal mask, and wait for a signal.
329 */
330
Franck Bui-Huuf90080a2007-02-05 15:24:27 +0100331asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332{
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900333 compat_sigset_t __user *uset;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000334 sigset_t newset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900336 uset = (compat_sigset_t __user *) regs.regs[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 if (get_sigset(&newset, uset))
338 return -EFAULT;
339 sigdelsetmask(&newset, ~_BLOCKABLE);
340
341 spin_lock_irq(&current->sighand->siglock);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000342 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 current->blocked = newset;
344 recalc_sigpending();
345 spin_unlock_irq(&current->sighand->siglock);
346
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000347 current->state = TASK_INTERRUPTIBLE;
348 schedule();
349 set_thread_flag(TIF_RESTORE_SIGMASK);
350 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351}
352
Franck Bui-Huuf90080a2007-02-05 15:24:27 +0100353asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900355 compat_sigset_t __user *uset;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000356 sigset_t newset;
Ralf Baechle304416d2006-02-18 18:20:47 +0000357 size_t sigsetsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359 /* XXX Don't preclude handling different sized sigset_t's. */
360 sigsetsize = regs.regs[5];
361 if (sigsetsize != sizeof(compat_sigset_t))
362 return -EINVAL;
363
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900364 uset = (compat_sigset_t __user *) regs.regs[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 if (get_sigset(&newset, uset))
366 return -EFAULT;
367 sigdelsetmask(&newset, ~_BLOCKABLE);
368
369 spin_lock_irq(&current->sighand->siglock);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000370 current->saved_sigmask = current->blocked;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 current->blocked = newset;
Martin Michlmayr62549442006-02-18 20:06:32 +0000372 recalc_sigpending();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 spin_unlock_irq(&current->sighand->siglock);
374
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000375 current->state = TASK_INTERRUPTIBLE;
376 schedule();
377 set_thread_flag(TIF_RESTORE_SIGMASK);
378 return -ERESTARTNOHAND;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379}
380
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900381asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
382 struct sigaction32 __user *oact)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
384 struct k_sigaction new_ka, old_ka;
385 int ret;
386 int err = 0;
387
388 if (act) {
389 old_sigset_t mask;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000390 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
392 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
393 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000394 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900395 new_ka.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
397 err |= __get_user(mask, &act->sa_mask.sig[0]);
398 if (err)
399 return -EFAULT;
400
401 siginitset(&new_ka.sa.sa_mask, mask);
402 }
403
404 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
405
406 if (!ret && oact) {
407 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
Martin Michlmayr62549442006-02-18 20:06:32 +0000408 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
410 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
411 &oact->sa_handler);
412 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
Martin Michlmayr62549442006-02-18 20:06:32 +0000413 err |= __put_user(0, &oact->sa_mask.sig[1]);
414 err |= __put_user(0, &oact->sa_mask.sig[2]);
415 err |= __put_user(0, &oact->sa_mask.sig[3]);
416 if (err)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return -EFAULT;
418 }
419
420 return ret;
421}
422
423asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
424{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900425 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
426 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 unsigned long usp = regs.regs[29];
428 stack_t kss, koss;
429 int ret, err = 0;
430 mm_segment_t old_fs = get_fs();
431 s32 sp;
432
433 if (uss) {
434 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
435 return -EFAULT;
436 err |= __get_user(sp, &uss->ss_sp);
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900437 kss.ss_sp = (void __user *) (long) sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 err |= __get_user(kss.ss_size, &uss->ss_size);
439 err |= __get_user(kss.ss_flags, &uss->ss_flags);
440 if (err)
441 return -EFAULT;
442 }
443
444 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900445 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
446 uoss ? (stack_t __user *)&koss : NULL, usp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 set_fs (old_fs);
448
449 if (!ret && uoss) {
450 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
451 return -EFAULT;
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900452 sp = (int) (unsigned long) koss.ss_sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 err |= __put_user(sp, &uoss->ss_sp);
454 err |= __put_user(koss.ss_size, &uoss->ss_size);
455 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
456 if (err)
457 return -EFAULT;
458 }
459 return ret;
460}
461
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900462int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
464 int err;
465
466 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
467 return -EFAULT;
468
469 /* If you change siginfo_t structure, please be sure
470 this code is fixed accordingly.
471 It should never copy any pad contained in the structure
472 to avoid security leaks, but must copy the generic
473 3 ints plus the relevant union member.
474 This routine must convert siginfo from 64bit to 32bit as well
475 at the same time. */
476 err = __put_user(from->si_signo, &to->si_signo);
477 err |= __put_user(from->si_errno, &to->si_errno);
478 err |= __put_user((short)from->si_code, &to->si_code);
479 if (from->si_code < 0)
480 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
481 else {
482 switch (from->si_code >> 16) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000483 case __SI_TIMER >> 16:
484 err |= __put_user(from->si_tid, &to->si_tid);
485 err |= __put_user(from->si_overrun, &to->si_overrun);
486 err |= __put_user(from->si_int, &to->si_int);
487 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 case __SI_CHLD >> 16:
489 err |= __put_user(from->si_utime, &to->si_utime);
490 err |= __put_user(from->si_stime, &to->si_stime);
491 err |= __put_user(from->si_status, &to->si_status);
492 default:
493 err |= __put_user(from->si_pid, &to->si_pid);
494 err |= __put_user(from->si_uid, &to->si_uid);
495 break;
496 case __SI_FAULT >> 16:
Atsushi Nemoto5665a0a2006-02-02 01:26:34 +0900497 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 break;
499 case __SI_POLL >> 16:
500 err |= __put_user(from->si_band, &to->si_band);
501 err |= __put_user(from->si_fd, &to->si_fd);
502 break;
503 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
504 case __SI_MESGQ >> 16:
505 err |= __put_user(from->si_pid, &to->si_pid);
506 err |= __put_user(from->si_uid, &to->si_uid);
507 err |= __put_user(from->si_int, &to->si_int);
508 break;
509 }
510 }
511 return err;
512}
513
Franck Bui-Huuf90080a2007-02-05 15:24:27 +0100514asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515{
Ralf Baechledd02f062007-02-13 00:50:57 +0000516 struct sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 sigset_t blocked;
518
Ralf Baechledd02f062007-02-13 00:50:57 +0000519 frame = (struct sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
521 goto badframe;
522 if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
523 goto badframe;
524
525 sigdelsetmask(&blocked, ~_BLOCKABLE);
526 spin_lock_irq(&current->sighand->siglock);
527 current->blocked = blocked;
528 recalc_sigpending();
529 spin_unlock_irq(&current->sighand->siglock);
530
531 if (restore_sigcontext32(&regs, &frame->sf_sc))
532 goto badframe;
533
534 /*
535 * Don't let your children do this ...
536 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 __asm__ __volatile__(
538 "move\t$29, %0\n\t"
539 "j\tsyscall_exit"
540 :/* no outputs */
541 :"r" (&regs));
542 /* Unreached */
543
544badframe:
545 force_sig(SIGSEGV, current);
546}
547
Franck Bui-Huuf90080a2007-02-05 15:24:27 +0100548asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900550 struct rt_sigframe32 __user *frame;
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000551 mm_segment_t old_fs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 sigset_t set;
553 stack_t st;
554 s32 sp;
555
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900556 frame = (struct rt_sigframe32 __user *) regs.regs[29];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
558 goto badframe;
559 if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
560 goto badframe;
561
562 sigdelsetmask(&set, ~_BLOCKABLE);
563 spin_lock_irq(&current->sighand->siglock);
564 current->blocked = set;
565 recalc_sigpending();
566 spin_unlock_irq(&current->sighand->siglock);
567
568 if (restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext))
569 goto badframe;
570
571 /* The ucontext contains a stack32_t, so we must convert! */
572 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
573 goto badframe;
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900574 st.ss_sp = (void __user *)(long) sp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
576 goto badframe;
577 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
578 goto badframe;
579
580 /* It is more difficult to avoid calling this function than to
581 call it and ignore errors. */
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000582 old_fs = get_fs();
583 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900584 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
Ralf Baechle1fcf1cc2005-04-13 18:18:04 +0000585 set_fs (old_fs);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
587 /*
588 * Don't let your children do this ...
589 */
590 __asm__ __volatile__(
591 "move\t$29, %0\n\t"
592 "j\tsyscall_exit"
593 :/* no outputs */
594 :"r" (&regs));
595 /* Unreached */
596
597badframe:
598 force_sig(SIGSEGV, current);
599}
600
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900601int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
602 int signr, sigset_t *set)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603{
Ralf Baechledd02f062007-02-13 00:50:57 +0000604 struct sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 int err = 0;
606
607 frame = get_sigframe(ka, regs, sizeof(*frame));
608 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
609 goto give_sigsegv;
610
Franck Bui-Huu36a1f2c2007-02-05 15:24:22 +0100611 err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613 err |= setup_sigcontext32(regs, &frame->sf_sc);
614 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
615 if (err)
616 goto give_sigsegv;
617
618 /*
619 * Arguments to signal handler:
620 *
621 * a0 = signal number
622 * a1 = 0 (should be cause)
623 * a2 = pointer to struct sigcontext
624 *
625 * $25 and c0_epc point to the signal handler, $29 points to the
626 * struct sigframe.
627 */
628 regs->regs[ 4] = signr;
629 regs->regs[ 5] = 0;
630 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
631 regs->regs[29] = (unsigned long) frame;
632 regs->regs[31] = (unsigned long) frame->sf_code;
633 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
634
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100635 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 current->comm, current->pid,
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100637 frame, regs->cp0_epc, regs->regs[31]);
638
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000639 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641give_sigsegv:
642 force_sigsegv(signr, current);
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000643 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644}
645
Atsushi Nemoto16cd3952005-11-05 23:00:58 +0900646int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
647 int signr, sigset_t *set, siginfo_t *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648{
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900649 struct rt_sigframe32 __user *frame;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 int err = 0;
651 s32 sp;
652
653 frame = get_sigframe(ka, regs, sizeof(*frame));
654 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
655 goto give_sigsegv;
656
Franck Bui-Huu36a1f2c2007-02-05 15:24:22 +0100657 err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
660 err |= copy_siginfo_to_user32(&frame->rs_info, info);
661
662 /* Create the ucontext. */
663 err |= __put_user(0, &frame->rs_uc.uc_flags);
664 err |= __put_user(0, &frame->rs_uc.uc_link);
665 sp = (int) (long) current->sas_ss_sp;
666 err |= __put_user(sp,
667 &frame->rs_uc.uc_stack.ss_sp);
668 err |= __put_user(sas_ss_flags(regs->regs[29]),
669 &frame->rs_uc.uc_stack.ss_flags);
670 err |= __put_user(current->sas_ss_size,
671 &frame->rs_uc.uc_stack.ss_size);
672 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
673 err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
674
675 if (err)
676 goto give_sigsegv;
677
678 /*
679 * Arguments to signal handler:
680 *
681 * a0 = signal number
682 * a1 = 0 (should be cause)
683 * a2 = pointer to ucontext
684 *
685 * $25 and c0_epc point to the signal handler, $29 points to
686 * the struct rt_sigframe32.
687 */
688 regs->regs[ 4] = signr;
689 regs->regs[ 5] = (unsigned long) &frame->rs_info;
690 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
691 regs->regs[29] = (unsigned long) frame;
692 regs->regs[31] = (unsigned long) frame->rs_code;
693 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
694
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100695 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 current->comm, current->pid,
Franck Bui-Huu722bb632007-02-05 15:24:24 +0100697 frame, regs->cp0_epc, regs->regs[31]);
698
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000699 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701give_sigsegv:
702 force_sigsegv(signr, current);
Ralf Baechle7b3e2fc2006-02-08 12:58:41 +0000703 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704}
705
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000706static inline int handle_signal(unsigned long sig, siginfo_t *info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs)
708{
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000709 int ret;
710
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 switch (regs->regs[0]) {
712 case ERESTART_RESTARTBLOCK:
713 case ERESTARTNOHAND:
714 regs->regs[2] = EINTR;
715 break;
716 case ERESTARTSYS:
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000717 if (!(ka->sa.sa_flags & SA_RESTART)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 regs->regs[2] = EINTR;
719 break;
720 }
721 /* fallthrough */
722 case ERESTARTNOINTR: /* Userland will reload $v0. */
723 regs->regs[7] = regs->regs[26];
724 regs->cp0_epc -= 8;
725 }
726
727 regs->regs[0] = 0; /* Don't deal with this again. */
728
729 if (ka->sa.sa_flags & SA_SIGINFO)
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000730 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 else
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000732 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
Steven Rostedt69be8f12005-08-29 11:44:09 -0400734 spin_lock_irq(&current->sighand->siglock);
735 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
736 if (!(ka->sa.sa_flags & SA_NODEFER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 sigaddset(&current->blocked,sig);
Steven Rostedt69be8f12005-08-29 11:44:09 -0400738 recalc_sigpending();
739 spin_unlock_irq(&current->sighand->siglock);
Ralf Baechle129bc8f2005-07-11 20:45:51 +0000740
741 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742}
743
Martin Michlmayrdda73d02006-02-18 15:21:30 +0000744void do_signal32(struct pt_regs *regs)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
746 struct k_sigaction ka;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000747 sigset_t *oldset;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 siginfo_t info;
749 int signr;
750
751 /*
752 * We want the common case to go fast, which is why we may in certain
753 * cases get here from kernel mode. Just return without doing anything
754 * if so.
755 */
756 if (!user_mode(regs))
Martin Michlmayrdda73d02006-02-18 15:21:30 +0000757 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000759 if (test_thread_flag(TIF_RESTORE_SIGMASK))
760 oldset = &current->saved_sigmask;
761 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 oldset = &current->blocked;
763
764 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000765 if (signr > 0) {
766 /* Whee! Actually deliver the signal. */
767 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
768 /*
769 * A signal was successfully delivered; the saved
770 * sigmask will have been stored in the signal frame,
771 * and will be restored by sigreturn, so we can simply
772 * clear the TIF_RESTORE_SIGMASK flag.
773 */
774 if (test_thread_flag(TIF_RESTORE_SIGMASK))
775 clear_thread_flag(TIF_RESTORE_SIGMASK);
776 }
Ralf Baechle45887e12006-08-03 21:54:13 +0100777
778 return;
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 /*
782 * Who's code doesn't conform to the restartable syscall convention
783 * dies here!!! The li instruction, a single machine instruction,
784 * must directly be followed by the syscall instruction.
785 */
786 if (regs->regs[0]) {
787 if (regs->regs[2] == ERESTARTNOHAND ||
788 regs->regs[2] == ERESTARTSYS ||
789 regs->regs[2] == ERESTARTNOINTR) {
790 regs->regs[7] = regs->regs[26];
791 regs->cp0_epc -= 8;
792 }
793 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
794 regs->regs[2] = __NR_O32_restart_syscall;
795 regs->regs[7] = regs->regs[26];
796 regs->cp0_epc -= 4;
797 }
Ralf Baechle13fdd312006-08-08 03:47:01 +0100798 regs->regs[0] = 0; /* Don't deal with this again. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 }
Martin Michlmayr68fa3832006-02-18 14:55:45 +0000800
801 /*
802 * If there's no signal to deliver, we just put the saved sigmask
803 * back
804 */
805 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
806 clear_thread_flag(TIF_RESTORE_SIGMASK);
807 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809}
810
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900811asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900812 struct sigaction32 __user *oact,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 unsigned int sigsetsize)
814{
815 struct k_sigaction new_sa, old_sa;
816 int ret = -EINVAL;
817
818 /* XXX: Don't preclude handling different sized sigset_t's. */
819 if (sigsetsize != sizeof(sigset_t))
820 goto out;
821
822 if (act) {
Ralf Baechle77c728c2005-03-04 19:36:51 +0000823 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 int err = 0;
825
826 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
827 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +0000828 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900829 new_sa.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
831 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
832 if (err)
833 return -EFAULT;
834 }
835
836 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
837
838 if (!ret && oact) {
839 int err = 0;
840
841 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
842 return -EFAULT;
843
844 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
845 &oact->sa_handler);
846 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
847 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
848 if (err)
849 return -EFAULT;
850 }
851out:
852 return ret;
853}
854
Atsushi Nemoto9c6031c2006-02-19 23:46:44 +0900855asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900856 compat_sigset_t __user *oset, unsigned int sigsetsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
858 sigset_t old_set, new_set;
859 int ret;
860 mm_segment_t old_fs = get_fs();
861
862 if (set && get_sigset(&new_set, set))
863 return -EFAULT;
864
865 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900866 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
867 oset ? (sigset_t __user *)&old_set : NULL,
868 sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 set_fs (old_fs);
870
871 if (!ret && oset && put_sigset(&old_set, oset))
872 return -EFAULT;
873
874 return ret;
875}
876
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900877asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 unsigned int sigsetsize)
879{
880 int ret;
881 sigset_t set;
882 mm_segment_t old_fs = get_fs();
883
884 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900885 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 set_fs (old_fs);
887
888 if (!ret && put_sigset(&set, uset))
889 return -EFAULT;
890
891 return ret;
892}
893
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900894asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 siginfo_t info;
897 int ret;
898 mm_segment_t old_fs = get_fs();
899
900 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
901 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
902 return -EFAULT;
903 set_fs (KERNEL_DS);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +0900904 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 set_fs (old_fs);
906 return ret;
907}
Ralf Baechle54f2da72005-02-16 21:21:29 +0000908
909asmlinkage long
910sys32_waitid(int which, compat_pid_t pid,
911 compat_siginfo_t __user *uinfo, int options,
912 struct compat_rusage __user *uru)
913{
914 siginfo_t info;
915 struct rusage ru;
916 long ret;
917 mm_segment_t old_fs = get_fs();
918
919 info.si_signo = 0;
920 set_fs (KERNEL_DS);
921 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
922 uru ? (struct rusage __user *) &ru : NULL);
923 set_fs (old_fs);
924
925 if (ret < 0 || info.si_signo == 0)
926 return ret;
927
928 if (uru && (ret = put_compat_rusage(&ru, uru)))
929 return ret;
930
931 BUG_ON(info.si_code & __SI_MASK);
932 info.si_code |= __SI_CHLD;
933 return copy_siginfo_to_user32(uinfo, &info);
934}