blob: 97b7c51b825179c59388e341a496fa751e1a3d1c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Martin Michlmayrdda73d02006-02-18 15:21:30 +00007 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
Harvey Huntd1e63c92016-06-17 16:03:45 +01009 * Copyright (C) 2016, Imagination Technologies Ltd.
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 */
Harvey Huntd1e63c92016-06-17 16:03:45 +010011#include <linux/compiler.h>
12#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/kernel.h>
14#include <linux/signal.h>
15#include <linux/syscalls.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016
Harvey Huntd1e63c92016-06-17 16:03:45 +010017#include <asm/compat.h>
Ralf Baechle431dc802007-02-13 00:05:11 +000018#include <asm/compat-signal.h>
Harvey Huntd1e63c92016-06-17 16:03:45 +010019#include <asm/uaccess.h>
20#include <asm/unistd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021
Franck Bui-Huu36a1f2c22007-02-05 15:24:22 +010022#include "signal-common.h"
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024/* 32-bit compatibility types */
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026typedef unsigned int __sighandler32_t;
27typedef void (*vfptr_t)(void);
28
Franck Bui-Huu9432a9b2007-02-05 15:24:25 +010029/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070030 * Atomically swap in the new signal mask, and wait for a signal.
31 */
32
Al Viro1910f4a2012-12-25 16:25:18 -050033asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
Linus Torvalds1da177e2005-04-16 15:20:36 -070034{
Al Viro1910f4a2012-12-25 16:25:18 -050035 return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
Linus Torvalds1da177e2005-04-16 15:20:36 -070036}
37
Al Viroaa584802012-12-25 18:55:27 -050038SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
39 struct compat_sigaction __user *, oact)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040{
41 struct k_sigaction new_ka, old_ka;
42 int ret;
43 int err = 0;
44
45 if (act) {
46 old_sigset_t mask;
Ralf Baechle77c728c2005-03-04 19:36:51 +000047 s32 handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
49 if (!access_ok(VERIFY_READ, act, sizeof(*act)))
50 return -EFAULT;
Ralf Baechle77c728c2005-03-04 19:36:51 +000051 err |= __get_user(handler, &act->sa_handler);
Atsushi Nemoto9bbf28a32006-02-01 01:41:09 +090052 new_ka.sa.sa_handler = (void __user *)(s64)handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 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)))
Martin Michlmayr62549442006-02-18 20:06:32 +000065 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -070066 err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
67 err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
Ralf Baechle70342282013-01-22 12:59:30 +010068 &oact->sa_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
Martin Michlmayr62549442006-02-18 20:06:32 +000070 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)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 return -EFAULT;
75 }
76
77 return ret;
78}
79
Al Viroce395962013-10-13 17:23:53 -040080int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
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) {
Ralf Baechlea9820992005-02-16 21:24:16 +0000101 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 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:
Atsushi Nemoto5665a0a2006-02-02 01:26:34 +0900115 err |= __put_user((unsigned long)from->si_addr, &to->si_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 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;
Matt Redfearn5050e912016-03-29 09:35:30 +0100127 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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 }
134 }
135 return err;
136}
137
Thomas Bogendoerfer5d9a76c2008-08-17 16:49:25 +0200138int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
139{
Thomas Bogendoerfer5d9a76c2008-08-17 16:49:25 +0200140 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}