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
45
46
47
48#define __NR_O32_restart_syscall 4253
49
50
51
52typedef unsigned int __sighandler32_t;
53typedef void (*vfptr_t)(void);
54
55struct ucontext32 {
56 u32 uc_flags;
57 s32 uc_link;
58 compat_stack_t uc_stack;
59 struct sigcontext32 uc_mcontext;
60 compat_sigset_t uc_sigmask;
61};
62
63struct sigframe32 {
64 u32 sf_ass[4];
65 u32 sf_pad[2];
66 struct sigcontext32 sf_sc;
67 compat_sigset_t sf_mask;
68};
69
70struct rt_sigframe32 {
71 u32 rs_ass[4];
72 u32 rs_pad[2];
73 compat_siginfo_t rs_info;
74 struct ucontext32 rs_uc;
75};
76
77
78
79
80
81static int copy_fp_to_sigcontext32(struct sigcontext32 __user *sc)
82{
83 int i;
84 int err = 0;
85 int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
86
87 for (i = 0; i < NUM_FPU_REGS; i += inc) {
88 err |=
89 __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0),
90 &sc->sc_fpregs[i]);
91 }
92 err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
93
94 return err;
95}
96
97static int copy_fp_from_sigcontext32(struct sigcontext32 __user *sc)
98{
99 int i;
100 int err = 0;
101 int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1;
102 u64 fpr_val;
103
104 for (i = 0; i < NUM_FPU_REGS; i += inc) {
105 err |= __get_user(fpr_val, &sc->sc_fpregs[i]);
106 set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val);
107 }
108 err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
109
110 return err;
111}
112
113
114
115
116static int protected_save_fp_context32(struct sigcontext32 __user *sc)
117{
118 int err;
119 while (1) {
120 lock_fpu_owner();
121 if (is_fpu_owner()) {
122 err = save_fp_context32(sc);
123 unlock_fpu_owner();
124 } else {
125 unlock_fpu_owner();
126 err = copy_fp_to_sigcontext32(sc);
127 }
128 if (likely(!err))
129 break;
130
131 err = __put_user(0, &sc->sc_fpregs[0]) |
132 __put_user(0, &sc->sc_fpregs[31]) |
133 __put_user(0, &sc->sc_fpc_csr);
134 if (err)
135 break;
136 }
137 return err;
138}
139
140static int protected_restore_fp_context32(struct sigcontext32 __user *sc)
141{
142 int err, tmp __maybe_unused;
143 while (1) {
144 lock_fpu_owner();
145 if (is_fpu_owner()) {
146 err = restore_fp_context32(sc);
147 unlock_fpu_owner();
148 } else {
149 unlock_fpu_owner();
150 err = copy_fp_from_sigcontext32(sc);
151 }
152 if (likely(!err))
153 break;
154
155 err = __get_user(tmp, &sc->sc_fpregs[0]) |
156 __get_user(tmp, &sc->sc_fpregs[31]) |
157 __get_user(tmp, &sc->sc_fpc_csr);
158 if (err)
159 break;
160 }
161 return err;
162}
163
164static int setup_sigcontext32(struct pt_regs *regs,
165 struct sigcontext32 __user *sc)
166{
167 int err = 0;
168 int i;
169 u32 used_math;
170
171 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
172
173 err |= __put_user(0, &sc->sc_regs[0]);
174 for (i = 1; i < 32; i++)
175 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
176
177 err |= __put_user(regs->hi, &sc->sc_mdhi);
178 err |= __put_user(regs->lo, &sc->sc_mdlo);
179 if (cpu_has_dsp) {
180 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
181 err |= __put_user(mfhi1(), &sc->sc_hi1);
182 err |= __put_user(mflo1(), &sc->sc_lo1);
183 err |= __put_user(mfhi2(), &sc->sc_hi2);
184 err |= __put_user(mflo2(), &sc->sc_lo2);
185 err |= __put_user(mfhi3(), &sc->sc_hi3);
186 err |= __put_user(mflo3(), &sc->sc_lo3);
187 }
188
189 used_math = !!used_math();
190 err |= __put_user(used_math, &sc->sc_used_math);
191
192 if (used_math) {
193
194
195
196
197 err |= protected_save_fp_context32(sc);
198 }
199 return err;
200}
201
202static int
203check_and_restore_fp_context32(struct sigcontext32 __user *sc)
204{
205 int err, sig;
206
207 err = sig = fpcsr_pending(&sc->sc_fpc_csr);
208 if (err > 0)
209 err = 0;
210 err |= protected_restore_fp_context32(sc);
211 return err ?: sig;
212}
213
214static int restore_sigcontext32(struct pt_regs *regs,
215 struct sigcontext32 __user *sc)
216{
217 u32 used_math;
218 int err = 0;
219 s32 treg;
220 int i;
221
222
223 current_thread_info()->restart_block.fn = do_no_restart_syscall;
224
225 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
226 err |= __get_user(regs->hi, &sc->sc_mdhi);
227 err |= __get_user(regs->lo, &sc->sc_mdlo);
228 if (cpu_has_dsp) {
229 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
230 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
231 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
232 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
233 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
234 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
235 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
236 }
237
238 for (i = 1; i < 32; i++)
239 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
240
241 err |= __get_user(used_math, &sc->sc_used_math);
242 conditional_used_math(used_math);
243
244 if (used_math) {
245
246 if (!err)
247 err = check_and_restore_fp_context32(sc);
248 } else {
249
250 lose_fpu(0);
251 }
252
253 return err;
254}
255
256
257
258
259extern void __put_sigset_unknown_nsig(void);
260extern void __get_sigset_unknown_nsig(void);
261
262static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t __user *ubuf)
263{
264 int err = 0;
265
266 if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
267 return -EFAULT;
268
269 switch (_NSIG_WORDS) {
270 default:
271 __put_sigset_unknown_nsig();
272 case 2:
273 err |= __put_user(kbuf->sig[1] >> 32, &ubuf->sig[3]);
274 err |= __put_user(kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
275 case 1:
276 err |= __put_user(kbuf->sig[0] >> 32, &ubuf->sig[1]);
277 err |= __put_user(kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
278 }
279
280 return err;
281}
282
283static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
284{
285 int err = 0;
286 unsigned long sig[4];
287
288 if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
289 return -EFAULT;
290
291 switch (_NSIG_WORDS) {
292 default:
293 __get_sigset_unknown_nsig();
294 case 2:
295 err |= __get_user(sig[3], &ubuf->sig[3]);
296 err |= __get_user(sig[2], &ubuf->sig[2]);
297 kbuf->sig[1] = sig[2] | (sig[3] << 32);
298 case 1:
299 err |= __get_user(sig[1], &ubuf->sig[1]);
300 err |= __get_user(sig[0], &ubuf->sig[0]);
301 kbuf->sig[0] = sig[0] | (sig[1] << 32);
302 }
303
304 return err;
305}
306
307
308
309
310
311asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
312{
313 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
314}
315
316SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
317 struct compat_sigaction __user *, oact)
318{
319 struct k_sigaction new_ka, old_ka;
320 int ret;
321 int err = 0;
322
323 if (act) {
324 old_sigset_t mask;
325 s32 handler;
326
327 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
328 return -EFAULT;
329 err |= __get_user(handler, &act->sa_handler);
330 new_ka.sa.sa_handler = (void __user *)(s64)handler;
331 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
332 err |= __get_user(mask, &act->sa_mask.sig[0]);
333 if (err)
334 return -EFAULT;
335
336 siginitset(&new_ka.sa.sa_mask, mask);
337 }
338
339 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
340
341 if (!ret && oact) {
342 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
343 return -EFAULT;
344 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
345 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
346 &oact->sa_handler);
347 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
348 err |= __put_user(0, &oact->sa_mask.sig[1]);
349 err |= __put_user(0, &oact->sa_mask.sig[2]);
350 err |= __put_user(0, &oact->sa_mask.sig[3]);
351 if (err)
352 return -EFAULT;
353 }
354
355 return ret;
356}
357
358int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
359{
360 int err;
361
362 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
363 return -EFAULT;
364
365
366
367
368
369
370
371
372 err = __put_user(from->si_signo, &to->si_signo);
373 err |= __put_user(from->si_errno, &to->si_errno);
374 err |= __put_user((short)from->si_code, &to->si_code);
375 if (from->si_code < 0)
376 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
377 else {
378 switch (from->si_code >> 16) {
379 case __SI_TIMER >> 16:
380 err |= __put_user(from->si_tid, &to->si_tid);
381 err |= __put_user(from->si_overrun, &to->si_overrun);
382 err |= __put_user(from->si_int, &to->si_int);
383 break;
384 case __SI_CHLD >> 16:
385 err |= __put_user(from->si_utime, &to->si_utime);
386 err |= __put_user(from->si_stime, &to->si_stime);
387 err |= __put_user(from->si_status, &to->si_status);
388 default:
389 err |= __put_user(from->si_pid, &to->si_pid);
390 err |= __put_user(from->si_uid, &to->si_uid);
391 break;
392 case __SI_FAULT >> 16:
393 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
394 break;
395 case __SI_POLL >> 16:
396 err |= __put_user(from->si_band, &to->si_band);
397 err |= __put_user(from->si_fd, &to->si_fd);
398 break;
399 case __SI_RT >> 16:
400 case __SI_MESGQ >> 16:
401 err |= __put_user(from->si_pid, &to->si_pid);
402 err |= __put_user(from->si_uid, &to->si_uid);
403 err |= __put_user(from->si_int, &to->si_int);
404 break;
405 }
406 }
407 return err;
408}
409
410int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
411{
412 memset(to, 0, sizeof *to);
413
414 if (copy_from_user(to, from, 3*sizeof(int)) ||
415 copy_from_user(to->_sifields._pad,
416 from->_sifields._pad, SI_PAD_SIZE32))
417 return -EFAULT;
418
419 return 0;
420}
421
422asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
423{
424 struct sigframe32 __user *frame;
425 sigset_t blocked;
426 int sig;
427
428 frame = (struct sigframe32 __user *) regs.regs[29];
429 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
430 goto badframe;
431 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
432 goto badframe;
433
434 set_current_blocked(&blocked);
435
436 sig = restore_sigcontext32(®s, &frame->sf_sc);
437 if (sig < 0)
438 goto badframe;
439 else if (sig)
440 force_sig(sig, current);
441
442
443
444
445 __asm__ __volatile__(
446 "move\t$29, %0\n\t"
447 "j\tsyscall_exit"
448 :
449 :"r" (®s));
450
451
452badframe:
453 force_sig(SIGSEGV, current);
454}
455
456asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
457{
458 struct rt_sigframe32 __user *frame;
459 sigset_t set;
460 int sig;
461
462 frame = (struct rt_sigframe32 __user *) regs.regs[29];
463 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
464 goto badframe;
465 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
466 goto badframe;
467
468 set_current_blocked(&set);
469
470 sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext);
471 if (sig < 0)
472 goto badframe;
473 else if (sig)
474 force_sig(sig, current);
475
476 if (compat_restore_altstack(&frame->rs_uc.uc_stack))
477 goto badframe;
478
479
480
481
482 __asm__ __volatile__(
483 "move\t$29, %0\n\t"
484 "j\tsyscall_exit"
485 :
486 :"r" (®s));
487
488
489badframe:
490 force_sig(SIGSEGV, current);
491}
492
493static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
494 struct pt_regs *regs, int signr, sigset_t *set)
495{
496 struct sigframe32 __user *frame;
497 int err = 0;
498
499 frame = get_sigframe(ka, regs, sizeof(*frame));
500 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
501 goto give_sigsegv;
502
503 err |= setup_sigcontext32(regs, &frame->sf_sc);
504 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
505
506 if (err)
507 goto give_sigsegv;
508
509
510
511
512
513
514
515
516
517
518
519 regs->regs[ 4] = signr;
520 regs->regs[ 5] = 0;
521 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
522 regs->regs[29] = (unsigned long) frame;
523 regs->regs[31] = (unsigned long) sig_return;
524 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
525
526 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
527 current->comm, current->pid,
528 frame, regs->cp0_epc, regs->regs[31]);
529
530 return 0;
531
532give_sigsegv:
533 force_sigsegv(signr, current);
534 return -EFAULT;
535}
536
537static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
538 struct pt_regs *regs, int signr, sigset_t *set,
539 siginfo_t *info)
540{
541 struct rt_sigframe32 __user *frame;
542 int err = 0;
543
544 frame = get_sigframe(ka, regs, sizeof(*frame));
545 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
546 goto give_sigsegv;
547
548
549 err |= copy_siginfo_to_user32(&frame->rs_info, info);
550
551
552 err |= __put_user(0, &frame->rs_uc.uc_flags);
553 err |= __put_user(0, &frame->rs_uc.uc_link);
554 err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
555 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
556 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
557
558 if (err)
559 goto give_sigsegv;
560
561
562
563
564
565
566
567
568
569
570
571 regs->regs[ 4] = signr;
572 regs->regs[ 5] = (unsigned long) &frame->rs_info;
573 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
574 regs->regs[29] = (unsigned long) frame;
575 regs->regs[31] = (unsigned long) sig_return;
576 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
577
578 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
579 current->comm, current->pid,
580 frame, regs->cp0_epc, regs->regs[31]);
581
582 return 0;
583
584give_sigsegv:
585 force_sigsegv(signr, current);
586 return -EFAULT;
587}
588
589
590
591
592struct mips_abi mips_abi_32 = {
593 .setup_frame = setup_frame_32,
594 .signal_return_offset =
595 offsetof(struct mips_vdso, o32_signal_trampoline),
596 .setup_rt_frame = setup_rt_frame_32,
597 .rt_signal_return_offset =
598 offsetof(struct mips_vdso, o32_rt_signal_trampoline),
599 .restart = __NR_O32_restart_syscall
600};
601
602static int signal32_init(void)
603{
604 if (cpu_has_fpu) {
605 save_fp_context32 = _save_fp_context32;
606 restore_fp_context32 = _restore_fp_context32;
607 } else {
608 save_fp_context32 = copy_fp_to_sigcontext32;
609 restore_fp_context32 = copy_fp_from_sigcontext32;
610 }
611
612 return 0;
613}
614
615arch_initcall(signal32_init);
616