Skip to content

Commit 0cd575c

Browse files
anakryikoIngo Molnar
authored andcommitted
uprobes: Avoid false-positive lockdep splat on CONFIG_PREEMPT_RT=y in the ri_timer() uprobe timer callback, use raw_write_seqcount_*()
Avoid a false-positive lockdep warning in the CONFIG_PREEMPT_RT=y configuration when using write_seqcount_begin() in the uprobe timer callback by using raw_write_* APIs. Uprobe's use of timer callback is guaranteed to not race with itself for a given uprobe_task, and as such seqcount's insistence on having preemption disabled on the writer side is irrelevant. So switch to raw_ variants of seqcount API instead of disabling preemption unnecessarily. Also, point out in the comments more explicitly why we use seqcount despite our reader side being rather simple and never retrying. We favor well-maintained kernel primitive in favor of open-coding our own memory barriers. Fixes: 8622e45 ("uprobes: Reuse return_instances between multiple uretprobes within task") Reported-by: Alexei Starovoitov <ast@kernel.org> Suggested-by: Sebastian Siewior <bigeasy@linutronix.de> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Acked-by: Oleg Nesterov <oleg@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: stable@kernel.org Link: https://lore.kernel.org/r/20250404194848.2109539-1-andrii@kernel.org
1 parent 0ba3a4a commit 0cd575c

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

kernel/events/uprobes.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1956,6 +1956,9 @@ static void free_ret_instance(struct uprobe_task *utask,
19561956
* to-be-reused return instances for future uretprobes. If ri_timer()
19571957
* happens to be running right now, though, we fallback to safety and
19581958
* just perform RCU-delated freeing of ri.
1959+
* Admittedly, this is a rather simple use of seqcount, but it nicely
1960+
* abstracts away all the necessary memory barriers, so we use
1961+
* a well-supported kernel primitive here.
19591962
*/
19601963
if (raw_seqcount_try_begin(&utask->ri_seqcount, seq)) {
19611964
/* immediate reuse of ri without RCU GP is OK */
@@ -2016,12 +2019,20 @@ static void ri_timer(struct timer_list *timer)
20162019
/* RCU protects return_instance from freeing. */
20172020
guard(rcu)();
20182021

2019-
write_seqcount_begin(&utask->ri_seqcount);
2022+
/*
2023+
* See free_ret_instance() for notes on seqcount use.
2024+
* We also employ raw API variants to avoid lockdep false-positive
2025+
* warning complaining about enabled preemption. The timer can only be
2026+
* invoked once for a uprobe_task. Therefore there can only be one
2027+
* writer. The reader does not require an even sequence count to make
2028+
* progress, so it is OK to remain preemptible on PREEMPT_RT.
2029+
*/
2030+
raw_write_seqcount_begin(&utask->ri_seqcount);
20202031

20212032
for_each_ret_instance_rcu(ri, utask->return_instances)
20222033
hprobe_expire(&ri->hprobe, false);
20232034

2024-
write_seqcount_end(&utask->ri_seqcount);
2035+
raw_write_seqcount_end(&utask->ri_seqcount);
20252036
}
20262037

20272038
static struct uprobe_task *alloc_utask(void)

0 commit comments

Comments
 (0)