Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | |
dda73d0b | 7 | * Copyright (C) 1994 - 2000, 2006 Ralf Baechle |
1da177e4 | 8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
d1e63c94 | 9 | * Copyright (C) 2016, Imagination Technologies Ltd. |
1da177e4 | 10 | */ |
d1e63c94 HH |
11 | #include <linux/compiler.h> |
12 | #include <linux/errno.h> | |
1da177e4 LT |
13 | #include <linux/kernel.h> |
14 | #include <linux/signal.h> | |
15 | #include <linux/syscalls.h> | |
1da177e4 | 16 | |
d1e63c94 | 17 | #include <asm/compat.h> |
431dc804 | 18 | #include <asm/compat-signal.h> |
7c0f6ba6 | 19 | #include <linux/uaccess.h> |
d1e63c94 | 20 | #include <asm/unistd.h> |
1da177e4 | 21 | |
36a1f2c2 FBH |
22 | #include "signal-common.h" |
23 | ||
1da177e4 LT |
24 | /* 32-bit compatibility types */ |
25 | ||
1da177e4 LT |
26 | typedef unsigned int __sighandler32_t; |
27 | typedef void (*vfptr_t)(void); | |
28 | ||
1da177e4 LT |
29 | /* |
30 | * Atomically swap in the new signal mask, and wait for a signal. | |
31 | */ | |
32 | ||
1910f4ab | 33 | asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset) |
1da177e4 | 34 | { |
1910f4ab | 35 | return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t)); |
1da177e4 LT |
36 | } |
37 | ||
aa584802 AV |
38 | SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act, |
39 | struct compat_sigaction __user *, oact) | |
1da177e4 LT |
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; | |
77c728c2 | 47 | s32 handler; |
1da177e4 LT |
48 | |
49 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) | |
50 | return -EFAULT; | |
77c728c2 | 51 | err |= __get_user(handler, &act->sa_handler); |
9bbf28a3 | 52 | new_ka.sa.sa_handler = (void __user *)(s64)handler; |
1da177e4 LT |
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))) | |
6254944f | 65 | return -EFAULT; |
1da177e4 LT |
66 | err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
67 | err |= __put_user((u32)(u64)old_ka.sa.sa_handler, | |
70342287 | 68 | &oact->sa_handler); |
1da177e4 | 69 | err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); |
6254944f MM |
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) | |
1da177e4 LT |
74 | return -EFAULT; |
75 | } | |
76 | ||
77 | return ret; | |
78 | } | |
79 | ||
ce395960 | 80 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) |
1da177e4 LT |
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); | |
cc731525 | 96 | err |= __put_user(from->si_code, &to->si_code); |
1da177e4 LT |
97 | if (from->si_code < 0) |
98 | err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); | |
99 | else { | |
cc731525 EB |
100 | switch (siginfo_layout(from->si_signo, from->si_code)) { |
101 | case SIL_TIMER: | |
a982099c RB |
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; | |
cc731525 | 106 | case SIL_CHLD: |
1da177e4 LT |
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); | |
cc731525 | 110 | case SIL_KILL: |
1da177e4 LT |
111 | err |= __put_user(from->si_pid, &to->si_pid); |
112 | err |= __put_user(from->si_uid, &to->si_uid); | |
113 | break; | |
cc731525 | 114 | case SIL_FAULT: |
5665a0ac | 115 | err |= __put_user((unsigned long)from->si_addr, &to->si_addr); |
1da177e4 | 116 | break; |
cc731525 | 117 | case SIL_POLL: |
1da177e4 LT |
118 | err |= __put_user(from->si_band, &to->si_band); |
119 | err |= __put_user(from->si_fd, &to->si_fd); | |
120 | break; | |
cc731525 | 121 | case SIL_RT: |
1da177e4 LT |
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; | |
cc731525 | 126 | case SIL_SYS: |
5050e91f MR |
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; | |
1da177e4 LT |
132 | } |
133 | } | |
134 | return err; | |
135 | } | |
136 | ||
5d9a76cd TB |
137 | int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) |
138 | { | |
5d9a76cd TB |
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 | } |