usercopy: Allow boot cmdline disabling of hardening
[sfrench/cifs-2.6.git] / mm / usercopy.c
index e9e9325f7638db115151e953fd66e7ae063a8f2f..852eb4e53f06ede4ffd39988f3aa12aa43bd88e3 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/sched/task.h>
 #include <linux/sched/task_stack.h>
 #include <linux/thread_info.h>
+#include <linux/atomic.h>
+#include <linux/jump_label.h>
 #include <asm/sections.h>
 
 /*
@@ -240,6 +242,8 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
        }
 }
 
+static DEFINE_STATIC_KEY_FALSE_RO(bypass_usercopy_checks);
+
 /*
  * Validates that the given object is:
  * - not bogus address
@@ -248,6 +252,9 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
  */
 void __check_object_size(const void *ptr, unsigned long n, bool to_user)
 {
+       if (static_branch_unlikely(&bypass_usercopy_checks))
+               return;
+
        /* Skip all tests if size is zero. */
        if (!n)
                return;
@@ -279,3 +286,21 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
        check_kernel_text_object((const unsigned long)ptr, n, to_user);
 }
 EXPORT_SYMBOL(__check_object_size);
+
+static bool enable_checks __initdata = true;
+
+static int __init parse_hardened_usercopy(char *str)
+{
+       return strtobool(str, &enable_checks);
+}
+
+__setup("hardened_usercopy=", parse_hardened_usercopy);
+
+static int __init set_hardened_usercopy(void)
+{
+       if (enable_checks == false)
+               static_branch_enable(&bypass_usercopy_checks);
+       return 1;
+}
+
+late_initcall(set_hardened_usercopy);