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