.. | .. |
---|
32 | 32 | #define KERNEL_DS ((mm_segment_t) { 0 }) |
---|
33 | 33 | #define USER_DS ((mm_segment_t) { 1 }) |
---|
34 | 34 | |
---|
35 | | -#define get_ds() (KERNEL_DS) |
---|
36 | 35 | #define get_fs() (current->thread.current_ds) |
---|
37 | 36 | #define set_fs(val) (current->thread.current_ds = (val)) |
---|
38 | 37 | |
---|
39 | | -#define segment_eq(a, b) ((a).seg == (b).seg) |
---|
| 38 | +#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) |
---|
40 | 39 | |
---|
41 | 40 | #define __kernel_ok (uaccess_kernel()) |
---|
42 | 41 | #define __user_ok(addr, size) \ |
---|
43 | 42 | (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) |
---|
44 | 43 | #define __access_ok(addr, size) (__kernel_ok || __user_ok((addr), (size))) |
---|
45 | | -#define access_ok(type, addr, size) __access_ok((unsigned long)(addr), (size)) |
---|
| 44 | +#define access_ok(addr, size) __access_ok((unsigned long)(addr), (size)) |
---|
46 | 45 | |
---|
47 | 46 | #define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE) |
---|
48 | 47 | |
---|
.. | .. |
---|
85 | 84 | #define __put_user_check(x, ptr, size) \ |
---|
86 | 85 | ({ \ |
---|
87 | 86 | long __pu_err = -EFAULT; \ |
---|
88 | | - __typeof__(*(ptr)) *__pu_addr = (ptr); \ |
---|
89 | | - if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ |
---|
| 87 | + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ |
---|
| 88 | + if (access_ok(__pu_addr, size)) \ |
---|
90 | 89 | __put_user_size((x), __pu_addr, (size), __pu_err); \ |
---|
91 | 90 | __pu_err; \ |
---|
92 | 91 | }) |
---|
.. | .. |
---|
101 | 100 | case 4: __put_user_asm(x, ptr, retval, 4, "s32i", __cb); break; \ |
---|
102 | 101 | case 8: { \ |
---|
103 | 102 | __typeof__(*ptr) __v64 = x; \ |
---|
104 | | - retval = __copy_to_user(ptr, &__v64, 8); \ |
---|
| 103 | + retval = __copy_to_user(ptr, &__v64, 8) ? -EFAULT : 0; \ |
---|
105 | 104 | break; \ |
---|
106 | 105 | } \ |
---|
107 | 106 | default: __put_user_bad(); \ |
---|
.. | .. |
---|
133 | 132 | #define __check_align_1 "" |
---|
134 | 133 | |
---|
135 | 134 | #define __check_align_2 \ |
---|
136 | | - " _bbci.l %3, 0, 1f \n" \ |
---|
137 | | - " movi %0, %4 \n" \ |
---|
| 135 | + " _bbci.l %[mem] * 0, 1f \n" \ |
---|
| 136 | + " movi %[err], %[efault] \n" \ |
---|
138 | 137 | " _j 2f \n" |
---|
139 | 138 | |
---|
140 | 139 | #define __check_align_4 \ |
---|
141 | | - " _bbsi.l %3, 0, 0f \n" \ |
---|
142 | | - " _bbci.l %3, 1, 1f \n" \ |
---|
143 | | - "0: movi %0, %4 \n" \ |
---|
| 140 | + " _bbsi.l %[mem] * 0, 0f \n" \ |
---|
| 141 | + " _bbci.l %[mem] * 0 + 1, 1f \n" \ |
---|
| 142 | + "0: movi %[err], %[efault] \n" \ |
---|
144 | 143 | " _j 2f \n" |
---|
145 | 144 | |
---|
146 | 145 | |
---|
.. | .. |
---|
152 | 151 | * WARNING: If you modify this macro at all, verify that the |
---|
153 | 152 | * __check_align_* macros still work. |
---|
154 | 153 | */ |
---|
155 | | -#define __put_user_asm(x, addr, err, align, insn, cb) \ |
---|
| 154 | +#define __put_user_asm(x_, addr_, err_, align, insn, cb)\ |
---|
156 | 155 | __asm__ __volatile__( \ |
---|
157 | 156 | __check_align_##align \ |
---|
158 | | - "1: "insn" %2, %3, 0 \n" \ |
---|
| 157 | + "1: "insn" %[x], %[mem] \n" \ |
---|
159 | 158 | "2: \n" \ |
---|
160 | 159 | " .section .fixup,\"ax\" \n" \ |
---|
161 | 160 | " .align 4 \n" \ |
---|
162 | | - "4: \n" \ |
---|
163 | | - " .long 2b \n" \ |
---|
| 161 | + " .literal_position \n" \ |
---|
164 | 162 | "5: \n" \ |
---|
165 | | - " l32r %1, 4b \n" \ |
---|
166 | | - " movi %0, %4 \n" \ |
---|
167 | | - " jx %1 \n" \ |
---|
| 163 | + " movi %[tmp], 2b \n" \ |
---|
| 164 | + " movi %[err], %[efault] \n" \ |
---|
| 165 | + " jx %[tmp] \n" \ |
---|
168 | 166 | " .previous \n" \ |
---|
169 | 167 | " .section __ex_table,\"a\" \n" \ |
---|
170 | 168 | " .long 1b, 5b \n" \ |
---|
171 | 169 | " .previous" \ |
---|
172 | | - :"=r" (err), "=r" (cb) \ |
---|
173 | | - :"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err)) |
---|
| 170 | + :[err] "+r"(err_), [tmp] "=r"(cb), [mem] "=m"(*(addr_)) \ |
---|
| 171 | + :[x] "r"(x_), [efault] "i"(-EFAULT)) |
---|
174 | 172 | |
---|
175 | 173 | #define __get_user_nocheck(x, ptr, size) \ |
---|
176 | 174 | ({ \ |
---|
177 | | - long __gu_err, __gu_val; \ |
---|
178 | | - __get_user_size(__gu_val, (ptr), (size), __gu_err); \ |
---|
179 | | - (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
---|
| 175 | + long __gu_err; \ |
---|
| 176 | + __get_user_size((x), (ptr), (size), __gu_err); \ |
---|
180 | 177 | __gu_err; \ |
---|
181 | 178 | }) |
---|
182 | 179 | |
---|
183 | 180 | #define __get_user_check(x, ptr, size) \ |
---|
184 | 181 | ({ \ |
---|
185 | | - long __gu_err = -EFAULT, __gu_val = 0; \ |
---|
186 | | - const __typeof__(*(ptr)) *__gu_addr = (ptr); \ |
---|
187 | | - if (access_ok(VERIFY_READ, __gu_addr, size)) \ |
---|
188 | | - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
---|
189 | | - (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
---|
| 182 | + long __gu_err = -EFAULT; \ |
---|
| 183 | + const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
---|
| 184 | + if (access_ok(__gu_addr, size)) \ |
---|
| 185 | + __get_user_size((x), __gu_addr, (size), __gu_err); \ |
---|
| 186 | + else \ |
---|
| 187 | + (x) = (__typeof__(*(ptr)))0; \ |
---|
190 | 188 | __gu_err; \ |
---|
191 | 189 | }) |
---|
192 | 190 | |
---|
.. | .. |
---|
200 | 198 | case 1: __get_user_asm(x, ptr, retval, 1, "l8ui", __cb); break;\ |
---|
201 | 199 | case 2: __get_user_asm(x, ptr, retval, 2, "l16ui", __cb); break;\ |
---|
202 | 200 | case 4: __get_user_asm(x, ptr, retval, 4, "l32i", __cb); break;\ |
---|
203 | | - case 8: retval = __copy_from_user(&x, ptr, 8); break; \ |
---|
204 | | - default: (x) = __get_user_bad(); \ |
---|
| 201 | + case 8: { \ |
---|
| 202 | + u64 __x; \ |
---|
| 203 | + if (unlikely(__copy_from_user(&__x, ptr, 8))) { \ |
---|
| 204 | + retval = -EFAULT; \ |
---|
| 205 | + (x) = (__typeof__(*(ptr)))0; \ |
---|
| 206 | + } else { \ |
---|
| 207 | + (x) = *(__force __typeof__(*(ptr)) *)&__x; \ |
---|
| 208 | + } \ |
---|
| 209 | + break; \ |
---|
| 210 | + } \ |
---|
| 211 | + default: \ |
---|
| 212 | + (x) = (__typeof__(*(ptr)))0; \ |
---|
| 213 | + __get_user_bad(); \ |
---|
205 | 214 | } \ |
---|
206 | 215 | } while (0) |
---|
207 | 216 | |
---|
.. | .. |
---|
210 | 219 | * WARNING: If you modify this macro at all, verify that the |
---|
211 | 220 | * __check_align_* macros still work. |
---|
212 | 221 | */ |
---|
213 | | -#define __get_user_asm(x, addr, err, align, insn, cb) \ |
---|
214 | | -__asm__ __volatile__( \ |
---|
215 | | - __check_align_##align \ |
---|
216 | | - "1: "insn" %2, %3, 0 \n" \ |
---|
217 | | - "2: \n" \ |
---|
218 | | - " .section .fixup,\"ax\" \n" \ |
---|
219 | | - " .align 4 \n" \ |
---|
220 | | - "4: \n" \ |
---|
221 | | - " .long 2b \n" \ |
---|
222 | | - "5: \n" \ |
---|
223 | | - " l32r %1, 4b \n" \ |
---|
224 | | - " movi %2, 0 \n" \ |
---|
225 | | - " movi %0, %4 \n" \ |
---|
226 | | - " jx %1 \n" \ |
---|
227 | | - " .previous \n" \ |
---|
228 | | - " .section __ex_table,\"a\" \n" \ |
---|
229 | | - " .long 1b, 5b \n" \ |
---|
230 | | - " .previous" \ |
---|
231 | | - :"=r" (err), "=r" (cb), "=r" (x) \ |
---|
232 | | - :"r" (addr), "i" (-EFAULT), "0" (err)) |
---|
| 222 | +#define __get_user_asm(x_, addr_, err_, align, insn, cb) \ |
---|
| 223 | +do { \ |
---|
| 224 | + u32 __x = 0; \ |
---|
| 225 | + __asm__ __volatile__( \ |
---|
| 226 | + __check_align_##align \ |
---|
| 227 | + "1: "insn" %[x], %[mem] \n" \ |
---|
| 228 | + "2: \n" \ |
---|
| 229 | + " .section .fixup,\"ax\" \n" \ |
---|
| 230 | + " .align 4 \n" \ |
---|
| 231 | + " .literal_position \n" \ |
---|
| 232 | + "5: \n" \ |
---|
| 233 | + " movi %[tmp], 2b \n" \ |
---|
| 234 | + " movi %[err], %[efault] \n" \ |
---|
| 235 | + " jx %[tmp] \n" \ |
---|
| 236 | + " .previous \n" \ |
---|
| 237 | + " .section __ex_table,\"a\" \n" \ |
---|
| 238 | + " .long 1b, 5b \n" \ |
---|
| 239 | + " .previous" \ |
---|
| 240 | + :[err] "+r"(err_), [tmp] "=r"(cb), [x] "+r"(__x) \ |
---|
| 241 | + :[mem] "m"(*(addr_)), [efault] "i"(-EFAULT)); \ |
---|
| 242 | + (x_) = (__force __typeof__(*(addr_)))__x; \ |
---|
| 243 | +} while (0) |
---|
233 | 244 | |
---|
234 | 245 | |
---|
235 | 246 | /* |
---|
.. | .. |
---|
261 | 272 | */ |
---|
262 | 273 | |
---|
263 | 274 | static inline unsigned long |
---|
264 | | -__xtensa_clear_user(void *addr, unsigned long size) |
---|
| 275 | +__xtensa_clear_user(void __user *addr, unsigned long size) |
---|
265 | 276 | { |
---|
266 | | - if (!__memset(addr, 0, size)) |
---|
| 277 | + if (!__memset((void __force *)addr, 0, size)) |
---|
267 | 278 | return size; |
---|
268 | 279 | return 0; |
---|
269 | 280 | } |
---|
270 | 281 | |
---|
271 | 282 | static inline unsigned long |
---|
272 | | -clear_user(void *addr, unsigned long size) |
---|
| 283 | +clear_user(void __user *addr, unsigned long size) |
---|
273 | 284 | { |
---|
274 | | - if (access_ok(VERIFY_WRITE, addr, size)) |
---|
| 285 | + if (access_ok(addr, size)) |
---|
275 | 286 | return __xtensa_clear_user(addr, size); |
---|
276 | 287 | return size ? -EFAULT : 0; |
---|
277 | 288 | } |
---|
.. | .. |
---|
281 | 292 | |
---|
282 | 293 | #ifndef CONFIG_GENERIC_STRNCPY_FROM_USER |
---|
283 | 294 | |
---|
284 | | -extern long __strncpy_user(char *, const char *, long); |
---|
| 295 | +extern long __strncpy_user(char *dst, const char __user *src, long count); |
---|
285 | 296 | |
---|
286 | 297 | static inline long |
---|
287 | | -strncpy_from_user(char *dst, const char *src, long count) |
---|
| 298 | +strncpy_from_user(char *dst, const char __user *src, long count) |
---|
288 | 299 | { |
---|
289 | | - if (access_ok(VERIFY_READ, src, 1)) |
---|
| 300 | + if (access_ok(src, 1)) |
---|
290 | 301 | return __strncpy_user(dst, src, count); |
---|
291 | 302 | return -EFAULT; |
---|
292 | 303 | } |
---|
.. | .. |
---|
297 | 308 | /* |
---|
298 | 309 | * Return the size of a string (including the ending 0!) |
---|
299 | 310 | */ |
---|
300 | | -extern long __strnlen_user(const char *, long); |
---|
| 311 | +extern long __strnlen_user(const char __user *str, long len); |
---|
301 | 312 | |
---|
302 | | -static inline long strnlen_user(const char *str, long len) |
---|
| 313 | +static inline long strnlen_user(const char __user *str, long len) |
---|
303 | 314 | { |
---|
304 | | - unsigned long top = __kernel_ok ? ~0UL : TASK_SIZE - 1; |
---|
305 | | - |
---|
306 | | - if ((unsigned long)str > top) |
---|
| 315 | + if (!access_ok(str, 1)) |
---|
307 | 316 | return 0; |
---|
308 | 317 | return __strnlen_user(str, len); |
---|
309 | 318 | } |
---|