]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/extable.c
userns: prevent speculative execution
[mirror_ubuntu-artful-kernel.git] / kernel / extable.c
index 38c2412401a1b118d53d3cff92eba24753134aed..9aa1cc41ecf79c8c2cc5fb9dbd3fbd418025c0dd 100644 (file)
@@ -102,15 +102,7 @@ int core_kernel_data(unsigned long addr)
 
 int __kernel_text_address(unsigned long addr)
 {
-       if (core_kernel_text(addr))
-               return 1;
-       if (is_module_text_address(addr))
-               return 1;
-       if (is_ftrace_trampoline(addr))
-               return 1;
-       if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
-               return 1;
-       if (is_bpf_text_address(addr))
+       if (kernel_text_address(addr))
                return 1;
        /*
         * There might be init symbols in saved stacktraces.
@@ -127,17 +119,42 @@ int __kernel_text_address(unsigned long addr)
 
 int kernel_text_address(unsigned long addr)
 {
+       bool no_rcu;
+       int ret = 1;
+
        if (core_kernel_text(addr))
                return 1;
+
+       /*
+        * If a stack dump happens while RCU is not watching, then
+        * RCU needs to be notified that it requires to start
+        * watching again. This can happen either by tracing that
+        * triggers a stack trace, or a WARN() that happens during
+        * coming back from idle, or cpu on or offlining.
+        *
+        * is_module_text_address() as well as the kprobe slots
+        * and is_bpf_text_address() require RCU to be watching.
+        */
+       no_rcu = !rcu_is_watching();
+
+       /* Treat this like an NMI as it can happen anywhere */
+       if (no_rcu)
+               rcu_nmi_enter();
+
        if (is_module_text_address(addr))
-               return 1;
+               goto out;
        if (is_ftrace_trampoline(addr))
-               return 1;
+               goto out;
        if (is_kprobe_optinsn_slot(addr) || is_kprobe_insn_slot(addr))
-               return 1;
+               goto out;
        if (is_bpf_text_address(addr))
-               return 1;
-       return 0;
+               goto out;
+       ret = 0;
+out:
+       if (no_rcu)
+               rcu_nmi_exit();
+
+       return ret;
 }
 
 /*