1
2
3
4
5
6
7
8
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/suspend.h>
22#include <linux/compiler.h>
23#include <linux/uaccess.h>
24
25#include <asm/abi.h>
26#include <asm/asm.h>
27#include <asm/compat-signal.h>
28#include <linux/bitops.h>
29#include <asm/cacheflush.h>
30#include <asm/sim.h>
31#include <asm/ucontext.h>
32#include <asm/fpu.h>
33#include <asm/war.h>
34#include <asm/vdso.h>
35#include <asm/dsp.h>
36
37#include "signal-common.h"
38
39static int (*save_fp_context32)(struct sigcontext32 __user *sc);
40static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
41
42extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
43extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
44
45extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
46extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
47
48
49
50
51#define __NR_O32_restart_syscall 4253
52
53
54
55typedef unsigned int __sighandler32_t;
56typedef void (*vfptr_t)(void);
57
58struct sigaction32 {
59 unsigned int sa_flags;
60 __sighandler32_t sa_handler;
61 compat_sigset_t sa_mask;
62};
63
64
65typedef struct sigaltstack32 {
66 s32 ss_sp;
67 compat_size_t ss_size;
68 int ss_flags;
69} stack32_t;
70
71struct ucontext32 {
72 u32 uc_flags;
73 s32 uc_link;
74 stack32_t uc_stack;
75 struct sigcontext32 uc_mcontext;
76 compat_sigset_t uc_sigmask;
77};
78
79struct sigframe32 {
80 u32 sf_ass[4];
81 u32 sf_pad[2];
82 struct sigcontext32 sf_sc;
83 compat_sigset_t sf_mask;
84};
85
86struct rt_sigframe32 {
87 u32 rs_ass[4];
88 u32 rs_pad[2];
89 compat_siginfo_t rs_info;
90 struct ucontext32 rs_uc;
91};
92
93
94
95
96static int protected_save_fp_context32(struct sigcontext32 __user *sc)
97{
98 int err;
99 while (1) {
100 lock_fpu_owner();
101 own_fpu_inatomic(1);
102 err = save_fp_context32(sc);
103 unlock_fpu_owner();
104 if (likely(!err))
105 break;
106
107 err = __put_user(0, &sc->sc_fpregs[0]) |
108 __put_user(0, &sc->sc_fpregs[31]) |
109 __put_user(0, &sc->sc_fpc_csr);
110 if (err)
111 break;
112 }
113 return err;
114}
115
116static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
117{
118 int err, tmp __maybe_unused;
119 while (1) {
120 lock_fpu_owner();
121 own_fpu_inatomic(0);
122 err = restore_fp_context32(sc);
123 unlock_fpu_owner();
124 if (likely(!err))
125 break;
126
127 err = __get_user(tmp, &sc->sc_fpregs[0]) |
128 __get_user(tmp, &sc->sc_fpregs[31]) |
129 __get_user(tmp, &sc->sc_fpc_csr);
130 if (err)
131 break;
132 }
133 return err;
134}
135
136static int setup_sigcontext32(struct pt_regs *regs,
137 struct sigcontext32 __user *sc)
138{
139 int err = 0;
140 int i;
141 u32 used_math;
142
143 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
144
145 err |= __put_user(0, &sc->sc_regs[0]);
146 for (i = 1; i < 32; i++)
147 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
148
149 err |= __put_user(regs->hi, &sc->sc_mdhi);
150 err |= __put_user(regs->lo, &sc->sc_mdlo);
151 if (cpu_has_dsp) {
152 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
153 err |= __put_user(mfhi1(), &sc->sc_hi1);
154 err |= __put_user(mflo1(), &sc->sc_lo1);
155 err |= __put_user(mfhi2(), &sc->sc_hi2);
156 err |= __put_user(mflo2(), &sc->sc_lo2);
157 err |= __put_user(mfhi3(), &sc->sc_hi3);
158 err |= __put_user(mflo3(), &sc->sc_lo3);
159 }
160
161 used_math = !!used_math();
162 err |= __put_user(used_math, &sc->sc_used_math);
163
164 if (used_math) {
165
166
167
168
169 err |= protected_save_fp_context32(sc);
170 }
171 return err;
172}
173
174static int
175check_and_restore_fp_context32(struct sigcontext32 __user *sc)
176{
177 int err, sig;
178
179 err = sig = fpcsr_pending(&sc->sc_fpc_csr);
180 if (err > 0)
181 err = 0;
182 err |= protected_restore_fp_context32(sc);
183 return err ?: sig;
184}
185
186static int restore_sigcontext32(struct pt_regs *regs,
187 struct sigcontext32 __user *sc)
188{
189 u32 used_math;
190 int err = 0;
191 s32 treg;
192 int i;
193
194
195 current_thread_info()->restart_block.fn = do_no_restart_syscall;
196
197 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
198 err |= __get_user(regs->hi, &sc->sc_mdhi);
199 err |= __get_user(regs->lo, &sc->sc_mdlo);
200 if (cpu_has_dsp) {
201 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
202 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
203 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
204 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
205 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
206 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
207 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
208 }
209
210 for (i = 1; i < 32; i++)
211 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
212
213 err |= __get_user(used_math, &sc->sc_used_math);
214 conditional_used_math(used_math);
215
216 if (used_math) {
217
218 if (!err)
219 err = check_and_restore_fp_context32(sc);
220 } else {
221
222 lose_fpu(0);
223 }
224
225 return err;
226}
227
228
229
230
231extern void __put_sigset_unknown_nsig(void);
232extern void __get_sigset_unknown_nsig(void);
233
234static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
235{
236 int err = 0;
237
238 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
239 return -EFAULT;
240
241 switch (_NSIG_WORDS) {
242 default:
243 __put_sigset_unknown_nsig();
244 case 2:
245 err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
246 err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
247 case 1:
248 err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
249 err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
250 }
251
252 return err;
253}
254
255static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
256{
257 int err = 0;
258 unsigned long sig[4];
259
260 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
261 return -EFAULT;
262
263 switch (_NSIG_WORDS) {
264 default:
265 __get_sigset_unknown_nsig();
266 case 2:
267 err |= __get_user(sig[3], &ubuf->sig[3]);
268 err |= __get_user(sig[2], &ubuf->sig[2]);
269 kbuf->sig[1] = sig[2] | (sig[3] << 32);
270 case 1:
271 err |= __get_user(sig[1], &ubuf->sig[1]);
272 err |= __get_user(sig[0], &ubuf->sig[0]);
273 kbuf->sig[0] = sig[0] | (sig[1] << 32);
274 }
275
276 return err;
277}
278
279
280
281
282
283asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
284{
285 compat_sigset_t __user *uset;
286 sigset_t newset;
287
288 uset = (compat_sigset_t __user *) regs.regs[4];
289 if (get_sigset(&newset, uset))
290 return -EFAULT;
291 return sigsuspend(&newset);
292}
293
294asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
295{
296 compat_sigset_t __user *uset;
297 sigset_t newset;
298 size_t sigsetsize;
299
300
301 sigsetsize = regs.regs[5];
302 if (sigsetsize != sizeof(compat_sigset_t))
303 return -EINVAL;
304
305 uset = (compat_sigset_t __user *) regs.regs[4];
306 if (get_sigset(&newset, uset))
307 return -EFAULT;
308 return sigsuspend(&newset);
309}
310
311SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
312 struct sigaction32 __user *, oact)
313{
314 struct k_sigaction new_ka, old_ka;
315 int ret;
316 int err = 0;
317
318 if (act) {
319 old_sigset_t mask;
320 s32 handler;
321
322 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
323 return -EFAULT;
324 err |= __get_user(handler, &act->sa_handler);
325 new_ka.sa.sa_handler = (void __user *)(s64)handler;
326 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
327 err |= __get_user(mask, &act->sa_mask.sig[0]);
328 if (err)
329 return -EFAULT;
330
331 siginitset(&new_ka.sa.sa_mask, mask);
332 }
333
334 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
335
336 if (!ret && oact) {
337 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
338 return -EFAULT;
339 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
340 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
341 &oact->sa_handler);
342 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
343 err |= __put_user(0, &oact->sa_mask.sig[1]);
344 err |= __put_user(0, &oact->sa_mask.sig[2]);
345 err |= __put_user(0, &oact->sa_mask.sig[3]);
346 if (err)
347 return -EFAULT;
348 }
349
350 return ret;
351}
352
353asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
354{
355 const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
356 stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
357 unsigned long usp = regs.regs[29];
358 stack_t kss, koss;
359 int ret, err = 0;
360 mm_segment_t old_fs = get_fs();
361 s32 sp;
362
363 if (uss) {
364 if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
365 return -EFAULT;
366 err |= __get_user(sp, &uss->ss_sp);
367 kss.ss_sp = (void __user *) (long) sp;
368 err |= __get_user(kss.ss_size, &uss->ss_size);
369 err |= __get_user(kss.ss_flags, &uss->ss_flags);
370 if (err)
371 return -EFAULT;
372 }
373
374 set_fs(KERNEL_DS);
375 ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
376 uoss ? (stack_t __user *)&koss : NULL, usp);
377 set_fs(old_fs);
378
379 if (!ret && uoss) {
380 if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
381 return -EFAULT;
382 sp = (int) (unsigned long) koss.ss_sp;
383 err |= __put_user(sp, &uoss->ss_sp);
384 err |= __put_user(koss.ss_size, &uoss->ss_size);
385 err |= __put_user(koss.ss_flags, &uoss->ss_flags);
386 if (err)
387 return -EFAULT;
388 }
389 return ret;
390}
391
392int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
393{
394 int err;
395
396 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
397 return -EFAULT;
398
399
400
401
402
403
404
405
406 err = __put_user(from->si_signo, &to->si_signo);
407 err |= __put_user(from->si_errno, &to->si_errno);
408 err |= __put_user((short)from->si_code, &to->si_code);
409 if (from->si_code < 0)
410 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
411 else {
412 switch (from->si_code >> 16) {
413 case __SI_TIMER >> 16:
414 err |= __put_user(from->si_tid, &to->si_tid);
415 err |= __put_user(from->si_overrun, &to->si_overrun);
416 err |= __put_user(from->si_int, &to->si_int);
417 break;
418 case __SI_CHLD >> 16:
419 err |= __put_user(from->si_utime, &to->si_utime);
420 err |= __put_user(from->si_stime, &to->si_stime);
421 err |= __put_user(from->si_status, &to->si_status);
422 default:
423 err |= __put_user(from->si_pid, &to->si_pid);
424 err |= __put_user(from->si_uid, &to->si_uid);
425 break;
426 case __SI_FAULT >> 16:
427 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
428 break;
429 case __SI_POLL >> 16:
430 err |= __put_user(from->si_band, &to->si_band);
431 err |= __put_user(from->si_fd, &to->si_fd);
432 break;
433 case __SI_RT >> 16:
434 case __SI_MESGQ >> 16:
435 err |= __put_user(from->si_pid, &to->si_pid);
436 err |= __put_user(from->si_uid, &to->si_uid);
437 err |= __put_user(from->si_int, &to->si_int);
438 break;
439 }
440 }
441 return err;
442}
443
444int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
445{
446 memset(to, 0, sizeof *to);
447
448 if (copy_from_user(to, from, 3*sizeof(int)) ||
449 copy_from_user(to->_sifields._pad,
450 from->_sifields._pad, SI_PAD_SIZE32))
451 return -EFAULT;
452
453 return 0;
454}
455
456asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
457{
458 struct sigframe32 __user *frame;
459 sigset_t blocked;
460 int sig;
461
462 frame = (struct sigframe32 __user *) regs.regs[29];
463 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
464 goto badframe;
465 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
466 goto badframe;
467
468 set_current_blocked(&blocked);
469
470 sig = restore_sigcontext32(®s, &frame->sf_sc);
471 if (sig < 0)
472 goto badframe;
473 else if (sig)
474 force_sig(sig, current);
475
476
477
478
479 __asm__ __volatile__(
480 "move\t$29, %0\n\t"
481 "j\tsyscall_exit"
482 :
483 :"r" (®s));
484
485
486badframe:
487 force_sig(SIGSEGV, current);
488}
489
490asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
491{
492 struct rt_sigframe32 __user *frame;
493 mm_segment_t old_fs;
494 sigset_t set;
495 stack_t st;
496 s32 sp;
497 int sig;
498
499 frame = (struct rt_sigframe32 __user *) regs.regs[29];
500 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
501 goto badframe;
502 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
503 goto badframe;
504
505 set_current_blocked(&set);
506
507 sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext);
508 if (sig < 0)
509 goto badframe;
510 else if (sig)
511 force_sig(sig, current);
512
513
514 if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
515 goto badframe;
516 st.ss_sp = (void __user *)(long) sp;
517 if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
518 goto badframe;
519 if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
520 goto badframe;
521
522
523
524 old_fs = get_fs();
525 set_fs(KERNEL_DS);
526 do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
527 set_fs(old_fs);
528
529
530
531
532 __asm__ __volatile__(
533 "move\t$29, %0\n\t"
534 "j\tsyscall_exit"
535 :
536 :"r" (®s));
537
538
539badframe:
540 force_sig(SIGSEGV, current);
541}
542
543static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
544 struct pt_regs *regs, int signr, sigset_t *set)
545{
546 struct sigframe32 __user *frame;
547 int err = 0;
548
549 frame = get_sigframe(ka, regs, sizeof(*frame));
550 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
551 goto give_sigsegv;
552
553 err |= setup_sigcontext32(regs, &frame->sf_sc);
554 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
555
556 if (err)
557 goto give_sigsegv;
558
559
560
561
562
563
564
565
566
567
568
569 regs->regs[ 4] = signr;
570 regs->regs[ 5] = 0;
571 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
572 regs->regs[29] = (unsigned long) frame;
573 regs->regs[31] = (unsigned long) sig_return;
574 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
575
576 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
577 current->comm, current->pid,
578 frame, regs->cp0_epc, regs->regs[31]);
579
580 return 0;
581
582give_sigsegv:
583 force_sigsegv(signr, current);
584 return -EFAULT;
585}
586
587static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
588 struct pt_regs *regs, int signr, sigset_t *set,
589 siginfo_t *info)
590{
591 struct rt_sigframe32 __user *frame;
592 int err = 0;
593 s32 sp;
594
595 frame = get_sigframe(ka, regs, sizeof(*frame));
596 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
597 goto give_sigsegv;
598
599
600 err |= copy_siginfo_to_user32(&frame->rs_info, info);
601
602
603 err |= __put_user(0, &frame->rs_uc.uc_flags);
604 err |= __put_user(0, &frame->rs_uc.uc_link);
605 sp = (int) (long) current->sas_ss_sp;
606 err |= __put_user(sp,
607 &frame->rs_uc.uc_stack.ss_sp);
608 err |= __put_user(sas_ss_flags(regs->regs[29]),
609 &frame->rs_uc.uc_stack.ss_flags);
610 err |= __put_user(current->sas_ss_size,
611 &frame->rs_uc.uc_stack.ss_size);
612 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
613 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
614
615 if (err)
616 goto give_sigsegv;
617
618
619
620
621
622
623
624
625
626
627
628 regs->regs[ 4] = signr;
629 regs->regs[ 5] = (unsigned long) &frame->rs_info;
630 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
631 regs->regs[29] = (unsigned long) frame;
632 regs->regs[31] = (unsigned long) sig_return;
633 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
634
635 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
636 current->comm, current->pid,
637 frame, regs->cp0_epc, regs->regs[31]);
638
639 return 0;
640
641give_sigsegv:
642 force_sigsegv(signr, current);
643 return -EFAULT;
644}
645
646
647
648
649struct mips_abi mips_abi_32 = {
650 .setup_frame = setup_frame_32,
651 .signal_return_offset =
652 offsetof(struct mips_vdso, o32_signal_trampoline),
653 .setup_rt_frame = setup_rt_frame_32,
654 .rt_signal_return_offset =
655 offsetof(struct mips_vdso, o32_rt_signal_trampoline),
656 .restart = __NR_O32_restart_syscall
657};
658
659SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
660 const struct sigaction32 __user *, act,
661 struct sigaction32 __user *, oact, unsigned int, sigsetsize)
662{
663 struct k_sigaction new_sa, old_sa;
664 int ret = -EINVAL;
665
666
667 if (sigsetsize != sizeof(sigset_t))
668 goto out;
669
670 if (act) {
671 s32 handler;
672 int err = 0;
673
674 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
675 return -EFAULT;
676 err |= __get_user(handler, &act->sa_handler);
677 new_sa.sa.sa_handler = (void __user *)(s64)handler;
678 err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
679 err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
680 if (err)
681 return -EFAULT;
682 }
683
684 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
685
686 if (!ret && oact) {
687 int err = 0;
688
689 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
690 return -EFAULT;
691
692 err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
693 &oact->sa_handler);
694 err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
695 err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
696 if (err)
697 return -EFAULT;
698 }
699out:
700 return ret;
701}
702
703SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
704 compat_sigset_t __user *, oset, unsigned int, sigsetsize)
705{
706 sigset_t old_set, new_set;
707 int ret;
708 mm_segment_t old_fs = get_fs();
709
710 if (set && get_sigset(&new_set, set))
711 return -EFAULT;
712
713 set_fs(KERNEL_DS);
714 ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
715 oset ? (sigset_t __user *)&old_set : NULL,
716 sigsetsize);
717 set_fs(old_fs);
718
719 if (!ret && oset && put_sigset(&old_set, oset))
720 return -EFAULT;
721
722 return ret;
723}
724
725SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
726 unsigned int, sigsetsize)
727{
728 int ret;
729 sigset_t set;
730 mm_segment_t old_fs = get_fs();
731
732 set_fs(KERNEL_DS);
733 ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
734 set_fs(old_fs);
735
736 if (!ret && put_sigset(&set, uset))
737 return -EFAULT;
738
739 return ret;
740}
741
742SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
743 compat_siginfo_t __user *, uinfo)
744{
745 siginfo_t info;
746 int ret;
747 mm_segment_t old_fs = get_fs();
748
749 if (copy_from_user(&info, uinfo, 3*sizeof(int)) ||
750 copy_from_user(info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
751 return -EFAULT;
752 set_fs(KERNEL_DS);
753 ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
754 set_fs(old_fs);
755 return ret;
756}
757
758SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
759 compat_siginfo_t __user *, uinfo, int, options,
760 struct compat_rusage __user *, uru)
761{
762 siginfo_t info;
763 struct rusage ru;
764 long ret;
765 mm_segment_t old_fs = get_fs();
766
767 info.si_signo = 0;
768 set_fs(KERNEL_DS);
769 ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
770 uru ? (struct rusage __user *) &ru : NULL);
771 set_fs(old_fs);
772
773 if (ret < 0 || info.si_signo == 0)
774 return ret;
775
776 if (uru && (ret = put_compat_rusage(&ru, uru)))
777 return ret;
778
779 BUG_ON(info.si_code & __SI_MASK);
780 info.si_code |= __SI_CHLD;
781 return copy_siginfo_to_user32(uinfo, &info);
782}
783
784static int signal32_init(void)
785{
786 if (cpu_has_fpu) {
787 save_fp_context32 = _save_fp_context32;
788 restore_fp_context32 = _restore_fp_context32;
789 } else {
790 save_fp_context32 = fpu_emulator_save_context32;
791 restore_fp_context32 = fpu_emulator_restore_context32;
792 }
793
794 return 0;
795}
796
797arch_initcall(signal32_init);
798