On Thu, Jun 25, 2026 at 06:02:03PM +0000, Tristan Madani wrote: > From: Tristan Madani <[email protected]> > > user_event_enabler_destroy() removes the enabler from an RCU-protected > list via list_del_rcu() and then immediately frees it with kfree(). This > can result in a concurrent reader in user_event_enabler_dup() accessing > stale memory during fork, since the enabler list is traversed under > rcu_read_lock(). > > The ENABLE_VAL_FREEING_BIT check in user_event_enabler_dup() is not > sufficient to prevent this, as the enabler can be freed between the bit > test and the subsequent pointer dereference. > > Use kfree_rcu() to defer the free until after all RCU read-side critical > sections complete. > > Fixes: 7235759084a4 ("tracing/user_events: Use remote writes for event > enablement") > Cc: [email protected] > Signed-off-by: Tristan Madani <[email protected]> > --- > kernel/trace/trace_events_user.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/kernel/trace/trace_events_user.c > b/kernel/trace/trace_events_user.c > index c4ba484f7b38b..72bcb429eb4f3 100644 > --- a/kernel/trace/trace_events_user.c > +++ b/kernel/trace/trace_events_user.c > @@ -109,6 +109,7 @@ struct user_event_enabler { > > /* Track enable bit, flags, etc. Aligned for bitops. */ > unsigned long values; > + struct rcu_head rcu; > }; > > /* Bits 0-5 are for the bit to update upon enable/disable (0-63 allowed) */ > @@ -404,7 +405,7 @@ static void user_event_enabler_destroy(struct > user_event_enabler *enabler, > /* No longer tracking the event via the enabler */ > user_event_put(enabler->event, locked); > > - kfree(enabler); > + kfree_rcu(enabler, rcu); > } > > static int user_event_mm_fault_in(struct user_event_mm *mm, unsigned long > uaddr, > -- > 2.47.3
See [1] as there are more issues than simply the enabler being freed via RCU, there are lifetime aspects of the underlying user_event. Thanks, -Beau 1. https://lore.kernel.org/linux-trace-kernel/[email protected]/
