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