linux/arch/mips/kernel/signal32.c
<<
>>
Prefs
   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 * Copyright (C) 2016, Imagination Technologies Ltd.
  10 */
  11#include <linux/compiler.h>
  12#include <linux/errno.h>
  13#include <linux/kernel.h>
  14#include <linux/signal.h>
  15#include <linux/syscalls.h>
  16
  17#include <asm/compat.h>
  18#include <asm/compat-signal.h>
  19#include <asm/uaccess.h>
  20#include <asm/unistd.h>
  21
  22#include "signal-common.h"
  23
  24/* 32-bit compatibility types */
  25
  26typedef unsigned int __sighandler32_t;
  27typedef void (*vfptr_t)(void);
  28
  29/*
  30 * Atomically swap in the new signal mask, and wait for a signal.
  31 */
  32
  33asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
  34{
  35        return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
  36}
  37
  38SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
  39        struct compat_sigaction __user *, oact)
  40{
  41        struct k_sigaction new_ka, old_ka;
  42        int ret;
  43        int err = 0;
  44
  45        if (act) {
  46                old_sigset_t mask;
  47                s32 handler;
  48
  49                if (!access_ok(VERIFY_READ, act, sizeof(*act)))
  50                        return -EFAULT;
  51                err |= __get_user(handler, &act->sa_handler);
  52                new_ka.sa.sa_handler = (void __user *)(s64)handler;
  53                err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
  54                err |= __get_user(mask, &act->sa_mask.sig[0]);
  55                if (err)
  56                        return -EFAULT;
  57
  58                siginitset(&new_ka.sa.sa_mask, mask);
  59        }
  60
  61        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  62
  63        if (!ret && oact) {
  64                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
  65                        return -EFAULT;
  66                err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
  67                err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
  68                                  &oact->sa_handler);
  69                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
  70                err |= __put_user(0, &oact->sa_mask.sig[1]);
  71                err |= __put_user(0, &oact->sa_mask.sig[2]);
  72                err |= __put_user(0, &oact->sa_mask.sig[3]);
  73                if (err)
  74                        return -EFAULT;
  75        }
  76
  77        return ret;
  78}
  79
  80int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
  81{
  82        int err;
  83
  84        if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
  85                return -EFAULT;
  86
  87        /* If you change siginfo_t structure, please be sure
  88           this code is fixed accordingly.
  89           It should never copy any pad contained in the structure
  90           to avoid security leaks, but must copy the generic
  91           3 ints plus the relevant union member.
  92           This routine must convert siginfo from 64bit to 32bit as well
  93           at the same time.  */
  94        err = __put_user(from->si_signo, &to->si_signo);
  95        err |= __put_user(from->si_errno, &to->si_errno);
  96        err |= __put_user((short)from->si_code, &to->si_code);
  97        if (from->si_code < 0)
  98                err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
  99        else {
 100                switch (from->si_code >> 16) {
 101                case __SI_TIMER >> 16:
 102                        err |= __put_user(from->si_tid, &to->si_tid);
 103                        err |= __put_user(from->si_overrun, &to->si_overrun);
 104                        err |= __put_user(from->si_int, &to->si_int);
 105                        break;
 106                case __SI_CHLD >> 16:
 107                        err |= __put_user(from->si_utime, &to->si_utime);
 108                        err |= __put_user(from->si_stime, &to->si_stime);
 109                        err |= __put_user(from->si_status, &to->si_status);
 110                default:
 111                        err |= __put_user(from->si_pid, &to->si_pid);
 112                        err |= __put_user(from->si_uid, &to->si_uid);
 113                        break;
 114                case __SI_FAULT >> 16:
 115                        err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
 116                        break;
 117                case __SI_POLL >> 16:
 118                        err |= __put_user(from->si_band, &to->si_band);
 119                        err |= __put_user(from->si_fd, &to->si_fd);
 120                        break;
 121                case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
 122                case __SI_MESGQ >> 16:
 123                        err |= __put_user(from->si_pid, &to->si_pid);
 124                        err |= __put_user(from->si_uid, &to->si_uid);
 125                        err |= __put_user(from->si_int, &to->si_int);
 126                        break;
 127                case __SI_SYS >> 16:
 128                        err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr,
 129                                              sizeof(compat_uptr_t));
 130                        err |= __put_user(from->si_syscall, &to->si_syscall);
 131                        err |= __put_user(from->si_arch, &to->si_arch);
 132                        break;
 133                }
 134        }
 135        return err;
 136}
 137
 138int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 139{
 140        if (copy_from_user(to, from, 3*sizeof(int)) ||
 141            copy_from_user(to->_sifields._pad,
 142                           from->_sifields._pad, SI_PAD_SIZE32))
 143                return -EFAULT;
 144
 145        return 0;
 146}
 147