diff options
Diffstat (limited to 'include/asm-generic/uaccess.h')
-rw-r--r-- | include/asm-generic/uaccess.h | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h index 5dea1fb6979c..6df9b0749671 100644 --- a/include/asm-generic/uaccess.h +++ b/include/asm-generic/uaccess.h | |||
@@ -231,14 +231,18 @@ extern int __put_user_bad(void) __attribute__((noreturn)); | |||
231 | might_fault(); \ | 231 | might_fault(); \ |
232 | access_ok(VERIFY_READ, __p, sizeof(*ptr)) ? \ | 232 | access_ok(VERIFY_READ, __p, sizeof(*ptr)) ? \ |
233 | __get_user((x), (__typeof__(*(ptr)) *)__p) : \ | 233 | __get_user((x), (__typeof__(*(ptr)) *)__p) : \ |
234 | -EFAULT; \ | 234 | ((x) = (__typeof__(*(ptr)))0,-EFAULT); \ |
235 | }) | 235 | }) |
236 | 236 | ||
237 | #ifndef __get_user_fn | 237 | #ifndef __get_user_fn |
238 | static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) | 238 | static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) |
239 | { | 239 | { |
240 | size = __copy_from_user(x, ptr, size); | 240 | size_t n = __copy_from_user(x, ptr, size); |
241 | return size ? -EFAULT : size; | 241 | if (unlikely(n)) { |
242 | memset(x + (size - n), 0, n); | ||
243 | return -EFAULT; | ||
244 | } | ||
245 | return 0; | ||
242 | } | 246 | } |
243 | 247 | ||
244 | #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) | 248 | #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) |
@@ -258,11 +262,13 @@ extern int __get_user_bad(void) __attribute__((noreturn)); | |||
258 | static inline long copy_from_user(void *to, | 262 | static inline long copy_from_user(void *to, |
259 | const void __user * from, unsigned long n) | 263 | const void __user * from, unsigned long n) |
260 | { | 264 | { |
265 | unsigned long res = n; | ||
261 | might_fault(); | 266 | might_fault(); |
262 | if (access_ok(VERIFY_READ, from, n)) | 267 | if (likely(access_ok(VERIFY_READ, from, n))) |
263 | return __copy_from_user(to, from, n); | 268 | res = __copy_from_user(to, from, n); |
264 | else | 269 | if (unlikely(res)) |
265 | return n; | 270 | memset(to + (n - res), 0, res); |
271 | return res; | ||
266 | } | 272 | } |
267 | 273 | ||
268 | static inline long copy_to_user(void __user *to, | 274 | static inline long copy_to_user(void __user *to, |