hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAA3U5 CVE: NA
---------------------------
Lockdep report that:
WARNING: suspicious RCU usage ./include/linux/rcupdate.h:625 rcu_read_lock() used illegally while idle! other info that might help us debug this:
RCU used illegally from idle CPU! rcu_scheduler_active = 2, debug_locks = 1 RCU used illegally from extended quiescent state! 1 lock held by swapper/0/0: #0: 000000003f648ecc (rcu_read_lock){....}, at: ftrace_location_range+0x0/0x400 kernel/trace/ftrace.c:1326
[...] Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0x125/0x1ae lib/dump_stack.c:117 rcu_read_lock include/linux/rcupdate.h:624 [inline] ftrace_location_range+0x2e4/0x400 kernel/trace/ftrace.c:1613 ftrace_int3_handler+0x47/0x220 arch/x86/kernel/ftrace.c:304 do_int3+0x1d2/0x260 arch/x86/kernel/traps.c:592 int3+0x33/0x40 arch/x86/entry/entry_64.S:1170 [...] default_idle_call+0x3c/0x60 kernel/sched/idle.c:95 cpuidle_idle_call kernel/sched/idle.c:155 [inline] do_idle+0x28a/0x380 kernel/sched/idle.c:257 cpu_startup_entry+0xcb/0xe0 kernel/sched/idle.c:363 start_kernel+0x8bc/0x8fb init/main.c:744 secondary_startup_64+0xb7/0xc0 arch/x86/kernel/head_64.S:243
When function tracer is enabling, an 'int3' will be put at the fentry location of traced function, and before the fentry location being fully replaced as ftrace caller, any calls to the traced function will first redirect to call ftrace caller through ftrace_int3_handler(). When the traced function is called by idle task and rcu_read_lock() is indirectly called in ftrace_int3_handler(), then lockdep will warn that is illegal.
RCU lock is not needed when ftrace_location() is called by ftrace_int3_handler() because that is an atomic context, so add in_atomic() check before hold or release RCU lock.
Fixes: 85b642bd0701 ("ftrace: Fix possible use-after-free issue in ftrace_location()") Signed-off-by: Zheng Yejian zhengyejian1@huawei.com --- kernel/trace/ftrace.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6704150cb655..ad4440da5b78 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1581,7 +1581,12 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end) key.ip = start; key.flags = end; /* overload flags, as it is unsigned long */
- rcu_read_lock(); + /* + * It is in atomic context when called from ftrace_int3_handler(), + * in this case rcu lock is not needed. + */ + if (!in_atomic()) + rcu_read_lock(); for (pg = ftrace_pages_start; pg; pg = pg->next) { if (pg->index == 0 || end < pg->records[0].ip || @@ -1595,7 +1600,8 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end) break; } } - rcu_read_unlock(); + if (!in_atomic()) + rcu_read_unlock();
return ip; }