allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / mips / kernel / signal32.c
blob563e9b1e4ea55b58808becf6d4aceb7369ac0e2f
1 /*
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.
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 */
10 #include <linux/cache.h>
11 #include <linux/compat.h>
12 #include <linux/sched.h>
13 #include <linux/mm.h>
14 #include <linux/smp.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 #include <linux/uaccess.h>
26 #include <asm/abi.h>
27 #include <asm/asm.h>
28 #include <asm/compat-signal.h>
29 #include <linux/bitops.h>
30 #include <asm/cacheflush.h>
31 #include <asm/sim.h>
32 #include <asm/ucontext.h>
33 #include <asm/system.h>
34 #include <asm/fpu.h>
35 #include <asm/war.h>
36 #include <asm/vdso.h>
38 #include "signal-common.h"
41 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
43 #define __NR_O32_restart_syscall 4253
45 /* 32-bit compatibility types */
47 typedef unsigned int __sighandler32_t;
48 typedef void (*vfptr_t)(void);
50 struct sigaction32 {
51 unsigned int sa_flags;
52 __sighandler32_t sa_handler;
53 compat_sigset_t sa_mask;
56 /* IRIX compatible stack_t */
57 typedef struct sigaltstack32 {
58 s32 ss_sp;
59 compat_size_t ss_size;
60 int ss_flags;
61 } stack32_t;
63 struct ucontext32 {
64 u32 uc_flags;
65 s32 uc_link;
66 stack32_t uc_stack;
67 struct sigcontext32 uc_mcontext;
68 compat_sigset_t uc_sigmask; /* mask last for extensibility */
71 struct sigframe32 {
72 u32 sf_ass[4]; /* argument save space for o32 */
73 u32 sf_pad[2]; /* Was: signal trampoline */
74 struct sigcontext32 sf_sc;
75 compat_sigset_t sf_mask;
78 struct rt_sigframe32 {
79 u32 rs_ass[4]; /* argument save space for o32 */
80 u32 rs_pad[2]; /* Was: signal trampoline */
81 compat_siginfo_t rs_info;
82 struct ucontext32 rs_uc;
86 * sigcontext handlers
88 static int protected_save_fp_context32(struct sigcontext32 __user *sc)
90 int err;
91 while (1) {
92 lock_fpu_owner();
93 own_fpu_inatomic(1);
94 err = save_fp_context32(sc); /* this might fail */
95 unlock_fpu_owner();
96 if (likely(!err))
97 break;
98 /* touch the sigcontext and try again */
99 err = __put_user(0, &sc->sc_fpregs[0]) |
100 __put_user(0, &sc->sc_fpregs[31]) |
101 __put_user(0, &sc->sc_fpc_csr);
102 if (err)
103 break; /* really bad sigcontext */
105 return err;
108 static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
110 int err, tmp __maybe_unused;
111 while (1) {
112 lock_fpu_owner();
113 own_fpu_inatomic(0);
114 err = restore_fp_context32(sc); /* this might fail */
115 unlock_fpu_owner();
116 if (likely(!err))
117 break;
118 /* touch the sigcontext and try again */
119 err = __get_user(tmp, &sc->sc_fpregs[0]) |
120 __get_user(tmp, &sc->sc_fpregs[31]) |
121 __get_user(tmp, &sc->sc_fpc_csr);
122 if (err)
123 break; /* really bad sigcontext */
125 return err;
128 static int setup_sigcontext32(struct pt_regs *regs,
129 struct sigcontext32 __user *sc)
131 int err = 0;
132 int i;
133 u32 used_math;
135 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
137 err |= __put_user(0, &sc->sc_regs[0]);
138 for (i = 1; i < 32; i++)
139 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
141 err |= __put_user(regs->hi, &sc->sc_mdhi);
142 err |= __put_user(regs->lo, &sc->sc_mdlo);
143 if (cpu_has_dsp) {
144 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
145 err |= __put_user(mfhi1(), &sc->sc_hi1);
146 err |= __put_user(mflo1(), &sc->sc_lo1);
147 err |= __put_user(mfhi2(), &sc->sc_hi2);
148 err |= __put_user(mflo2(), &sc->sc_lo2);
149 err |= __put_user(mfhi3(), &sc->sc_hi3);
150 err |= __put_user(mflo3(), &sc->sc_lo3);
153 used_math = !!used_math();
154 err |= __put_user(used_math, &sc->sc_used_math);
156 if (used_math) {
158 * Save FPU state to signal context. Signal handler
159 * will "inherit" current FPU state.
161 err |= protected_save_fp_context32(sc);
163 return err;
166 static int
167 check_and_restore_fp_context32(struct sigcontext32 __user *sc)
169 int err, sig;
171 err = sig = fpcsr_pending(&sc->sc_fpc_csr);
172 if (err > 0)
173 err = 0;
174 err |= protected_restore_fp_context32(sc);
175 return err ?: sig;
178 static int restore_sigcontext32(struct pt_regs *regs,
179 struct sigcontext32 __user *sc)
181 u32 used_math;
182 int err = 0;
183 s32 treg;
184 int i;
186 /* Always make any pending restarted system calls return -EINTR */
187 current_thread_info()->restart_block.fn = do_no_restart_syscall;
189 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
190 err |= __get_user(regs->hi, &sc->sc_mdhi);
191 err |= __get_user(regs->lo, &sc->sc_mdlo);
192 if (cpu_has_dsp) {
193 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
194 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
195 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
196 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
197 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
198 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
199 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
202 for (i = 1; i < 32; i++)
203 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
205 err |= __get_user(used_math, &sc->sc_used_math);
206 conditional_used_math(used_math);
208 if (used_math) {
209 /* restore fpu context if we have used it before */
210 if (!err)
211 err = check_and_restore_fp_context32(sc);
212 } else {
213 /* signal handler may have used FPU. Give it up. */
214 lose_fpu(0);
217 return err;
223 extern void __put_sigset_unknown_nsig(void);
224 extern void __get_sigset_unknown_nsig(void);
226 static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
228 int err = 0;
230 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
231 return -EFAULT;
233 switch (_NSIG_WORDS) {
234 default:
235 __put_sigset_unknown_nsig();
236 case 2:
237 err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
238 err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
239 case 1:
240 err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
241 err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
244 return err;
247 static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
249 int err = 0;
250 unsigned long sig[4];
252 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
253 return -EFAULT;
255 switch (_NSIG_WORDS) {
256 default:
257 __get_sigset_unknown_nsig();
258 case 2:
259 err |= __get_user (sig[3], &ubuf->sig[3]);
260 err |= __get_user (sig[2], &ubuf->sig[2]);
261 kbuf->sig[1] = sig[2] | (sig[3] << 32);
262 case 1:
263 err |= __get_user (sig[1], &ubuf->sig[1]);
264 err |= __get_user (sig[0], &ubuf->sig[0]);
265 kbuf->sig[0] = sig[0] | (sig[1] << 32);
268 return err;
272 * Atomically swap in the new signal mask, and wait for a signal.
275 asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
277 compat_sigset_t __user *uset;
278 sigset_t newset;
280 uset = (compat_sigset_t __user *) regs.regs[4];
281 if (get_sigset(&newset, uset))
282 return -EFAULT;
283 sigdelsetmask(&newset, ~_BLOCKABLE);
285 spin_lock_irq(&current->sighand->siglock);
286 current->saved_sigmask = current->blocked;
287 current->blocked = newset;
288 recalc_sigpending();
289 spin_unlock_irq(&current->sighand->siglock);
291 current->state = TASK_INTERRUPTIBLE;
292 schedule();
293 set_thread_flag(TIF_RESTORE_SIGMASK);
294 return -ERESTARTNOHAND;
297 asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
299 compat_sigset_t __user *uset;
300 sigset_t newset;
301 size_t sigsetsize;
303 /* XXX Don't preclude handling different sized sigset_t's. */
304 sigsetsize = regs.regs[5];
305 if (sigsetsize != sizeof(compat_sigset_t))
306 return -EINVAL;
308 uset = (compat_sigset_t __user *) regs.regs[4];
309 if (get_sigset(&newset, uset))
310 return -EFAULT;
311 sigdelsetmask(&newset, ~_BLOCKABLE);
313 spin_lock_irq(&current->sighand->siglock);
314 current->saved_sigmask = current->blocked;
315 current->blocked = newset;
316 recalc_sigpending();
317 spin_unlock_irq(&current->sighand->siglock);
319 current->state = TASK_INTERRUPTIBLE;
320 schedule();
321 set_thread_flag(TIF_RESTORE_SIGMASK);
322 return -ERESTARTNOHAND;
325 asmlinkage int sys32_sigaction(int sig, const struct sigaction32 __user *act,
326 struct sigaction32 __user *oact)
328 struct k_sigaction new_ka, old_ka;
329 int ret;
330 int err = 0;
332 if (act) {
333 old_sigset_t mask;
334 s32 handler;
336 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
337 return -EFAULT;
338 err |= __get_user(handler, &act->sa_handler);
339 new_ka.sa.sa_handler = (void __user *)(s64)handler;
340 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
341 err |= __get_user(mask, &act->sa_mask.sig[0]);
342 if (err)
343 return -EFAULT;
345 siginitset(&new_ka.sa.sa_mask, mask);
348 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
350 if (!ret && oact) {
351 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
352 return -EFAULT;
353 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
354 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
355 &oact->sa_handler);
356 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
357 err |= __put_user(0, &oact->sa_mask.sig[1]);
358 err |= __put_user(0, &oact->sa_mask.sig[2]);
359 err |= __put_user(0, &oact->sa_mask.sig[3]);
360 if (err)
361 return -EFAULT;
364 return ret;
367 asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
369 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
370 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
371 unsigned long usp = regs.regs[29];
372 stack_t kss, koss;
373 int ret, err = 0;
374 mm_segment_t old_fs = get_fs();
375 s32 sp;
377 if (uss) {
378 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
379 return -EFAULT;
380 err |= __get_user(sp, &uss->ss_sp);
381 kss.ss_sp = (void __user *) (long) sp;
382 err |= __get_user(kss.ss_size, &uss->ss_size);
383 err |= __get_user(kss.ss_flags, &uss->ss_flags);
384 if (err)
385 return -EFAULT;
388 set_fs (KERNEL_DS);
389 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
390 uoss ? (stack_t __user *)&koss : NULL, usp);
391 set_fs (old_fs);
393 if (!ret && uoss) {
394 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
395 return -EFAULT;
396 sp = (int) (unsigned long) koss.ss_sp;
397 err |= __put_user(sp, &uoss->ss_sp);
398 err |= __put_user(koss.ss_size, &uoss->ss_size);
399 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
400 if (err)
401 return -EFAULT;
403 return ret;
406 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
408 int err;
410 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
411 return -EFAULT;
413 /* If you change siginfo_t structure, please be sure
414 this code is fixed accordingly.
415 It should never copy any pad contained in the structure
416 to avoid security leaks, but must copy the generic
417 3 ints plus the relevant union member.
418 This routine must convert siginfo from 64bit to 32bit as well
419 at the same time. */
420 err = __put_user(from->si_signo, &to->si_signo);
421 err |= __put_user(from->si_errno, &to->si_errno);
422 err |= __put_user((short)from->si_code, &to->si_code);
423 if (from->si_code < 0)
424 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
425 else {
426 switch (from->si_code >> 16) {
427 case __SI_TIMER >> 16:
428 err |= __put_user(from->si_tid, &to->si_tid);
429 err |= __put_user(from->si_overrun, &to->si_overrun);
430 err |= __put_user(from->si_int, &to->si_int);
431 break;
432 case __SI_CHLD >> 16:
433 err |= __put_user(from->si_utime, &to->si_utime);
434 err |= __put_user(from->si_stime, &to->si_stime);
435 err |= __put_user(from->si_status, &to->si_status);
436 default:
437 err |= __put_user(from->si_pid, &to->si_pid);
438 err |= __put_user(from->si_uid, &to->si_uid);
439 break;
440 case __SI_FAULT >> 16:
441 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
442 break;
443 case __SI_POLL >> 16:
444 err |= __put_user(from->si_band, &to->si_band);
445 err |= __put_user(from->si_fd, &to->si_fd);
446 break;
447 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
448 case __SI_MESGQ >> 16:
449 err |= __put_user(from->si_pid, &to->si_pid);
450 err |= __put_user(from->si_uid, &to->si_uid);
451 err |= __put_user(from->si_int, &to->si_int);
452 break;
455 return err;
458 asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
460 struct sigframe32 __user *frame;
461 sigset_t blocked;
462 int sig;
464 frame = (struct sigframe32 __user *) regs.regs[29];
465 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
466 goto badframe;
467 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
468 goto badframe;
470 sigdelsetmask(&blocked, ~_BLOCKABLE);
471 spin_lock_irq(&current->sighand->siglock);
472 current->blocked = blocked;
473 recalc_sigpending();
474 spin_unlock_irq(&current->sighand->siglock);
476 sig = restore_sigcontext32(&regs, &frame->sf_sc);
477 if (sig < 0)
478 goto badframe;
479 else if (sig)
480 force_sig(sig, current);
483 * Don't let your children do this ...
485 __asm__ __volatile__(
486 "move\t$29, %0\n\t"
487 "j\tsyscall_exit"
488 :/* no outputs */
489 :"r" (&regs));
490 /* Unreached */
492 badframe:
493 force_sig(SIGSEGV, current);
496 asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
498 struct rt_sigframe32 __user *frame;
499 mm_segment_t old_fs;
500 sigset_t set;
501 stack_t st;
502 s32 sp;
503 int sig;
505 frame = (struct rt_sigframe32 __user *) regs.regs[29];
506 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
507 goto badframe;
508 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
509 goto badframe;
511 sigdelsetmask(&set, ~_BLOCKABLE);
512 spin_lock_irq(&current->sighand->siglock);
513 current->blocked = set;
514 recalc_sigpending();
515 spin_unlock_irq(&current->sighand->siglock);
517 sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
518 if (sig < 0)
519 goto badframe;
520 else if (sig)
521 force_sig(sig, current);
523 /* The ucontext contains a stack32_t, so we must convert! */
524 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
525 goto badframe;
526 st.ss_sp = (void __user *)(long) sp;
527 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
528 goto badframe;
529 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
530 goto badframe;
532 /* It is more difficult to avoid calling this function than to
533 call it and ignore errors. */
534 old_fs = get_fs();
535 set_fs (KERNEL_DS);
536 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
537 set_fs (old_fs);
540 * Don't let your children do this ...
542 __asm__ __volatile__(
543 "move\t$29, %0\n\t"
544 "j\tsyscall_exit"
545 :/* no outputs */
546 :"r" (&regs));
547 /* Unreached */
549 badframe:
550 force_sig(SIGSEGV, current);
553 static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
554 struct pt_regs *regs, int signr, sigset_t *set)
556 struct sigframe32 __user *frame;
557 int err = 0;
559 frame = get_sigframe(ka, regs, sizeof(*frame));
560 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
561 goto give_sigsegv;
563 err |= setup_sigcontext32(regs, &frame->sf_sc);
564 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
566 if (err)
567 goto give_sigsegv;
570 * Arguments to signal handler:
572 * a0 = signal number
573 * a1 = 0 (should be cause)
574 * a2 = pointer to struct sigcontext
576 * $25 and c0_epc point to the signal handler, $29 points to the
577 * struct sigframe.
579 regs->regs[ 4] = signr;
580 regs->regs[ 5] = 0;
581 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
582 regs->regs[29] = (unsigned long) frame;
583 regs->regs[31] = (unsigned long) sig_return;
584 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
586 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
587 current->comm, current->pid,
588 frame, regs->cp0_epc, regs->regs[31]);
590 return 0;
592 give_sigsegv:
593 force_sigsegv(signr, current);
594 return -EFAULT;
597 static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
598 struct pt_regs *regs, int signr, sigset_t *set,
599 siginfo_t *info)
601 struct rt_sigframe32 __user *frame;
602 int err = 0;
603 s32 sp;
605 frame = get_sigframe(ka, regs, sizeof(*frame));
606 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
607 goto give_sigsegv;
609 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
610 err |= copy_siginfo_to_user32(&frame->rs_info, info);
612 /* Create the ucontext. */
613 err |= __put_user(0, &frame->rs_uc.uc_flags);
614 err |= __put_user(0, &frame->rs_uc.uc_link);
615 sp = (int) (long) current->sas_ss_sp;
616 err |= __put_user(sp,
617 &frame->rs_uc.uc_stack.ss_sp);
618 err |= __put_user(sas_ss_flags(regs->regs[29]),
619 &frame->rs_uc.uc_stack.ss_flags);
620 err |= __put_user(current->sas_ss_size,
621 &frame->rs_uc.uc_stack.ss_size);
622 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
623 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
625 if (err)
626 goto give_sigsegv;
629 * Arguments to signal handler:
631 * a0 = signal number
632 * a1 = 0 (should be cause)
633 * a2 = pointer to ucontext
635 * $25 and c0_epc point to the signal handler, $29 points to
636 * the struct rt_sigframe32.
638 regs->regs[ 4] = signr;
639 regs->regs[ 5] = (unsigned long) &frame->rs_info;
640 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
641 regs->regs[29] = (unsigned long) frame;
642 regs->regs[31] = (unsigned long) sig_return;
643 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
645 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
646 current->comm, current->pid,
647 frame, regs->cp0_epc, regs->regs[31]);
649 return 0;
651 give_sigsegv:
652 force_sigsegv(signr, current);
653 return -EFAULT;
657 * o32 compatibility on 64-bit kernels, without DSP ASE
659 struct mips_abi mips_abi_32 = {
660 .setup_frame = setup_frame_32,
661 .signal_return_offset =
662 offsetof(struct mips_vdso, o32_signal_trampoline),
663 .setup_rt_frame = setup_rt_frame_32,
664 .rt_signal_return_offset =
665 offsetof(struct mips_vdso, o32_rt_signal_trampoline),
666 .restart = __NR_O32_restart_syscall
669 asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
670 struct sigaction32 __user *oact,
671 unsigned int sigsetsize)
673 struct k_sigaction new_sa, old_sa;
674 int ret = -EINVAL;
676 /* XXX: Don't preclude handling different sized sigset_t's. */
677 if (sigsetsize != sizeof(sigset_t))
678 goto out;
680 if (act) {
681 s32 handler;
682 int err = 0;
684 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
685 return -EFAULT;
686 err |= __get_user(handler, &act->sa_handler);
687 new_sa.sa.sa_handler = (void __user *)(s64)handler;
688 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
689 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
690 if (err)
691 return -EFAULT;
694 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
696 if (!ret && oact) {
697 int err = 0;
699 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
700 return -EFAULT;
702 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
703 &oact->sa_handler);
704 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
705 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
706 if (err)
707 return -EFAULT;
709 out:
710 return ret;
713 asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
714 compat_sigset_t __user *oset, unsigned int sigsetsize)
716 sigset_t old_set, new_set;
717 int ret;
718 mm_segment_t old_fs = get_fs();
720 if (set && get_sigset(&new_set, set))
721 return -EFAULT;
723 set_fs (KERNEL_DS);
724 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
725 oset ? (sigset_t __user *)&old_set : NULL,
726 sigsetsize);
727 set_fs (old_fs);
729 if (!ret && oset && put_sigset(&old_set, oset))
730 return -EFAULT;
732 return ret;
735 asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset,
736 unsigned int sigsetsize)
738 int ret;
739 sigset_t set;
740 mm_segment_t old_fs = get_fs();
742 set_fs (KERNEL_DS);
743 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
744 set_fs (old_fs);
746 if (!ret && put_sigset(&set, uset))
747 return -EFAULT;
749 return ret;
752 asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
754 siginfo_t info;
755 int ret;
756 mm_segment_t old_fs = get_fs();
758 if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
759 copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
760 return -EFAULT;
761 set_fs (KERNEL_DS);
762 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
763 set_fs (old_fs);
764 return ret;
767 asmlinkage long
768 sys32_waitid(int which, compat_pid_t pid,
769 compat_siginfo_t __user *uinfo, int options,
770 struct compat_rusage __user *uru)
772 siginfo_t info;
773 struct rusage ru;
774 long ret;
775 mm_segment_t old_fs = get_fs();
777 info.si_signo = 0;
778 set_fs (KERNEL_DS);
779 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
780 uru ? (struct rusage __user *) &ru : NULL);
781 set_fs (old_fs);
783 if (ret < 0 || info.si_signo == 0)
784 return ret;
786 if (uru && (ret = put_compat_rusage(&ru, uru)))
787 return ret;
789 BUG_ON(info.si_code & __SI_MASK);
790 info.si_code |= __SI_CHLD;
791 return copy_siginfo_to_user32(uinfo, &info);