Re: [PATCH 06/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path
[email protected] Wed, 05 Aug 2026 15:48:43 +0000
| Newsgroups | org.kernel.vger.linux-perf-users |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [Critical] Unvalidated nr_entry field in JIT_CODE_DEBUG_INFO leads to arbitrary heap out-of-bounds read and write. - [High] Insecure file creation in jit_emit_elf allows arbitrary file overwrite via symlink attacks, potentially leading to privilege escalation. -- --- Patch [6]: [PATCH 06/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path --- commit 9c3ece5485fc42d2bde29b52e999638dd26c389f Author: Arnaldo Carvalho de Melo <[email protected]> perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path If the malloc() for the initial read buffer fails, jit_open() jumps to the error label which calls funlockfile(jd->in). However, flockfile() is called later in the function, so at this point the stream was never locked. Calling funlockfile() on an unlocked stream is undefined behavior per POSIX. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index fd11e07bf00b7..c3f11d1c1d76d 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -155,7 +155,7 @@ jit_open(struct jit_buf_desc *jd, const char *name) > > buf = malloc(bsz); > if (!buf) > - goto error; > + goto error_noflock; > > /* > * protect from writer modifying the file while we are reading it > @@ -244,8 +244,9 @@ jit_open(struct jit_buf_desc *jd, const char *name) > > return 0; > error: > - free(buf); > funlockfile(jd->in); > +error_noflock: > + free(buf); > fclose(jd->in); > return retval; > } [Severity: High] This is a pre-existing issue, but I noticed an insecure file creation bug in jit_emit_elf() while reviewing this file: tools/perf/util/jitdump.c:jit_emit_elf() { ... nsinfo__mountns_enter(jd->nsi, &nsc); fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); saved_errno = errno; nsinfo__mountns_exit(&nsc); ... } The open() call truncates and writes to the file, but lacks O_EXCL or O_NOFOLLOW. Does this leave the file creation vulnerable to symlink-based file overwrite attacks? If a local attacker pre-creates a symlink matching the expected .so output filename (e.g., jitted-<pid>-<count>.so) in a world-writable directory (like /tmp), could they point it to a sensitive system file such as /etc/shadow? When a privileged user runs perf inject on the attacker's perf.data file, could the target file be truncated and overwritten with an ELF binary containing jitted code? [Severity: Critical] This is a pre-existing issue, but the nr_entry field is completely unvalidated against the actual JIT_CODE_DEBUG_INFO record size when jd->needs_bswap is false (native endianness): tools/perf/util/jitdump.c:jit_get_next_entry() { ... case JIT_CODE_DEBUG_INFO: if (jd->needs_bswap) { ... /* clamp so downstream consumers don't overrun */ jr->info.nr_entry = n; } break; ... } If a maliciously crafted jitdump file provides an artificially large nr_entry, could it cause this loop in jit_process_debug_info() to blindly iterate based on the unvalidated value? tools/perf/util/genelf_debug.c:jit_process_debug_info() { ... for (i = 0; i < nr_debug_entries; i++) { ent->addr = ent->addr - code_addr; ent = debug_entry_next(ent); } ... } If so, it appears debug_entry_next() could read out of bounds, and the ent->addr = ent->addr - code_addr; operation might repeatedly subtract fully attacker-controlled values (code_addr) from arbitrary heap metadata. Could this lead to arbitrary code execution when processing an untrusted file? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=6