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