Creating a tracefs instance can allocate private tracer nodes, copied flags and option arrays before trace_array_create_dir() returns. If a later allocation fails, trace_array_create_systems() jumps to out_free_tr and frees the trace_array without releasing those private allocations. The failed instance is never registered, so normal removal cannot reclaim them.
Free the tracer nodes and option arrays when trace_array_create_dir() fails, then continue through the existing trace_array cleanup. Earlier failures still use out_free_tr because the tracer list is not yet initialized there. Signed-off-by: Baek Kyu, Kim <[email protected]> --- Tested under ARM64 QEMU/KVM through tracefs instance mkdir with failslab targeting tracer flags, a later tracer node and option-array growth. The baseline retained one or four private allocations after the failed mkdir; the patched kernel retained none. Normal instance option read/write and removal also passed. kernel/trace/trace.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 97a058623f94..ad68a39a1161 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -8751,7 +8751,7 @@ trace_array_create_systems(const char *name, const char *systems, if (trace_instance_dir) { ret = trace_array_create_dir(tr); if (ret) - goto out_free_tr; + goto out_free_tracers; } else __trace_early_add_events(tr); @@ -8761,6 +8761,11 @@ trace_array_create_systems(const char *name, const char *systems, return tr; + out_free_tracers: + free_tracers(tr); + for (int i = 0; i < tr->nr_topts; i++) + kfree(tr->topts[i].topts); + kfree(tr->topts); out_free_tr: ftrace_free_ftrace_ops(tr); free_trace_buffers(tr);
