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 <linux/uaccess.h> 20 #include <asm/unistd.h> 21 22 #include "signal-common.h" 23 24 /* 32-bit compatibility types */ 25 26 typedef unsigned int __sighandler32_t; 27 typedef void (*vfptr_t)(void); 28 29 /* 30 * Atomically swap in the new signal mask, and wait for a signal. 31 */ 32 33 asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset) 34 { 35 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t)); 36 } 37 38 SYSCALL_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 80 int 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 138 int 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