]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
perf dwarf-aux: Fix libdw segmentation fault in cu_walk_functions_at
authorIan Rogers <irogers@google.com>
Mon, 4 May 2026 08:12:19 +0000 (01:12 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 6 May 2026 00:47:32 +0000 (21:47 -0300)
A segmentation fault was observed in `libdw` when running `perf kmem`
with `--page stat` on some workloads. The crash occurred deep inside
`libdw` (specifically in `dwarf_child` and `dwarf_diename`) when
processing DWARF information.

The root cause was improper error handling of `dwarf_getfuncs` in
`die_find_realfunc` and `die_find_tailfunc`.

`dwarf_getfuncs` returns:
 - `0` on success (when all functions have been processed).
 - A positive offset if the callback aborts early (e.g., via
   `DWARF_CB_ABORT` when a match is found).
 - `-1` on error.

The original code used `if (!dwarf_getfuncs(...)) return NULL;`. On
error (`-1`), `!-1` evaluates to `0` (false), bypassing the error
check. Execution then proceeded as if a match was found, returning
uninitialized stack memory (`die_mem`) to the caller
(`cu_walk_functions_at`). When `cu_walk_functions_at` passed this
uninitialized memory to `libdw` via `dwarf_diename`, it caused a
segmentation fault.

Fix this by correcting the error check to `if (dwarf_getfuncs(...) <= 0)`.

Fixes: e0d153c69040 ("perf-probe: Move dwarf library routines to dwarf-aux.{c, h}")
Fixes: d4c537e6bf86 ("perf probe: Ignore tail calls to probed functions")
Assisted-by: Gemini-CLI:Google Gemini 3
Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Zecheng Li <zli94@ncsu.edu>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/dwarf-aux.c

index 92db2fccc788abb970ff452d217e43f9ec6e9121..109a166a6d19cedbbb03bbbaae7c2e6f3016a894 100644 (file)
@@ -171,7 +171,6 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
        }
 
        return ret;
-
 }
 
 /**
@@ -620,7 +619,7 @@ Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
        ad.addr = addr;
        ad.die_mem = die_mem;
        /* dwarf_getscopes can't find subprogram. */
-       if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
+       if (dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0) <= 0)
                return NULL;
        else
                return die_mem;
@@ -659,7 +658,7 @@ Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
        ad.addr = addr;
        ad.die_mem = die_mem;
        /* dwarf_getscopes can't find subprogram. */
-       if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
+       if (dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0) <= 0)
                return NULL;
        else
                return die_mem;