Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cris: buggered copy_from_user/copy_to_user/clear_user

* copy_from_user() on access_ok() failure ought to zero the destination
* none of those primitives should skip the access_ok() check in case of
small constant size.

Cc: stable@vger.kernel.org
Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Al Viro eb47e029 9ad18b75

+32 -39
+32 -39
arch/cris/include/asm/uaccess.h
··· 194 194 extern unsigned long __copy_user_zeroing(void *to, const void __user *from, unsigned long n); 195 195 extern unsigned long __do_clear_user(void __user *to, unsigned long n); 196 196 197 - static inline unsigned long 198 - __generic_copy_to_user(void __user *to, const void *from, unsigned long n) 199 - { 200 - if (access_ok(VERIFY_WRITE, to, n)) 201 - return __copy_user(to, from, n); 202 - return n; 203 - } 204 - 205 - static inline unsigned long 206 - __generic_copy_from_user(void *to, const void __user *from, unsigned long n) 207 - { 208 - if (access_ok(VERIFY_READ, from, n)) 209 - return __copy_user_zeroing(to, from, n); 210 - return n; 211 - } 212 - 213 - static inline unsigned long 214 - __generic_clear_user(void __user *to, unsigned long n) 215 - { 216 - if (access_ok(VERIFY_WRITE, to, n)) 217 - return __do_clear_user(to, n); 218 - return n; 219 - } 220 - 221 197 static inline long 222 198 __strncpy_from_user(char *dst, const char __user *src, long count) 223 199 { ··· 258 282 else if (n == 24) 259 283 __asm_copy_from_user_24(to, from, ret); 260 284 else 261 - ret = __generic_copy_from_user(to, from, n); 285 + ret = __copy_user_zeroing(to, from, n); 262 286 263 287 return ret; 264 288 } ··· 309 333 else if (n == 24) 310 334 __asm_copy_to_user_24(to, from, ret); 311 335 else 312 - ret = __generic_copy_to_user(to, from, n); 336 + ret = __copy_user(to, from, n); 313 337 314 338 return ret; 315 339 } ··· 342 366 else if (n == 24) 343 367 __asm_clear_24(to, ret); 344 368 else 345 - ret = __generic_clear_user(to, n); 369 + ret = __do_clear_user(to, n); 346 370 347 371 return ret; 348 372 } 349 373 350 374 351 - #define clear_user(to, n) \ 352 - (__builtin_constant_p(n) ? \ 353 - __constant_clear_user(to, n) : \ 354 - __generic_clear_user(to, n)) 375 + static inline size_t clear_user(void __user *to, size_t n) 376 + { 377 + if (unlikely(!access_ok(VERIFY_WRITE, to, n))) 378 + return n; 379 + if (__builtin_constant_p(n)) 380 + return __constant_clear_user(to, n); 381 + else 382 + return __do_clear_user(to, n); 383 + } 355 384 356 - #define copy_from_user(to, from, n) \ 357 - (__builtin_constant_p(n) ? \ 358 - __constant_copy_from_user(to, from, n) : \ 359 - __generic_copy_from_user(to, from, n)) 385 + static inline size_t copy_from_user(void *to, const void __user *from, size_t n) 386 + { 387 + if (unlikely(!access_ok(VERIFY_READ, from, n))) { 388 + memset(to, 0, n); 389 + return n; 390 + } 391 + if (__builtin_constant_p(n)) 392 + return __constant_copy_from_user(to, from, n); 393 + else 394 + return __copy_user_zeroing(to, from, n); 395 + } 360 396 361 - #define copy_to_user(to, from, n) \ 362 - (__builtin_constant_p(n) ? \ 363 - __constant_copy_to_user(to, from, n) : \ 364 - __generic_copy_to_user(to, from, n)) 397 + static inline size_t copy_to_user(void __user *to, const void *from, size_t n) 398 + { 399 + if (unlikely(!access_ok(VERIFY_WRITE, to, n))) 400 + return n; 401 + if (__builtin_constant_p(n)) 402 + return __constant_copy_to_user(to, from, n); 403 + else 404 + return __copy_user(to, from, n); 405 + } 365 406 366 407 /* We let the __ versions of copy_from/to_user inline, because they're often 367 408 * used in fast paths and have only a small space overhead.