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/dsp.h>
35
36#include "signal-common.h"
37
38
39
40
41#define __NR_O32_restart_syscall 4253
42
43
44
45typedef unsigned int __sighandler32_t;
46typedef void (*vfptr_t)(void);
47
48struct ucontext32 {
49 u32 uc_flags;
50 s32 uc_link;
51 compat_stack_t uc_stack;
52 struct sigcontext32 uc_mcontext;
53 compat_sigset_t uc_sigmask;
54};
55
56struct sigframe32 {
57 u32 sf_ass[4];
58 u32 sf_pad[2];
59 struct sigcontext32 sf_sc;
60 compat_sigset_t sf_mask;
61};
62
63struct rt_sigframe32 {
64 u32 rs_ass[4];
65 u32 rs_pad[2];
66 compat_siginfo_t rs_info;
67 struct ucontext32 rs_uc;
68};
69
70static int setup_sigcontext32(struct pt_regs *regs,
71 struct sigcontext32 __user *sc)
72{
73 int err = 0;
74 int i;
75
76 err |= __put_user(regs->cp0_epc, &sc->sc_pc);
77
78 err |= __put_user(0, &sc->sc_regs[0]);
79 for (i = 1; i < 32; i++)
80 err |= __put_user(regs->regs[i], &sc->sc_regs[i]);
81
82 err |= __put_user(regs->hi, &sc->sc_mdhi);
83 err |= __put_user(regs->lo, &sc->sc_mdlo);
84 if (cpu_has_dsp) {
85 err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp);
86 err |= __put_user(mfhi1(), &sc->sc_hi1);
87 err |= __put_user(mflo1(), &sc->sc_lo1);
88 err |= __put_user(mfhi2(), &sc->sc_hi2);
89 err |= __put_user(mflo2(), &sc->sc_lo2);
90 err |= __put_user(mfhi3(), &sc->sc_hi3);
91 err |= __put_user(mflo3(), &sc->sc_lo3);
92 }
93
94
95
96
97
98 err |= protected_save_fp_context(sc);
99
100 return err;
101}
102
103static int restore_sigcontext32(struct pt_regs *regs,
104 struct sigcontext32 __user *sc)
105{
106 int err = 0;
107 s32 treg;
108 int i;
109
110
111 current->restart_block.fn = do_no_restart_syscall;
112
113 err |= __get_user(regs->cp0_epc, &sc->sc_pc);
114 err |= __get_user(regs->hi, &sc->sc_mdhi);
115 err |= __get_user(regs->lo, &sc->sc_mdlo);
116 if (cpu_has_dsp) {
117 err |= __get_user(treg, &sc->sc_hi1); mthi1(treg);
118 err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg);
119 err |= __get_user(treg, &sc->sc_hi2); mthi2(treg);
120 err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg);
121 err |= __get_user(treg, &sc->sc_hi3); mthi3(treg);
122 err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg);
123 err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK);
124 }
125
126 for (i = 1; i < 32; i++)
127 err |= __get_user(regs->regs[i], &sc->sc_regs[i]);
128
129 return err ?: protected_restore_fp_context(sc);
130}
131
132
133
134
135
136asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
137{
138 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
139}
140
141SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
142 struct compat_sigaction __user *, oact)
143{
144 struct k_sigaction new_ka, old_ka;
145 int ret;
146 int err = 0;
147
148 if (act) {
149 old_sigset_t mask;
150 s32 handler;
151
152 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
153 return -EFAULT;
154 err |= __get_user(handler, &act->sa_handler);
155 new_ka.sa.sa_handler = (void __user *)(s64)handler;
156 err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
157 err |= __get_user(mask, &act->sa_mask.sig[0]);
158 if (err)
159 return -EFAULT;
160
161 siginitset(&new_ka.sa.sa_mask, mask);
162 }
163
164 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
165
166 if (!ret && oact) {
167 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
168 return -EFAULT;
169 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
170 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
171 &oact->sa_handler);
172 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
173 err |= __put_user(0, &oact->sa_mask.sig[1]);
174 err |= __put_user(0, &oact->sa_mask.sig[2]);
175 err |= __put_user(0, &oact->sa_mask.sig[3]);
176 if (err)
177 return -EFAULT;
178 }
179
180 return ret;
181}
182
183int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
184{
185 int err;
186
187 if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
188 return -EFAULT;
189
190
191
192
193
194
195
196
197 err = __put_user(from->si_signo, &to->si_signo);
198 err |= __put_user(from->si_errno, &to->si_errno);
199 err |= __put_user((short)from->si_code, &to->si_code);
200 if (from->si_code < 0)
201 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
202 else {
203 switch (from->si_code >> 16) {
204 case __SI_TIMER >> 16:
205 err |= __put_user(from->si_tid, &to->si_tid);
206 err |= __put_user(from->si_overrun, &to->si_overrun);
207 err |= __put_user(from->si_int, &to->si_int);
208 break;
209 case __SI_CHLD >> 16:
210 err |= __put_user(from->si_utime, &to->si_utime);
211 err |= __put_user(from->si_stime, &to->si_stime);
212 err |= __put_user(from->si_status, &to->si_status);
213 default:
214 err |= __put_user(from->si_pid, &to->si_pid);
215 err |= __put_user(from->si_uid, &to->si_uid);
216 break;
217 case __SI_FAULT >> 16:
218 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
219 break;
220 case __SI_POLL >> 16:
221 err |= __put_user(from->si_band, &to->si_band);
222 err |= __put_user(from->si_fd, &to->si_fd);
223 break;
224 case __SI_RT >> 16:
225 case __SI_MESGQ >> 16:
226 err |= __put_user(from->si_pid, &to->si_pid);
227 err |= __put_user(from->si_uid, &to->si_uid);
228 err |= __put_user(from->si_int, &to->si_int);
229 break;
230 }
231 }
232 return err;
233}
234
235int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
236{
237 if (copy_from_user(to, from, 3*sizeof(int)) ||
238 copy_from_user(to->_sifields._pad,
239 from->_sifields._pad, SI_PAD_SIZE32))
240 return -EFAULT;
241
242 return 0;
243}
244
245asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
246{
247 struct sigframe32 __user *frame;
248 sigset_t blocked;
249 int sig;
250
251 frame = (struct sigframe32 __user *) regs.regs[29];
252 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
253 goto badframe;
254 if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
255 goto badframe;
256
257 set_current_blocked(&blocked);
258
259 sig = restore_sigcontext32(®s, &frame->sf_sc);
260 if (sig < 0)
261 goto badframe;
262 else if (sig)
263 force_sig(sig, current);
264
265
266
267
268 __asm__ __volatile__(
269 "move\t$29, %0\n\t"
270 "j\tsyscall_exit"
271 :
272 :"r" (®s));
273
274
275badframe:
276 force_sig(SIGSEGV, current);
277}
278
279asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
280{
281 struct rt_sigframe32 __user *frame;
282 sigset_t set;
283 int sig;
284
285 frame = (struct rt_sigframe32 __user *) regs.regs[29];
286 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
287 goto badframe;
288 if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
289 goto badframe;
290
291 set_current_blocked(&set);
292
293 sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext);
294 if (sig < 0)
295 goto badframe;
296 else if (sig)
297 force_sig(sig, current);
298
299 if (compat_restore_altstack(&frame->rs_uc.uc_stack))
300 goto badframe;
301
302
303
304
305 __asm__ __volatile__(
306 "move\t$29, %0\n\t"
307 "j\tsyscall_exit"
308 :
309 :"r" (®s));
310
311
312badframe:
313 force_sig(SIGSEGV, current);
314}
315
316static int setup_frame_32(void *sig_return, struct ksignal *ksig,
317 struct pt_regs *regs, sigset_t *set)
318{
319 struct sigframe32 __user *frame;
320 int err = 0;
321
322 frame = get_sigframe(ksig, regs, sizeof(*frame));
323 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
324 return -EFAULT;
325
326 err |= setup_sigcontext32(regs, &frame->sf_sc);
327 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
328
329 if (err)
330 return -EFAULT;
331
332
333
334
335
336
337
338
339
340
341
342 regs->regs[ 4] = ksig->sig;
343 regs->regs[ 5] = 0;
344 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
345 regs->regs[29] = (unsigned long) frame;
346 regs->regs[31] = (unsigned long) sig_return;
347 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
348
349 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
350 current->comm, current->pid,
351 frame, regs->cp0_epc, regs->regs[31]);
352
353 return 0;
354}
355
356static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
357 struct pt_regs *regs, sigset_t *set)
358{
359 struct rt_sigframe32 __user *frame;
360 int err = 0;
361
362 frame = get_sigframe(ksig, regs, sizeof(*frame));
363 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
364 return -EFAULT;
365
366
367 err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
368
369
370 err |= __put_user(0, &frame->rs_uc.uc_flags);
371 err |= __put_user(0, &frame->rs_uc.uc_link);
372 err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
373 err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
374 err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
375
376 if (err)
377 return -EFAULT;
378
379
380
381
382
383
384
385
386
387
388
389 regs->regs[ 4] = ksig->sig;
390 regs->regs[ 5] = (unsigned long) &frame->rs_info;
391 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
392 regs->regs[29] = (unsigned long) frame;
393 regs->regs[31] = (unsigned long) sig_return;
394 regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
395
396 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
397 current->comm, current->pid,
398 frame, regs->cp0_epc, regs->regs[31]);
399
400 return 0;
401}
402
403
404
405
406struct mips_abi mips_abi_32 = {
407 .setup_frame = setup_frame_32,
408 .setup_rt_frame = setup_rt_frame_32,
409 .restart = __NR_O32_restart_syscall,
410
411 .off_sc_fpregs = offsetof(struct sigcontext32, sc_fpregs),
412 .off_sc_fpc_csr = offsetof(struct sigcontext32, sc_fpc_csr),
413 .off_sc_used_math = offsetof(struct sigcontext32, sc_used_math),
414
415 .vdso = &vdso_image_o32,
416};
417