[RHEL7,COMMIT] ms/extable: Enable RCU if it is not watching in kernel_text_address()

Submitted by Vasily Averin on Dec. 3, 2020, 12:31 p.m.


Message ID 202012031231.0B3CVP7Z011050@vz7build.vvs.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Vasily Averin Dec. 3, 2020, 12:31 p.m.
The commit is pushed to "branch-rh7-3.10.0-1160.6.1.vz7.171.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.6.1.vz7.171.2
commit e451ccff8b8e1bd549a1e91fe1a79832d2243fa5
Author: Vasily Averin <vvs@virtuozzo.com>
Date:   Thu Dec 3 15:31:25 2020 +0300

    ms/extable: Enable RCU if it is not watching in kernel_text_address()
    Author: Steven Rostedt (VMware) <rostedt@goodmis.org>
    backported upstream commit e8cac8b1d10589be45671a5ade0926a639b543b7
        extable: Enable RCU if it is not watching in kernel_text_address()
        If kernel_text_address() is called when RCU is not watching, it can cause an
        RCU bug because is_module_text_address(), the is_kprobe_*insn_slot()
        and is_bpf_text_address() functions require the use of RCU.
        Only enable RCU if it is not currently watching before it calls
        is_module_text_address(). The use of rcu_nmi_enter() is used to enable RCU
        because kernel_text_address() can happen pretty much anywhere (like an NMI),
        and even from within an NMI. It is called via save_stack_trace() that can be
        called by any WARN() or tracing function, which can happen while RCU is not
        watching (for example, going to or coming from idle, or during CPU take down
        or bring up).
        Cc: stable@vger.kernel.org
        Fixes: 0be964be0 ("module: Sanitize RCU usage and locking")
        Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
        Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
    backport changes:
         context fixes, RH7/vz7 kernel does not have
          is_ftrace_trampoline() and is_kprobe_*() checks
    Signed-off-by: Vasily Averin <vvs@virtuozzo.com>
 kernel/extable.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/kernel/extable.c b/kernel/extable.c
index 4f1a5d2..e8de57b 100644
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -120,13 +120,38 @@  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_bpf_text_address(addr))
-		return 1;
-	return 0;
+		goto out;
+	ret = 0;
+	if (no_rcu)
+		rcu_nmi_exit();
+	return ret;