Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] tracing/user_events: permanent leak of non-persistent event in destroy_user_event() --
commit 426e76d7362e855d5b85cce6bb2e395443a0a474 Author: David Carlier <[email protected]> tracing/user_events: Don't free an event that a dynamic event still references This commit prevents destroy_user_event() from freeing a user_event while a dynamic event still holds a reference on user->call by checking trace_event_dyn_busy(&user->call) and returning -EBUSY. > diff --git a/kernel/trace/trace_events_user.c > b/kernel/trace/trace_events_user.c > index f658c3a77aa7a..49b857a7f1d78 100644 > --- a/kernel/trace/trace_events_user.c > +++ b/kernel/trace/trace_events_user.c > @@ -1506,6 +1506,10 @@ static int destroy_user_event(struct user_event *user) > > lockdep_assert_held(&event_mutex); > > + /* If there is a reference to a dynamic event */ > + if (trace_event_dyn_busy(&user->call)) > + return -EBUSY; [Severity: High] Does returning -EBUSY here cause non-persistent user_event instances to leak and become permanently undeletable if their last reference is dropped while user->call.refcnt is non-zero? When a non-persistent event is created via DIAG_IOCSREG without USER_EVENT_REG_PERSIST, user->refcnt tracks active user and probe references. If a dynamic event consumer holds a reference on user->call (such as an eprobe via find_and_get_event(), a histogram action via trace_get_event_file(), or an enable_event trigger during teardown in event_enable_trigger_free() before trigger_kthread runs enable_trigger_private_data_free()) when the last user->refcnt reference is dropped in user_event_put(), delayed_destroy_user_event() runs: kernel/trace/trace_events_user.c:delayed_destroy_user_event() { ... if (!refcount_dec_and_test(&user->refcnt)) goto out; if (destroy_user_event(user)) { ... pr_warn("user_events: Unable to delete event\n"); refcount_set(&user->refcnt, 1); } out: mutex_unlock(&event_mutex); } Because destroy_user_event() now returns -EBUSY, delayed_destroy_user_event() resets user->refcnt to 1 without setting USER_EVENT_REG_PERSIST in user->reg_flags, and with no owner holding that reference. Once the eprobe or trigger later drops its reference on user->call, how can this user_event ever be freed? 1. Manual deletion via dynamic_events in user_event_free(), via DIAG_IOCSDEL in delete_user_event(), or via dyn_events_release_all() -> user_event_is_busy() all check user_event_last_ref(): kernel/trace/trace_events_user.c:user_event_last_ref() { int last = 0; if (user->reg_flags & USER_EVENT_REG_PERSIST) last = 1; return refcount_read(&user->refcnt) == last; } Because USER_EVENT_REG_PERSIST is not set, user_event_last_ref() requires user->refcnt to be 0, so manual deletion permanently fails with -EBUSY. 2. Re-opening and closing the event increments user->refcnt from 1 to 2 and decrements it back to 1 in user_event_put(), never reaching 0 to re-queue delayed_destroy_user_event(). As a result, the struct user_event, its fields and validators, its tracefs entry, and a current_user_events quota slot appear to be leaked until reboot. -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=1
