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(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 (siginfo_layout(from->si_signo, from->si_code)) { 101 case SIL_TIMER: 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 SIL_CHLD: 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 case SIL_KILL: 111 err |= __put_user(from->si_pid, &to->si_pid); 112 err |= __put_user(from->si_uid, &to->si_uid); 113 break; 114 case SIL_FAULT: 115 err |= __put_user((unsigned long)from->si_addr, &to->si_addr); 116 break; 117 case SIL_POLL: 118 err |= __put_user(from->si_band, &to->si_band); 119 err |= __put_user(from->si_fd, &to->si_fd); 120 break; 121 case SIL_RT: 122 err |= __put_user(from->si_pid, &to->si_pid); 123 err |= __put_user(from->si_uid, &to->si_uid); 124 err |= __put_user(from->si_int, &to->si_int); 125 break; 126 case SIL_SYS: 127 err |= __copy_to_user(&to->si_call_addr, &from->si_call_addr, 128 sizeof(compat_uptr_t)); 129 err |= __put_user(from->si_syscall, &to->si_syscall); 130 err |= __put_user(from->si_arch, &to->si_arch); 131 break; 132 } 133 } 134 return err; 135 } 136 137 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) 138 { 139 if (copy_from_user(to, from, 3*sizeof(int)) || 140 copy_from_user(to->_sifields._pad, 141 from->_sifields._pad, SI_PAD_SIZE32)) 142 return -EFAULT; 143 144 return 0; 145 } 146