usercopy: Check valid lifetime via stack depth
[linux-block.git] / mm / usercopy.c
index d0d268135d96d6494949bb5eec702f7365ddc86a..5d34c40c16c2233e2d588b57058bfdb1b725d60e 100644 (file)
@@ -29,7 +29,7 @@
  * Returns:
  *     NOT_STACK: not at all on the stack
  *     GOOD_FRAME: fully within a valid stack frame
- *     GOOD_STACK: fully on the stack (when can't do frame-checking)
+ *     GOOD_STACK: within the current stack (when can't frame-check exactly)
  *     BAD_STACK: error condition (invalid stack position or bad stack frame)
  */
 static noinline int check_stack_object(const void *obj, unsigned long len)
@@ -55,6 +55,17 @@ static noinline int check_stack_object(const void *obj, unsigned long len)
        if (ret)
                return ret;
 
+       /* Finally, check stack depth if possible. */
+#ifdef CONFIG_ARCH_HAS_CURRENT_STACK_POINTER
+       if (IS_ENABLED(CONFIG_STACK_GROWSUP)) {
+               if ((void *)current_stack_pointer < obj + len)
+                       return BAD_STACK;
+       } else {
+               if (obj < (void *)current_stack_pointer)
+                       return BAD_STACK;
+       }
+#endif
+
        return GOOD_STACK;
 }
 
@@ -280,7 +291,15 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
                 */
                return;
        default:
-               usercopy_abort("process stack", NULL, to_user, 0, n);
+               usercopy_abort("process stack", NULL, to_user,
+#ifdef CONFIG_ARCH_HAS_CURRENT_STACK_POINTER
+                       IS_ENABLED(CONFIG_STACK_GROWSUP) ?
+                               ptr - (void *)current_stack_pointer :
+                               (void *)current_stack_pointer - ptr,
+#else
+                       0,
+#endif
+                       n);
        }
 
        /* Check for bad heap object. */