On Wed, 13 May 2026 16:19:16 -0400
Rik van Riel <[email protected]> wrote:

> perf_ftrace_function_unregister() unconditionally calls
> unregister_ftrace_function() without checking whether the ftrace_ops
> was ever successfully registered. This triggers a WARN_ON in
> __unregister_ftrace_function() when the ops doesn't have
> FTRACE_OPS_FL_ENABLED set.
> 
> This can happen during perf_event_alloc() error cleanup when
> perf_trace_destroy() is called via __free_event() on an event whose
> ftrace_ops registration failed or was already torn down by
> perf_try_init_event()'s err_destroy path.
> 
> The call path is:
>   perf_event_alloc() error cleanup
>     -> __free_event()
>       -> event->destroy() [tp_perf_event_destroy]
>         -> perf_trace_destroy()
>           -> perf_trace_event_close()
>             -> TRACE_REG_PERF_CLOSE
>               -> perf_ftrace_function_unregister()
>                 -> unregister_ftrace_function()
>                   -> __unregister_ftrace_function()
>                     -> WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED))
> 
> Fix this by checking FTRACE_OPS_FL_ENABLED before attempting to
> unregister. If the ops is not enabled, just free the filter and
> return success.
> 
> Assisted-by: Claude:claude-opus-4.7 syzkaller
> Signed-off-by: Rik van Riel <[email protected]>

Looks good to me.

Acked-by: Masami Hiramatsu (Google) <[email protected]>
Fixes: ced39002f5ea ("ftrace, perf: Add support to use function tracepoint in 
perf")

Thanks,

> ---
>  kernel/trace/trace_event_perf.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
> index a6bb7577e8c5..58e1b427b576 100644
> --- a/kernel/trace/trace_event_perf.c
> +++ b/kernel/trace/trace_event_perf.c
> @@ -497,7 +497,11 @@ static int perf_ftrace_function_register(struct 
> perf_event *event)
>  static int perf_ftrace_function_unregister(struct perf_event *event)
>  {
>       struct ftrace_ops *ops = &event->ftrace_ops;
> -     int ret = unregister_ftrace_function(ops);
> +     int ret = 0;
> +
> +     if (ops->flags & FTRACE_OPS_FL_ENABLED)
> +             ret = unregister_ftrace_function(ops);
> +
>       ftrace_free_filter(ops);
>       return ret;
>  }
> -- 
> 2.52.0
> 
> 


-- 
Masami Hiramatsu (Google) <[email protected]>

Reply via email to