blob: 40df33753bae8d71390b7f4bd81113211a7b67da [file] [log] [blame]
Brian Gerstc0bfd262015-06-22 07:55:10 -04001#include <linux/compat.h>
2#include <linux/uaccess.h>
Dmitry Safonov68463512016-09-05 16:33:08 +03003#include <linux/ptrace.h>
Brian Gerstc0bfd262015-06-22 07:55:10 -04004
Dave Hansen02e8fda2016-06-08 10:25:34 -07005/*
6 * The compat_siginfo_t structure and handing code is very easy
7 * to break in several ways. It must always be updated when new
8 * updates are made to the main siginfo_t, and
9 * copy_siginfo_to_user32() must be updated when the
10 * (arch-independent) copy_siginfo_to_user() is updated.
11 *
12 * It is also easy to put a new member in the compat_siginfo_t
13 * which has implicit alignment which can move internal structure
14 * alignment around breaking the ABI. This can happen if you,
15 * for instance, put a plain 64-bit value in there.
16 */
17static inline void signal_compat_build_tests(void)
18{
19 int _sifields_offset = offsetof(compat_siginfo_t, _sifields);
20
21 /*
22 * If adding a new si_code, there is probably new data in
23 * the siginfo. Make sure folks bumping the si_code
24 * limits also have to look at this code. Make sure any
25 * new fields are handled in copy_siginfo_to_user32()!
26 */
27 BUILD_BUG_ON(NSIGILL != 8);
28 BUILD_BUG_ON(NSIGFPE != 8);
29 BUILD_BUG_ON(NSIGSEGV != 4);
30 BUILD_BUG_ON(NSIGBUS != 5);
31 BUILD_BUG_ON(NSIGTRAP != 4);
32 BUILD_BUG_ON(NSIGCHLD != 6);
33 BUILD_BUG_ON(NSIGSYS != 1);
34
35 /* This is part of the ABI and can never change in size: */
36 BUILD_BUG_ON(sizeof(compat_siginfo_t) != 128);
37 /*
38 * The offsets of all the (unioned) si_fields are fixed
39 * in the ABI, of course. Make sure none of them ever
40 * move and are always at the beginning:
41 */
42 BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields) != 3 * sizeof(int));
43#define CHECK_CSI_OFFSET(name) BUILD_BUG_ON(_sifields_offset != offsetof(compat_siginfo_t, _sifields.name))
44
45 /*
46 * Ensure that the size of each si_field never changes.
47 * If it does, it is a sign that the
48 * copy_siginfo_to_user32() code below needs to updated
49 * along with the size in the CHECK_SI_SIZE().
50 *
51 * We repeat this check for both the generic and compat
52 * siginfos.
53 *
54 * Note: it is OK for these to grow as long as the whole
55 * structure stays within the padding size (checked
56 * above).
57 */
58#define CHECK_CSI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((compat_siginfo_t *)0)->_sifields.name))
59#define CHECK_SI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((siginfo_t *)0)->_sifields.name))
60
61 CHECK_CSI_OFFSET(_kill);
62 CHECK_CSI_SIZE (_kill, 2*sizeof(int));
63 CHECK_SI_SIZE (_kill, 2*sizeof(int));
64
65 CHECK_CSI_OFFSET(_timer);
66 CHECK_CSI_SIZE (_timer, 5*sizeof(int));
67 CHECK_SI_SIZE (_timer, 6*sizeof(int));
68
69 CHECK_CSI_OFFSET(_rt);
70 CHECK_CSI_SIZE (_rt, 3*sizeof(int));
71 CHECK_SI_SIZE (_rt, 4*sizeof(int));
72
73 CHECK_CSI_OFFSET(_sigchld);
74 CHECK_CSI_SIZE (_sigchld, 5*sizeof(int));
75 CHECK_SI_SIZE (_sigchld, 8*sizeof(int));
76
77 CHECK_CSI_OFFSET(_sigchld_x32);
78 CHECK_CSI_SIZE (_sigchld_x32, 7*sizeof(int));
79 /* no _sigchld_x32 in the generic siginfo_t */
80
81 CHECK_CSI_OFFSET(_sigfault);
82 CHECK_CSI_SIZE (_sigfault, 4*sizeof(int));
83 CHECK_SI_SIZE (_sigfault, 8*sizeof(int));
84
85 CHECK_CSI_OFFSET(_sigpoll);
86 CHECK_CSI_SIZE (_sigpoll, 2*sizeof(int));
87 CHECK_SI_SIZE (_sigpoll, 4*sizeof(int));
88
89 CHECK_CSI_OFFSET(_sigsys);
90 CHECK_CSI_SIZE (_sigsys, 3*sizeof(int));
91 CHECK_SI_SIZE (_sigsys, 4*sizeof(int));
92
93 /* any new si_fields should be added here */
94}
95
Dmitry Safonov68463512016-09-05 16:33:08 +030096void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
97{
98 /* Don't leak in-kernel non-uapi flags to user-space */
99 if (oact)
100 oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
101
102 if (!act)
103 return;
104
105 /* Don't let flags to be set from userspace */
106 act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
107
108 if (user_64bit_mode(current_pt_regs()))
109 return;
110
111 if (in_ia32_syscall())
112 act->sa.sa_flags |= SA_IA32_ABI;
113 if (in_x32_syscall())
114 act->sa.sa_flags |= SA_X32_ABI;
115}
116
117int __copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from,
118 bool x32_ABI)
Brian Gerstc0bfd262015-06-22 07:55:10 -0400119{
120 int err = 0;
Brian Gerstc0bfd262015-06-22 07:55:10 -0400121
Dave Hansen02e8fda2016-06-08 10:25:34 -0700122 signal_compat_build_tests();
123
Brian Gerstc0bfd262015-06-22 07:55:10 -0400124 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
125 return -EFAULT;
126
127 put_user_try {
128 /* If you change siginfo_t structure, please make sure that
129 this code is fixed accordingly.
130 It should never copy any pad contained in the structure
131 to avoid security leaks, but must copy the generic
132 3 ints plus the relevant union member. */
133 put_user_ex(from->si_signo, &to->si_signo);
134 put_user_ex(from->si_errno, &to->si_errno);
135 put_user_ex((short)from->si_code, &to->si_code);
136
137 if (from->si_code < 0) {
138 put_user_ex(from->si_pid, &to->si_pid);
139 put_user_ex(from->si_uid, &to->si_uid);
140 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
141 } else {
142 /*
143 * First 32bits of unions are always present:
144 * si_pid === si_band === si_tid === si_addr(LS half)
145 */
146 put_user_ex(from->_sifields._pad[0],
147 &to->_sifields._pad[0]);
148 switch (from->si_code >> 16) {
149 case __SI_FAULT >> 16:
Dave Hansena4455082016-06-08 10:25:33 -0700150 if (from->si_signo == SIGBUS &&
151 (from->si_code == BUS_MCEERR_AR ||
152 from->si_code == BUS_MCEERR_AO))
153 put_user_ex(from->si_addr_lsb, &to->si_addr_lsb);
154
155 if (from->si_signo == SIGSEGV) {
156 if (from->si_code == SEGV_BNDERR) {
157 compat_uptr_t lower = (unsigned long)&to->si_lower;
158 compat_uptr_t upper = (unsigned long)&to->si_upper;
159 put_user_ex(lower, &to->si_lower);
160 put_user_ex(upper, &to->si_upper);
161 }
162 if (from->si_code == SEGV_PKUERR)
163 put_user_ex(from->si_pkey, &to->si_pkey);
164 }
Brian Gerstc0bfd262015-06-22 07:55:10 -0400165 break;
166 case __SI_SYS >> 16:
167 put_user_ex(from->si_syscall, &to->si_syscall);
168 put_user_ex(from->si_arch, &to->si_arch);
169 break;
170 case __SI_CHLD >> 16:
Dmitry Safonov68463512016-09-05 16:33:08 +0300171 if (!x32_ABI) {
Brian Gerstc0bfd262015-06-22 07:55:10 -0400172 put_user_ex(from->si_utime, &to->si_utime);
173 put_user_ex(from->si_stime, &to->si_stime);
174 } else {
175 put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime);
176 put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime);
177 }
178 put_user_ex(from->si_status, &to->si_status);
179 /* FALL THROUGH */
180 default:
181 case __SI_KILL >> 16:
182 put_user_ex(from->si_uid, &to->si_uid);
183 break;
184 case __SI_POLL >> 16:
185 put_user_ex(from->si_fd, &to->si_fd);
186 break;
187 case __SI_TIMER >> 16:
188 put_user_ex(from->si_overrun, &to->si_overrun);
189 put_user_ex(ptr_to_compat(from->si_ptr),
190 &to->si_ptr);
191 break;
192 /* This is not generated by the kernel as of now. */
193 case __SI_RT >> 16:
194 case __SI_MESGQ >> 16:
195 put_user_ex(from->si_uid, &to->si_uid);
196 put_user_ex(from->si_int, &to->si_int);
197 break;
198 }
199 }
200 } put_user_catch(err);
201
202 return err;
203}
204
Dmitry Safonov68463512016-09-05 16:33:08 +0300205/* from syscall's path, where we know the ABI */
206int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
207{
208 return __copy_siginfo_to_user32(to, from, in_x32_syscall());
209}
210
Brian Gerstc0bfd262015-06-22 07:55:10 -0400211int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
212{
213 int err = 0;
214 u32 ptr32;
215
216 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
217 return -EFAULT;
218
219 get_user_try {
220 get_user_ex(to->si_signo, &from->si_signo);
221 get_user_ex(to->si_errno, &from->si_errno);
222 get_user_ex(to->si_code, &from->si_code);
223
224 get_user_ex(to->si_pid, &from->si_pid);
225 get_user_ex(to->si_uid, &from->si_uid);
226 get_user_ex(ptr32, &from->si_ptr);
227 to->si_ptr = compat_ptr(ptr32);
228 } get_user_catch(err);
229
230 return err;
231}