~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/kernel/signal32.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.10 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.83 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.153 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.200 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.200 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.76 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp