@@ -356,22 +356,6 @@ do {
\
-EFAULT; \
})
-static inline void check_obj_in_unused_stack(const void *obj,
unsigned long len)
-{
- unsigned long stack = (unsigned long)task_stack_page(current);
-
- if (__builtin_constant_p(len) ||
!IS_ENABLED(CONFIG_HARDENED_USERCOPY) || !len)
- return;
-
- /*
- * If current_stack_pointer is on the task stack, obj must not lie
- * between current_stack_pointer and the last stack address.
- */
- if ((current_stack_pointer & ~(THREAD_SIZE-1)) == stack)
- BUG_ON(stack <= (unsigned long)obj &&
- (unsigned long)obj < current_stack_pointer);
-}
-
extern unsigned long __must_check __arch_copy_from_user(void *to,
const void __user *from, unsigned long n);
extern unsigned long __must_check __arch_copy_to_user(void __user
*to, const void *from, unsigned long n);
extern unsigned long __must_check __copy_in_user(void __user *to,
const void __user *from, unsigned long n);
@@ -380,16 +364,14 @@ extern unsigned long __must_check
__clear_user(void __user *addr, unsigned long
static inline unsigned long __must_check __copy_from_user(void *to,
const void __user *from, unsigned long n)
{
kasan_check_write(to, n);
- check_obj_in_unused_stack(to, n);
- check_object_size(to, n, false);
+ check_object_size(to, n, current_stack_pointer, false);
return __arch_copy_from_user(to, from, n);
}
static inline unsigned long __must_check __copy_to_user(void __user
*to, const void *from, unsigned long n)
{
kasan_check_read(from, n);
- check_obj_in_unused_stack(from, n);
- check_object_size(from, n, true);
+ check_object_size(from, n, current_stack_pointer, true);
return __arch_copy_to_user(to, from, n);
}
@@ -399,8 +381,7 @@ static inline unsigned long __must_check
copy_from_user(void *to, const void __u
kasan_check_write(to, n);
if (access_ok(VERIFY_READ, from, n)) {
- check_obj_in_unused_stack(to, n);
- check_object_size(to, n, false);
+ check_object_size(to, n, current_stack_pointer, false);
res = __arch_copy_from_user(to, from, n);
}
if (unlikely(res))
@@ -413,8 +394,7 @@ static inline unsigned long __must_check
copy_to_user(void __user *to, const voi
kasan_check_read(from, n);
if (access_ok(VERIFY_WRITE, to, n)) {
- check_obj_in_unused_stack(from, n);
- check_object_size(from, n, true);
+ check_object_size(from, n, current_stack_pointer, true);
n = __arch_copy_to_user(to, from, n);
}
return n;
@@ -94,17 +94,17 @@ static inline enum stack_type
arch_within_stack_frames(const void * const stack,
#ifdef CONFIG_HARDENED_USERCOPY
extern void __check_object_size(const void *ptr, unsigned long n,
- bool to_user);
+ unsigned long sp, bool to_user);
static __always_inline void check_object_size(const void *ptr, unsigned long n,
- bool to_user)
+ unsigned long sp, bool to_user)
{
if (!__builtin_constant_p(n))
- __check_object_size(ptr, n, to_user);
+ __check_object_size(ptr, n, sp, to_user);
}
#else
static inline void check_object_size(const void *ptr, unsigned long n,
- bool to_user)
+ unsigned long sp, bool to_user)
{ }
#endif /* CONFIG_HARDENED_USERCOPY */
@@ -112,7 +112,7 @@ long strncpy_from_user(char *dst, const char
__user *src, long count)
long retval;
kasan_check_write(dst, count);
- check_object_size(dst, count, false);
+ check_object_size(dst, count, current_stack_pointer, false);
user_access_begin();
retval = do_strncpy_from_user(dst, src, count, max);
user_access_end();
@@ -29,7 +29,8 @@
* GOOD_STACK: fully on the stack (when can't do frame-checking)
* BAD_STACK: error condition (invalid stack position or bad stack frame)
*/
-static noinline int check_stack_object(const void *obj, unsigned long len)
+static noinline int check_stack_object(const void *obj, unsigned long len,
+ unsigned long usercopy_sp)
{
const void * const stack = task_stack_page(current);
const void * const stackend = stack + THREAD_SIZE;
@@ -44,7 +45,7 @@ static noinline int check_stack_object(const void
*obj, unsigned long len)
* the check above means at least one end is within the stack,
* so if this check fails, the other end is outside the stack).
*/
- if (obj < stack || stackend < obj + len)
+ if (obj < usercopy_sp || stackend < obj + len)
return BAD_STACK;