* [PATCHES v4 0/12] perf jitdump: Input validation hardening
@ 2026-08-31 13:10 Arnaldo Carvalho de Melo
2026-08-31 13:10 ` [PATCH 01/12] perf jitdump: Fix extended header read that always fails Arnaldo Carvalho de Melo
` (11 more replies)
0 siblings, 12 replies; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-08-31 13:10 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
Arnaldo Carvalho de Melo, Stephane Eranian, Stefano Sanfilippo
Hi,
Please consider merging,
This series addresses twelve classes of input validation and resource
handling bugs in the jitdump file format parser that could cause OOB
memory access or memory leaks when processing maliciously crafted or
corrupted jitdump files.
All issues were discovered by sashiko-bot during automated review of the
jitdump code path. The bugs affect both the native-endian and byte-swap
code paths, with some checks previously only enforced during
byte-swapping.
Critical fix:
code_size validation was bypassable via int truncation. A record with
code_size in [2^31, record_size - 56] passed the existing bounds check
in jit_repipe_code_load() but truncated to a negative int when sent to
jit_process_code_load(), so the code pointer landed ~2GiB past the
record buffer, defeating the memchr() NUL scan and corrupting the
injected ELF.
Before: code_size = 0x80000010 passes the range check, then truncates
to a negative offset
After: code_size > INT_MAX is rejected up front; all subsequent code
size arithmetic stays within the record buffer
- Arnaldo
Changes since v3:
- Address some issues about PATH_MAX
Changes since v2 (fe3ab00d55aa56b4), series reordered:
- Reordered the series so that the leak plug for debug_data and
unwinding_data (now patch 2/12) comes before the code_size
validation patch that introduces the early-return path flagged by
sashiko-bot during review of v2. With the fix in place first, the
early return no longer introduces a leak that would only have been
plugged later in the series.
- Otherwise the series is unchanged: the end result is byte-identical
to v2 (tree diff between the v2 and v3 tips is empty).
- The pre-existing issues reported by sashiko-bot that are outside the
scope of this series were recorded in a TODO list for the next
series (tools/perf/TODO.hardening), which is now in production.
Changes since v1 (20260805133013.235016-1-acme@kernel.org):
- Rebased onto the current perf-tools-next head (fe3ab00d55aa56b4).
- All 12 patches now carry a Reviewed-by: Ian Rogers <irogers@google.com>.
- Applied the code-convention suggestions from Ian's review of v1:
- Patch "perf jitdump: Check snprintf return before computing header
size": the clamp now uses sizeof(event->mmap2.filename) instead of
PATH_MAX in both jit_repipe_code_load() and
jit_repipe_code_move(), tying the bound to the actual destination
buffer.
- Patch "perf jitdump: Use dirname() return value in jit_open()":
the strlcpy() bound uses sizeof(jd->dir) instead of PATH_MAX.
- A cosmetics-only remark about the include order of <limits.h> was
deliberately not applied.
Issues fixed:
Validation and bounds checks:
- Validate code_size against both the record size and INT_MAX in
jit_repipe_code_load()
- Prevent integer underflow in the debug info size calculation
- Bounds-check the debug entry byte-swap loop
- Validate debug entries on the native (non-swap) path, matching the
existing byte-swap path checks
- Validate sym string NUL-termination in code load, bounding the
strlen() scan to the code blob
- Validate unwinding sizes against the record payload before allocating
- Check the snprintf() return before computing the header size, and
clamp against the actual buffer size
Stream and record handling:
- Fix the extended header read that always failed, causing records to
be misparsed
- Use dirname()'s return value in jit_open(), fixing ENOTDIR failures
- Fix funlockfile() being called on an unlocked stream in the jit_open()
error path
Resource management:
- Free the event in jit_repipe_code_move()
- Fix debug_data and unwinding_data leaks when records are overwritten
Each patch includes a Fixes: tag pointing to the offending commit, dating
back to jitdump mmap injection support (9b07e27f88b9cd78), source line
info support (598b7c6919c7bbcc), and unwinding support
(0284fecd13b6db3e), all from the original 2016 jitdump work.
Testing: Built and tested on x86_64. No existing tests cover jitdump
parsing with malformed input; test suite expansion is left for future
work. The final series was re-reviewed after the fixes and the v1
review (build-checked, Fixes: tags verified); no regressions found.
Arnaldo Carvalho de Melo (12):
perf jitdump: Fix extended header read that always fails
perf jitdump: Fix debug_data and unwinding_data leaks
perf jitdump: Validate code_size against total_size in code load
perf jitdump: Prevent integer underflow in debug info size calculation
perf jitdump: Bounds-check debug entry byte-swap loop
perf jitdump: Check snprintf return before computing header size
perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path
perf jitdump: Free event in jit_repipe_code_move()
perf jitdump: Use dirname() return value in jit_open()
perf jitdump: Validate debug entries on native (non-swap) path
perf jitdump: Validate sym string NUL-termination in code load
perf jitdump: Validate unwinding sizes against record payload
tools/perf/util/jitdump.c | 126 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 108 insertions(+), 18 deletions(-)
base-commit: fe3ab00d55aa56b4d55cbc1150448f0aadd6732c
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH 01/12] perf jitdump: Fix extended header read that always fails 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo @ 2026-08-31 13:10 ` Arnaldo Carvalho de Melo 2026-08-31 13:22 ` sashiko-bot 2026-08-31 13:10 ` [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks Arnaldo Carvalho de Melo ` (10 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:10 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_open() sets bsz = bs before the fread() that uses bs - bsz as the read size, making the expression always evaluate to zero. fread() with size 0 returns 0, which triggers the ret != 1 error path — so extended jitdump headers (total_size > sizeof(header)) have been silently broken since the original implementation. Additionally, when 0 < bs <= bsz the if (bs > bsz) block is skipped entirely, leaving extended header bytes unread in the stream. Subsequent jit_get_next_entry() calls then parse those leftover bytes as a jr_prefix, corrupting the record stream. Fix by separating the buffer growth from the read: realloc only when bs > bsz, then unconditionally fread bs bytes when bs > 0. Fixes: 9b07e27f88b9cd78 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Cc: Ian Rogers <irogers@google.com> Cc: Namhyung Kim <namhyung@kernel.org> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 83005b30b9bf3fd7..4b7c7ba7cd95ddbb 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -224,10 +224,12 @@ jit_open(struct jit_buf_desc *jd, const char *name) n = realloc(buf, bs); if (!n) goto error; - bsz = bs; buf = n; - /* read extra we do not know about */ - ret = fread(buf, bs - bsz, 1, jd->in); + bsz = bs; + } + if (bs > 0) { + /* consume extended header bytes from the stream */ + ret = fread(buf, bs, 1, jd->in); if (ret != 1) goto error; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 01/12] perf jitdump: Fix extended header read that always fails 2026-08-31 13:10 ` [PATCH 01/12] perf jitdump: Fix extended header read that always fails Arnaldo Carvalho de Melo @ 2026-08-31 13:22 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:22 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_open() sets bsz = bs before the fread() that uses bs - bsz as the > read size, making the expression always evaluate to zero. fread() with > size 0 returns 0, which triggers the ret != 1 error path — so extended > jitdump headers (total_size > sizeof(header)) have been silently broken > since the original implementation. > > Additionally, when 0 < bs <= bsz the if (bs > bsz) block is skipped > entirely, leaving extended header bytes unread in the stream. Subsequent > jit_get_next_entry() calls then parse those leftover bytes as a > jr_prefix, corrupting the record stream. > > Fix by separating the buffer growth from the read: realloc only when > bs > bsz, then unconditionally fread bs bytes when bs > 0. > > Fixes: 9b07e27f88b9cd78 ("perf inject: Add jitdump mmap injection support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Cc: Ian Rogers <irogers@google.com> > Cc: Namhyung Kim <namhyung@kernel.org> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=1 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo 2026-08-31 13:10 ` [PATCH 01/12] perf jitdump: Fix extended header read that always fails Arnaldo Carvalho de Melo @ 2026-08-31 13:10 ` Arnaldo Carvalho de Melo 2026-08-31 13:24 ` sashiko-bot 2026-08-31 13:10 ` [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load Arnaldo Carvalho de Melo ` (9 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:10 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_repipe_debug_info() overwrites jd->debug_data without freeing the previous allocation. If two consecutive JIT_CODE_DEBUG_INFO records appear without an intervening LOAD record consuming the data, the first allocation leaks. The sibling jit_repipe_unwinding_info() already frees the old jd->unwinding_data before reassignment — add the same pattern to jit_repipe_debug_info() using zfree(). Also add cleanup of both buffers in jit_close() so they are freed when the jitdump session ends, even if no LOAD record consumed them. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 4b7c7ba7cd95ddbb..dcb26d9c6c8fc551 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -117,6 +117,8 @@ jit_close(struct jit_buf_desc *jd) funlockfile(jd->in); fclose(jd->in); jd->in = NULL; + zfree(&jd->debug_data); + zfree(&jd->unwinding_data); } static int @@ -665,6 +667,7 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) memcpy(data, &jr->info.entries, sz); + zfree(&jd->debug_data); jd->debug_data = data; /* -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks 2026-08-31 13:10 ` [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks Arnaldo Carvalho de Melo @ 2026-08-31 13:24 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:24 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_repipe_debug_info() overwrites jd->debug_data without freeing the > previous allocation. If two consecutive JIT_CODE_DEBUG_INFO records > appear without an intervening LOAD record consuming the data, the first > allocation leaks. > > The sibling jit_repipe_unwinding_info() already frees the old > jd->unwinding_data before reassignment — add the same pattern to > jit_repipe_debug_info() using zfree(). > > Also add cleanup of both buffers in jit_close() so they are freed when > the jitdump session ends, even if no LOAD record consumed them. > > Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=2 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo 2026-08-31 13:10 ` [PATCH 01/12] perf jitdump: Fix extended header read that always fails Arnaldo Carvalho de Melo 2026-08-31 13:10 ` [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks Arnaldo Carvalho de Melo @ 2026-08-31 13:10 ` Arnaldo Carvalho de Melo 2026-08-31 13:21 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation Arnaldo Carvalho de Melo ` (8 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:10 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_repipe_code_load() reads code_size from the jitdump record and uses it to compute a pointer to the code blob: code = (unsigned long)jr + jr->load.p.total_size - csize; An oversized code_size underflows the pointer arithmetic, causing OOB reads into earlier heap memory. Validate that code_size fits within the record (total_size - sizeof(jr->load)) before the pointer computation. code_size is uint64_t but csize is int; values above INT_MAX wrap negative when narrowed into csize, which defeats the bounds check and sends the code pointer past the end of the record. Reject those too. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index dcb26d9c6c8fc551..14bd23c8d1963e92 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -9,6 +9,7 @@ #include <fcntl.h> #include <unistd.h> #include <inttypes.h> +#include <limits.h> #include <byteswap.h> #include <sys/stat.h> #include <sys/mman.h> @@ -452,6 +453,16 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) csize = jr->load.code_size; usize = jd->unwinding_mapped_size; addr = jr->load.code_addr; + + /* code blob lives at the end of the record, validate it fits */ + if (jr->load.p.total_size < sizeof(jr->load) || + jr->load.code_size > jr->load.p.total_size - sizeof(jr->load) || + jr->load.code_size > INT_MAX) { + pr_warning("jitdump: invalid code_size %" PRIu64 " (total_size=%u) in code_load record\n", + (uint64_t)jr->load.code_size, jr->load.p.total_size); + return -1; + } + sym = (void *)((unsigned long)jr + sizeof(jr->load)); code = (unsigned long)jr + jr->load.p.total_size - csize; count = jr->load.code_index; -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load 2026-08-31 13:10 ` [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load Arnaldo Carvalho de Melo @ 2026-08-31 13:21 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:21 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_repipe_code_load() reads code_size from the jitdump record and uses > it to compute a pointer to the code blob: > > code = (unsigned long)jr + jr->load.p.total_size - csize; > > An oversized code_size underflows the pointer arithmetic, causing OOB > reads into earlier heap memory. Validate that code_size fits within the > record (total_size - sizeof(jr->load)) before the pointer computation. > > code_size is uint64_t but csize is int; values above INT_MAX wrap > negative when narrowed into csize, which defeats the bounds check and > sends the code pointer past the end of the record. Reject those too. > > Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=3 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (2 preceding siblings ...) 2026-08-31 13:10 ` [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:22 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop Arnaldo Carvalho de Melo ` (7 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian, Stefano Sanfilippo From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_repipe_debug_info() and jit_repipe_unwinding_info() compute payload sizes by subtracting the fixed header size from total_size: sz = jr->prefix.total_size - sizeof(jr->info); When total_size is smaller than the header struct (from a truncated or corrupted jitdump record), the subtraction underflows to a massive value, causing an oversized allocation followed by an OOB memcpy. Validate that total_size covers at least the fixed header before the subtraction in both functions. Fixes: 598b7c6919c7 ("perf jit: add source line info support") Fixes: 0284fecd13b6 ("perf jit: Add unwinding support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Cc: Stefano Sanfilippo <ssanfilippo@chromium.org> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 14bd23c8d1963e92..f79e9420c6bd7c51 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -671,6 +671,10 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) if (!(jd && jr)) return -1; + /* total_size must cover at least the fixed header */ + if (jr->prefix.total_size < sizeof(jr->info)) + return -1; + sz = jr->prefix.total_size - sizeof(jr->info); data = malloc(sz); if (!data) @@ -699,6 +703,10 @@ jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr) if (!(jd && jr)) return -1; + /* total_size must cover at least the fixed header */ + if (jr->prefix.total_size < sizeof(jr->unwinding)) + return -1; + unwinding_data_size = jr->prefix.total_size - sizeof(jr->unwinding); unwinding_data = malloc(unwinding_data_size); if (!unwinding_data) -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation 2026-08-31 13:11 ` [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation Arnaldo Carvalho de Melo @ 2026-08-31 13:22 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:22 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_repipe_debug_info() and jit_repipe_unwinding_info() compute payload > sizes by subtracting the fixed header size from total_size: > > sz = jr->prefix.total_size - sizeof(jr->info); > > When total_size is smaller than the header struct (from a truncated or > corrupted jitdump record), the subtraction underflows to a massive > value, causing an oversized allocation followed by an OOB memcpy. > > Validate that total_size covers at least the fixed header before the > subtraction in both functions. > > Fixes: 598b7c6919c7 ("perf jit: add source line info support") > Fixes: 0284fecd13b6 ("perf jit: Add unwinding support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Cc: Stefano Sanfilippo <ssanfilippo@chromium.org> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=4 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (3 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 06/12] perf jitdump: Check snprintf return before computing header size Arnaldo Carvalho de Melo ` (6 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> The byte-swap loop for JIT_CODE_DEBUG_INFO uses array indexing (jr->info.entries[n]) to iterate debug entries. struct debug_entry has a flexible array member name[], so each entry has a different size. Array indexing computes offsets assuming fixed-size elements, landing inside variable-length name strings after the first entry and byte-swapping garbage. Additionally, nr_entry is read from untrusted jitdump input without validation against total_size, so a crafted value causes OOB reads. Replace the array indexing with debug_entry_next() pointer arithmetic (which correctly accounts for the variable-length name) and bounds-check each entry against the record's total_size before byte-swapping. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index f79e9420c6bd7c51..7efbaa07f1ba73f9 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -320,14 +320,32 @@ jit_get_next_entry(struct jit_buf_desc *jd) switch(id) { case JIT_CODE_DEBUG_INFO: if (jd->needs_bswap) { + void *end = (void *)jr + jr->prefix.total_size; + struct debug_entry *ent; uint64_t n; + jr->info.code_addr = bswap_64(jr->info.code_addr); jr->info.nr_entry = bswap_64(jr->info.nr_entry); - for (n = 0 ; n < jr->info.nr_entry; n++) { - jr->info.entries[n].addr = bswap_64(jr->info.entries[n].addr); - jr->info.entries[n].lineno = bswap_32(jr->info.entries[n].lineno); - jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim); + + /* + * debug_entry has a variable-length name[], so array + * indexing would compute wrong offsets — use + * debug_entry_next() and bounds-check each entry. + */ + ent = &jr->info.entries[0]; + for (n = 0; n < jr->info.nr_entry; n++) { + if ((void *)ent + sizeof(*ent) > end) + break; + /* name must be NUL-terminated within the record */ + if (!memchr(ent->name, '\0', (char *)end - ent->name)) + break; + ent->addr = bswap_64(ent->addr); + ent->lineno = bswap_32(ent->lineno); + ent->discrim = bswap_32(ent->discrim); + ent = debug_entry_next(ent); } + /* clamp so downstream consumers don't overrun */ + jr->info.nr_entry = n; } break; case JIT_CODE_UNWINDING_INFO: -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop 2026-08-31 13:11 ` [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop Arnaldo Carvalho de Melo @ 2026-08-31 13:23 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:23 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] Unaligned memory accesses leading to SIGBUS crashes on strict-alignment architectures. -- commit 947f2eb889b5646cf554f70f7bd7ac567ceaa090 Author: Arnaldo Carvalho de Melo <acme@redhat.com> perf jitdump: Bounds-check debug entry byte-swap loop This commit replaces fixed-size array indexing with pointer arithmetic using debug_entry_next to iterate variable-length debug entries in JIT_CODE_DEBUG_INFO records. It also adds bounds checking against the total record size to prevent out-of-bounds reads. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index f79e9420c6bd7..7efbaa07f1ba7 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c [ ... ] > @@ -320,14 +320,32 @@ jit_get_next_entry(struct jit_buf_desc *jd) > switch(id) { > case JIT_CODE_DEBUG_INFO: > if (jd->needs_bswap) { > + void *end = (void *)jr + jr->prefix.total_size; > + struct debug_entry *ent; > uint64_t n; > + > jr->info.code_addr = bswap_64(jr->info.code_addr); > jr->info.nr_entry = bswap_64(jr->info.nr_entry); > - for (n = 0 ; n < jr->info.nr_entry; n++) { > - jr->info.entries[n].addr = bswap_64(jr->info.entries[n].addr); > - jr->info.entries[n].lineno = bswap_32(jr->info.entries[n].lineno); > - jr->info.entries[n].discrim = bswap_32(jr->info.entries[n].discrim); > + > + /* > + * debug_entry has a variable-length name[], so array > + * indexing would compute wrong offsets — use > + * debug_entry_next() and bounds-check each entry. > + */ > + ent = &jr->info.entries[0]; > + for (n = 0; n < jr->info.nr_entry; n++) { > + if ((void *)ent + sizeof(*ent) > end) > + break; > + /* name must be NUL-terminated within the record */ > + if (!memchr(ent->name, '\0', (char *)end - ent->name)) > + break; > + ent->addr = bswap_64(ent->addr); > + ent->lineno = bswap_32(ent->lineno); > + ent->discrim = bswap_32(ent->discrim); [Severity: Medium] Does this code risk triggering unaligned memory accesses and SIGBUS crashes on strict-alignment architectures? In jitdump files, the debug_entry structure is packed with a variable-length name string without padding. The pointer arithmetic in debug_entry_next advances the ent pointer by the exact string length (including the NUL byte). If the string has an odd length, subsequent ent pointers will no longer be aligned to an 8-byte boundary. Because the struct lacks the __packed attribute, the compiler assumes natural alignment. When it emits standard aligned load and store instructions for the 64-bit addr and 32-bit lineno fields, they will trap when receiving an unaligned address while parsing cross-endian jitdump files in jit_get_next_entry. > + ent = debug_entry_next(ent); > } > + /* clamp so downstream consumers don't overrun */ > + jr->info.nr_entry = n; > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=5 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 06/12] perf jitdump: Check snprintf return before computing header size 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (4 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path Arnaldo Carvalho de Melo ` (5 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> snprintf() returns the would-have-been length on truncation. When the jitted filename exceeds PATH_MAX, the unclamped 'size' value inflates sizeof(event->mmap2.filename) - size into a massive underflow, causing the header.size computation to write an oversized header. The subsequent write to 'id = event + header.size - idr_size' then corrupts the heap. Clamp size to PATH_MAX - 1 after snprintf in both jit_repipe_code_load() and jit_repipe_code_move(). Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 7efbaa07f1ba73f9..45f0e21b0e780cb6 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -495,6 +495,9 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) jd->dir, nspid, count); + /* snprintf returns would-be length on truncation, clamp to buffer */ + if (size >= sizeof(event->mmap2.filename)) + size = sizeof(event->mmap2.filename) - 1; size++; /* for \0 */ @@ -625,6 +628,9 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) jd->dir, nspid, jr->move.code_index); + /* snprintf returns would-be length on truncation, clamp to buffer */ + if (size >= sizeof(event->mmap2.filename)) + size = sizeof(event->mmap2.filename) - 1; size++; /* for \0 */ -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 06/12] perf jitdump: Check snprintf return before computing header size 2026-08-31 13:11 ` [PATCH 06/12] perf jitdump: Check snprintf return before computing header size Arnaldo Carvalho de Melo @ 2026-08-31 13:23 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:23 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Insufficient heap allocation in `jit_repipe_code_move()` leads to an out-of-bounds read and heap disclosure when writing the event to `perf.data`. - [High] Heap out-of-bounds write due to brittle, hardcoded sample ID struct layout. -- commit 9bf23bcb5ee8564df7189ee4fbf6479763732a6c Author: Arnaldo Carvalho de Melo <acme@redhat.com> perf jitdump: Check snprintf return before computing header size This commit clamps the string size returned by snprintf() to prevent an integer underflow when computing header.size in jit_repipe_code_load() and jit_repipe_code_move(). This fixes a heap corruption that occurs when jitted filenames exceed PATH_MAX. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index 7efbaa07f1ba7..45f0e21b0e780 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -495,6 +495,9 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) > jd->dir, > nspid, > count); > + /* snprintf returns would-be length on truncation, clamp to buffer */ > + if (size >= sizeof(event->mmap2.filename)) > + size = sizeof(event->mmap2.filename) - 1; [Severity: High] This is a pre-existing issue, but is it possible for the allocation of event earlier in this function to cause an out-of-bounds write? In jit_repipe_code_load(), event is allocated with exactly idr_size trailing bytes: event = calloc(1, sizeof(*event) + idr_size); Later in the function, it writes to id->time based on a hardcoded struct layout: struct { u32 pid, tid; u64 time; } *id; if (jd->sample_type & PERF_SAMPLE_TIME) id->time = convert_timestamp(jd, jr->load.p.timestamp); If PERF_SAMPLE_TID is missing from the session but PERF_SAMPLE_TIME is present, idr_size may only be 8. Would writing to id->time at offset 8 strictly overflow the 8-byte dynamic allocation? > > size++; /* for \0 */ > [ ... ] > @@ -625,6 +628,9 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) > jd->dir, > nspid, > jr->move.code_index); > + /* snprintf returns would-be length on truncation, clamp to buffer */ > + if (size >= sizeof(event->mmap2.filename)) > + size = sizeof(event->mmap2.filename) - 1; [Severity: High] This is a pre-existing issue, but can this lead to an out-of-bounds read and heap disclosure when the event is injected? In jit_repipe_code_move(), the event buffer is allocated with a fixed 16-byte offset for the sample ID: /* * +16 to account for sample_id_all (hack) */ event = calloc(1, sizeof(*event) + 16); However, the total event size is calculated using the full dynamic idr_size: event->mmap2.header.size = (sizeof(event->mmap2) - (sizeof(event->mmap2.filename) - size) + idr_size); If idr_size > 16 (e.g. PERF_SAMPLE_CPU and PERF_SAMPLE_ID are set) and the filename length approaches PATH_MAX, could header.size strictly exceed the allocated buffer bounds? When jit_inject_event(jd, event) is called later, could the oversized header size cause it to read past the allocation and leak heap memory into the perf.data file? > > size++; /* for \0 */ > -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=6 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (5 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 06/12] perf jitdump: Check snprintf return before computing header size Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() Arnaldo Carvalho de Melo ` (4 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> 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. Split the error path into two labels: 'error' (after flockfile) calls funlockfile before cleanup, 'error_noflock' (before flockfile) skips the unlock. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 45f0e21b0e780cb6..ae63366b86c6d765 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -157,7 +157,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 @@ -246,8 +246,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; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path 2026-08-31 13:11 ` [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path Arnaldo Carvalho de Melo @ 2026-08-31 13:23 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:23 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > 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. > > Split the error path into two labels: 'error' (after flockfile) calls > funlockfile before cleanup, 'error_noflock' (before flockfile) skips > the unlock. > > Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=7 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (6 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:21 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() Arnaldo Carvalho de Melo ` (3 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_repipe_code_move() allocates a perf_event with calloc but never frees it — the 'out' label exits with only perf_sample__exit(). The sibling function jit_repipe_code_load() correctly calls free(event) at its out label. Add the same free(event) to jit_repipe_code_move(). Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index ae63366b86c6d765..91aa1eea8229faac 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -685,6 +685,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) build_id__mark_dso_hit(tool, event, &sample, jd->machine); out: perf_sample__exit(&sample); + free(event); return ret; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() 2026-08-31 13:11 ` [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() Arnaldo Carvalho de Melo @ 2026-08-31 13:21 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:21 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_repipe_code_move() allocates a perf_event with calloc but never > frees it — the 'out' label exits with only perf_sample__exit(). > > The sibling function jit_repipe_code_load() correctly calls > free(event) at its out label. Add the same free(event) to > jit_repipe_code_move(). > > Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=8 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (7 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:19 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo ` (2 subsequent siblings) 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_open() calls dirname(jd->dir) but ignores the return value. POSIX says dirname() may return a pointer to internal static storage — glibc does this when the path has no '/', returning "." from a static buffer and leaving jd->dir unchanged with the original filename. Capture the return value and copy it back to jd->dir when dirname() returns a different pointer. Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 91aa1eea8229faac..d3de307532d55065 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -146,6 +146,7 @@ jit_open(struct jit_buf_desc *jd, const char *name) ssize_t bs, bsz = 0; void *n, *buf = NULL; int ret, retval = -1; + char *dname; nsinfo__mountns_enter(jd->nsi, &nsc); jd->in = fopen(name, "r"); @@ -241,7 +242,9 @@ jit_open(struct jit_buf_desc *jd, const char *name) */ strncpy(jd->dir, name, PATH_MAX - 1); jd->dir[PATH_MAX - 1] = '\0'; - dirname(jd->dir); + dname = dirname(jd->dir); + if (dname != jd->dir) + strlcpy(jd->dir, dname, sizeof(jd->dir)); free(buf); return 0; -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() 2026-08-31 13:11 ` [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() Arnaldo Carvalho de Melo @ 2026-08-31 13:19 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:19 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_open() calls dirname(jd->dir) but ignores the return value. POSIX > says dirname() may return a pointer to internal static storage — glibc > does this when the path has no '/', returning "." from a static buffer > and leaving jd->dir unchanged with the original filename. > > Capture the return value and copy it back to jd->dir when dirname() > returns a different pointer. > > Fixes: 9b07e27f88b9 ("perf inject: Add jitdump mmap injection support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=9 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (8 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load Arnaldo Carvalho de Melo 2026-08-31 13:11 ` [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload Arnaldo Carvalho de Melo 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. On native-endian files, nr_entry passes through unvalidated to jit_repipe_debug_info(), which stores it as jd->nr_debug_entries. Downstream, jit_process_debug_info() in genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), which calls strlen() on each entry's name field — a crafted nr_entry causes OOB reads and writes. Add bounds-checked iteration in jit_repipe_debug_info() that validates each debug_entry fits in the payload and its name is NUL-terminated before calling debug_entry_next(). Clamp nr_debug_entries to the count of valid entries. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index d3de307532d55065..5a3ea2681fb37105 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) { - void *data; - size_t sz; + struct debug_entry *ent; + void *data, *end; + size_t sz, valid; + uint64_t i; if (!(jd && jr)) return -1; @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) jd->debug_data = data; /* - * we must use nr_entry instead of size here because - * we cannot distinguish actual entry from padding otherwise + * Clamp nr_debug_entries to entries that actually fit in the + * payload. The byte-swap path already does this for cross-endian + * files; validate on the native path too, since downstream + * jit_process_debug_info() iterates via debug_entry_next() which + * calls strlen() on each entry's name field. */ - jd->nr_debug_entries = jr->info.nr_entry; + end = data + sz; + ent = data; + valid = 0; + for (i = 0; i < jr->info.nr_entry; i++) { + if ((void *)ent + sizeof(*ent) > end) + break; + /* name must be NUL-terminated within the payload */ + if (!memchr(ent->name, '\0', (char *)end - ent->name)) + break; + ent = debug_entry_next(ent); + valid++; + } + jd->nr_debug_entries = valid; return 0; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-31 13:11 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo @ 2026-08-31 13:23 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:23 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > The bounds-checking and nr_entry clamping added for the byte-swap path > only runs when jd->needs_bswap is true. On native-endian files, nr_entry > passes through unvalidated to jit_repipe_debug_info(), which stores it > as jd->nr_debug_entries. Downstream, jit_process_debug_info() in > genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), > which calls strlen() on each entry's name field — a crafted nr_entry > causes OOB reads and writes. > > Add bounds-checked iteration in jit_repipe_debug_info() that validates > each debug_entry fits in the payload and its name is NUL-terminated > before calling debug_entry_next(). Clamp nr_debug_entries to the count > of valid entries. > > Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=10 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (9 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:31 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload Arnaldo Carvalho de Melo 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_repipe_code_load() computes sym = (void *)jr + sizeof(jr->load) and passes it to jit_emit_elf() which calls strlen(sym) via jit_write_elf(). If code_size equals total_size - sizeof(jr->load), the sym pointer aliases the code blob with no NUL terminator, and strlen() scans past the buffer into adjacent heap memory. Add a memchr() check to verify the symbol name is NUL-terminated within the region between the load header and the code blob before use. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 5a3ea2681fb37105..5898a7d8eb962daf 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -487,6 +487,13 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) sym = (void *)((unsigned long)jr + sizeof(jr->load)); code = (unsigned long)jr + jr->load.p.total_size - csize; + + /* sym string lives between the load header and the code blob */ + if (!memchr(sym, '\0', code - (unsigned long)sym)) { + pr_warning("jitdump: unterminated symbol name in code_load record\n"); + return -1; + } + count = jr->load.code_index; idr_size = jd->machine->id_hdr_size; -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load 2026-08-31 13:11 ` [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load Arnaldo Carvalho de Melo @ 2026-08-31 13:31 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:31 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > jit_repipe_code_load() computes sym = (void *)jr + sizeof(jr->load) and > passes it to jit_emit_elf() which calls strlen(sym) via jit_write_elf(). > If code_size equals total_size - sizeof(jr->load), the sym pointer > aliases the code blob with no NUL terminator, and strlen() scans past > the buffer into adjacent heap memory. > > Add a memchr() check to verify the symbol name is NUL-terminated within > the region between the load header and the code blob before use. > > Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Reviewed-by: Ian Rogers <irogers@google.com> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: LLM > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Sashiko has reviewed this patch and found no issues. It looks great! -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=11 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo ` (10 preceding siblings ...) 2026-08-31 13:11 ` [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load Arnaldo Carvalho de Melo @ 2026-08-31 13:11 ` Arnaldo Carvalho de Melo 2026-08-31 13:35 ` sashiko-bot 11 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-31 13:11 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stefano Sanfilippo, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> jit_repipe_unwinding_info() copies unwinding_size and eh_frame_hdr_size from the jitdump record into jd-> fields without checking them against the actual payload size. Downstream, jit_add_eh_frame_info() in genelf.c computes unwinding_table_size = unwinding_size - eh_frame_hdr_size, which underflows when eh_frame_hdr_size > unwinding_size. The result is passed as d->d_size to libelf, causing an OOB heap read into the output ELF file. Validate that unwinding_size fits within the record payload and that eh_frame_hdr_size does not exceed unwinding_size before allocating or storing the values, so a bogus record cannot force a large allocation that is then discarded. mapped_size is likewise taken from the record and was narrowed into an int for the mmap2 len computation in jit_repipe_code_load() and jit_repipe_code_move(); values above INT_MAX would turn negative, producing a wrong mmap2 length. Use uint64_t for usize so the value cannot truncate. Fixes: 0284fecd13b6db3e ("perf jit: Add unwinding support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Reviewed-by: Ian Rogers <irogers@google.com> Cc: Stefano Sanfilippo <ssanfilippo@chromium.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 5898a7d8eb962daf..d25a9fe9b020ce87 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -462,7 +462,8 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) u16 idr_size; const char *sym; uint64_t count; - int ret, csize, usize; + int ret, csize; + uint64_t usize; pid_t nspid, pid, tid; struct { u32 pid, tid; @@ -543,7 +544,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) event->mmap2.pgoff = GEN_ELF_TEXT_OFFSET; event->mmap2.start = addr; - event->mmap2.len = usize ? ALIGN_8(csize) + usize : csize; + event->mmap2.len = usize ? ALIGN_8((uint64_t)csize) + usize : (uint64_t)csize; event->mmap2.pid = pid; event->mmap2.tid = tid; event->mmap2.ino = st.st_ino; @@ -612,7 +613,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) char *filename; size_t size; struct stat st; - int usize; + uint64_t usize; u16 idr_size; int ret; pid_t nspid, pid, tid; @@ -761,6 +762,18 @@ jit_repipe_unwinding_info(struct jit_buf_desc *jd, union jr_entry *jr) return -1; unwinding_data_size = jr->prefix.total_size - sizeof(jr->unwinding); + + /* + * Validate sizes before allocating — jit_add_eh_frame_info() + * computes unwinding_size - eh_frame_hdr_size and uses the + * result as a buffer length for libelf. + */ + if (jr->unwinding.unwinding_size > unwinding_data_size || + jr->unwinding.eh_frame_hdr_size > jr->unwinding.unwinding_size) { + pr_warning("jitdump: invalid unwinding sizes in unwinding_info record\n"); + return -1; + } + unwinding_data = malloc(unwinding_data_size); if (!unwinding_data) return -1; -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload 2026-08-31 13:11 ` [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload Arnaldo Carvalho de Melo @ 2026-08-31 13:35 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-31 13:35 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Stale unwinding data leak and corruption in subsequent JIT ELF files due to missing cleanup when `eh_frame_hdr_size` is zero. - [High] Missing bounds check in `jit_repipe_code_move` leaks uninitialized heap memory into `perf.data`. -- commit 606a51d613d656e670cf8772d98c0b537c8eb055 Author: Arnaldo Carvalho de Melo <acme@redhat.com> perf jitdump: Validate unwinding sizes against record payload This commit validates unwinding sizes against the record payload to prevent out-of-bounds heap reads when eh_frame_hdr_size exceeds unwinding_size. It also updates mapped_size to use a uint64_t to avoid mmap2 length truncation. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index 5898a7d8eb962..d25a9fe9b020c 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -462,7 +462,8 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) > u16 idr_size; > const char *sym; > uint64_t count; > - int ret, csize, usize; > + int ret, csize; > + uint64_t usize; > pid_t nspid, pid, tid; > struct { > u32 pid, tid; > u64 time; > } *id; [Severity: High] This is a pre-existing issue, but does jit_repipe_code_load() leak stale unwinding data to subsequent JIT ELF files if eh_frame_hdr_size is zero? A JIT dump can contain an unwinding record with unwinding_size > 0 but eh_frame_hdr_size == 0, which is valid and permitted by the new size validation. When processing the subsequent code_load event, it correctly uses this unwinding data, but appears to skip the cleanup block because jd->eh_frame_hdr_size is zero: if (jd->unwinding_data && jd->eh_frame_hdr_size) { zfree(&jd->unwinding_data); jd->eh_frame_hdr_size = 0; ... } Could this cause all subsequent code_load events to erroneously embed the same stale unwinding table, corrupting the generated ELF files for unrelated JIT methods? [ ... ] > @@ -612,7 +613,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) > char *filename; > size_t size; > struct stat st; > - int usize; > + uint64_t usize; > u16 idr_size; > int ret; > pid_t nspid, pid, tid; [Severity: High] This is a pre-existing issue, but does jit_repipe_code_move() lack bounds checking for the record payload? A malformed JIT dump could provide a JIT_CODE_MOVE record with a total_size smaller than sizeof(struct jr_code_move). jit_get_next_entry() reallocates the buffer to exactly total_size bytes, but jit_repipe_code_move() doesn't validate total_size before unconditionally accessing fields past the fixed record prefix: nspid = jr->load.pid; ... event->mmap2.start = jr->move.new_code_addr; event->mmap2.len = usize ? ALIGN_8(jr->move.code_size) + usize : jr->move.code_size; Could this result in uninitialized out-of-bounds heap memory being assigned to event fields that are subsequently written to the output perf.data stream? [ ... ] -- Sashiko AI review · https://sashiko.dev/#/patchset/20260831131110.4681-1-acme@kernel.org?part=12 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHES v3 0/12] perf jitdump: Input validation hardening
@ 2026-08-06 12:35 Arnaldo Carvalho de Melo
2026-08-06 12:36 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo
0 siblings, 1 reply; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-08-06 12:35 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
Stephane Eranian, Stefano Sanfilippo, Arnaldo Carvalho de Melo
Hi,
Please consider merging,
This series addresses twelve classes of input validation and resource
handling bugs in the jitdump file format parser that could cause OOB
memory access or memory leaks when processing maliciously crafted or
corrupted jitdump files.
All issues were discovered by sashiko-bot during automated review of the
jitdump code path. The bugs affect both the native-endian and byte-swap
code paths, with some checks previously only enforced during
byte-swapping.
Critical fix:
code_size validation was bypassable via int truncation. A record with
code_size in [2^31, record_size - 56] passed the existing bounds check
in jit_repipe_code_load() but truncated to a negative int when sent to
jit_process_code_load(), so the code pointer landed ~2GiB past the
record buffer, defeating the memchr() NUL scan and corrupting the
injected ELF.
Before: code_size = 0x80000010 passes the range check, then truncates
to a negative offset
After: code_size > INT_MAX is rejected up front; all subsequent code
size arithmetic stays within the record buffer
Best regards,
- Arnaldo
Changes since v2 (fe3ab00d55aa56b4), series reordered:
- Reordered the series so that the leak plug for debug_data and
unwinding_data (now patch 2/12) comes before the code_size
validation patch that introduces the early-return path flagged by
sashiko-bot during review of v2. With the fix in place first, the
early return no longer introduces a leak that would only have been
plugged later in the series.
- Otherwise the series is unchanged: the end result is byte-identical
to v2 (tree diff between the v2 and v3 tips is empty).
- The pre-existing issues reported by sashiko-bot that are outside the
scope of this series were recorded in a TODO list for the next
series (tools/perf/TODO.hardening), which is now in production.
Changes since v1 (20260805133013.235016-1-acme@kernel.org):
- Rebased onto the current perf-tools-next head (fe3ab00d55aa56b4).
- All 12 patches now carry a Reviewed-by: Ian Rogers <irogers@google.com>.
- Applied the code-convention suggestions from Ian's review of v1:
- Patch "perf jitdump: Check snprintf return before computing header
size": the clamp now uses sizeof(event->mmap2.filename) instead of
PATH_MAX in both jit_repipe_code_load() and
jit_repipe_code_move(), tying the bound to the actual destination
buffer.
- Patch "perf jitdump: Use dirname() return value in jit_open()":
the strlcpy() bound uses sizeof(jd->dir) instead of PATH_MAX.
- A cosmetics-only remark about the include order of <limits.h> was
deliberately not applied.
Issues fixed:
Validation and bounds checks:
- Validate code_size against both the record size and INT_MAX in
jit_repipe_code_load()
- Prevent integer underflow in the debug info size calculation
- Bounds-check the debug entry byte-swap loop
- Validate debug entries on the native (non-swap) path, matching the
existing byte-swap path checks
- Validate sym string NUL-termination in code load, bounding the
strlen() scan to the code blob
- Validate unwinding sizes against the record payload before allocating
- Check the snprintf() return before computing the header size, and
clamp against the actual buffer size
Stream and record handling:
- Fix the extended header read that always failed, causing records to
be misparsed
- Use dirname()'s return value in jit_open(), fixing ENOTDIR failures
- Fix funlockfile() being called on an unlocked stream in the jit_open()
error path
Resource management:
- Free the event in jit_repipe_code_move()
- Fix debug_data and unwinding_data leaks when records are overwritten
Each patch includes a Fixes: tag pointing to the offending commit, dating
back to jitdump mmap injection support (9b07e27f88b9cd78), source line
info support (598b7c6919c7bbcc), and unwinding support
(0284fecd13b6db3e), all from the original 2016 jitdump work.
Testing: Built and tested on x86_64. No existing tests cover jitdump
parsing with malformed input; test suite expansion is left for future
work. The final series was re-reviewed after the fixes and the v1
review (build-checked, Fixes: tags verified); no regressions found.
AI assistance: This series was developed with assistance from Claude
(claude-opus-4.6) and Opencode (deepseek-v4-flash-free) for code
analysis, patch generation, and commit message composition.
Arnaldo Carvalho de Melo (12):
perf jitdump: Fix extended header read that always fails
perf jitdump: Fix debug_data and unwinding_data leaks
perf jitdump: Validate code_size against total_size in code load
perf jitdump: Prevent integer underflow in debug info size calculation
perf jitdump: Bounds-check debug entry byte-swap loop
perf jitdump: Check snprintf return before computing header size
perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path
perf jitdump: Free event in jit_repipe_code_move()
perf jitdump: Use dirname() return value in jit_open()
perf jitdump: Validate debug entries on native (non-swap) path
perf jitdump: Validate sym string NUL-termination in code load
perf jitdump: Validate unwinding sizes against record payload
tools/perf/util/jitdump.c | 126 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 108 insertions(+), 18 deletions(-)
base-commit: fe3ab00d55aa56b4d55cbc1150448f0aadd6732c
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-06 12:35 [PATCHES v3 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo @ 2026-08-06 12:36 ` Arnaldo Carvalho de Melo 2026-08-06 13:10 ` sashiko-bot 0 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-06 12:36 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. On native-endian files, nr_entry passes through unvalidated to jit_repipe_debug_info(), which stores it as jd->nr_debug_entries. Downstream, jit_process_debug_info() in genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), which calls strlen() on each entry's name field — a crafted nr_entry causes OOB reads and writes. Add bounds-checked iteration in jit_repipe_debug_info() that validates each debug_entry fits in the payload and its name is NUL-terminated before calling debug_entry_next(). Clamp nr_debug_entries to the count of valid entries. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index d3de307532d55065..5a3ea2681fb37105 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) { - void *data; - size_t sz; + struct debug_entry *ent; + void *data, *end; + size_t sz, valid; + uint64_t i; if (!(jd && jr)) return -1; @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) jd->debug_data = data; /* - * we must use nr_entry instead of size here because - * we cannot distinguish actual entry from padding otherwise + * Clamp nr_debug_entries to entries that actually fit in the + * payload. The byte-swap path already does this for cross-endian + * files; validate on the native path too, since downstream + * jit_process_debug_info() iterates via debug_entry_next() which + * calls strlen() on each entry's name field. */ - jd->nr_debug_entries = jr->info.nr_entry; + end = data + sz; + ent = data; + valid = 0; + for (i = 0; i < jr->info.nr_entry; i++) { + if ((void *)ent + sizeof(*ent) > end) + break; + /* name must be NUL-terminated within the payload */ + if (!memchr(ent->name, '\0', (char *)end - ent->name)) + break; + ent = debug_entry_next(ent); + valid++; + } + jd->nr_debug_entries = valid; return 0; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-06 12:36 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo @ 2026-08-06 13:10 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-06 13:10 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: Pre-existing issues: - [High] Iterating over `struct debug_entry` with `debug_entry_next()` produces unaligned pointers, causing undefined behavior and hardware exceptions (SIGBUS) on strict-alignment architectures. - [Medium] Parsing errors in JIT dump records are silently ignored in `jit_process_dump()`, leaving stale debug and unwinding data active and overwriting error return codes. - [Medium] `jit_repipe_code_move()` processes `JIT_CODE_MOVE` records without verifying that the record's `total_size` is large enough to contain the struct, leading to uninitialized heap memory reads. -- --- Patch [10]: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path --- commit f31dd5de27938e11279a2fce6356aeba4e9918b4 Author: Arnaldo Carvalho de Melo <acme@redhat.com> perf jitdump: Validate debug entries on native (non-swap) path The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. This patch adds bounds-checked iteration in jit_repipe_debug_info() to validate each debug_entry fits in the payload. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index d3de307532d55..5a3ea2681fb37 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) [Severity: Medium] This is a pre-existing issue, but does jit_repipe_code_move() process JIT_CODE_MOVE records without verifying that the record's total_size is large enough to contain the struct? If a malformed JIT_CODE_MOVE record specifies a small total_size, fread() might read 0 bytes, leaving the jr->move fields mapped to uninitialized bytes in jd->buf. Could this cause uninitialized heap memory to be read, byte-swapped in jit_get_next_entry(), and written to the output perf.data file? > > static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > { > - void *data; > - size_t sz; > + struct debug_entry *ent; > + void *data, *end; > + size_t sz, valid; > + uint64_t i; [ ... ] > /* > - * we must use nr_entry instead of size here because > - * we cannot distinguish actual entry from padding otherwise > + * Clamp nr_debug_entries to entries that actually fit in the > + * payload. The byte-swap path already does this for cross-endian > + * files; validate on the native path too, since downstream > + * jit_process_debug_info() iterates via debug_entry_next() which > + * calls strlen() on each entry's name field. > */ > - jd->nr_debug_entries = jr->info.nr_entry; > + end = data + sz; > + ent = data; > + valid = 0; > + for (i = 0; i < jr->info.nr_entry; i++) { > + if ((void *)ent + sizeof(*ent) > end) > + break; > + /* name must be NUL-terminated within the payload */ > + if (!memchr(ent->name, '\0', (char *)end - ent->name)) > + break; > + ent = debug_entry_next(ent); [Severity: High] This isn't a bug introduced by this patch, but does debug_entry_next() produce unaligned pointers here? Because struct debug_entry contains 64-bit and 32-bit fields but lacks __attribute__((packed)), the compiler emits 8-byte aligned memory accesses. Since the variable-length string does not pad to 8-byte boundaries, subsequent entries appear to become naturally unaligned in memory. When downstream code dereferences these fields, such as: tools/perf/util/genelf_debug.c:jit_process_debug_info() { ... ent->addr = ent->addr - code_addr; ... } could this perform unaligned 64-bit loads and stores, triggering hardware alignment faults (SIGBUS) on strict-alignment architectures? > + valid++; > + } > + jd->nr_debug_entries = valid; > > return 0; > } [Severity: Medium] This is a pre-existing issue, but are the error codes returned by this function silently ignored by its caller? In jit_process_dump(): tools/perf/util/jitdump.c:jit_process_dump() { ... ret = jit_repipe_debug_info(jd, jr); ... default: ret = 0; continue; } If jit_repipe_debug_info() returns -1 (e.g., due to OOM), the while loop doesn't seem to break. If a subsequent unrecognized record or JIT_CODE_CLOSE triggers the default case, ret is overwritten to 0. Does this successfully hide the parse failure and leave stale debug data active? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260806123604.271277-1-acme@kernel.org?part=10 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHES v2 0/12] perf jitdump: Input validation hardening
@ 2026-08-05 21:26 Arnaldo Carvalho de Melo
2026-08-05 21:27 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo
0 siblings, 1 reply; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-08-05 21:26 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
Arnaldo Carvalho de Melo, Stephane Eranian, Stefano Sanfilippo
Hi,
Please consider merging,
This series addresses twelve classes of input validation and resource
handling bugs in the jitdump file format parser that could cause OOB
memory access or memory leaks when processing maliciously crafted or
corrupted jitdump files.
All issues were discovered by sashiko-bot during automated review of the
jitdump code path. The bugs affect both the native-endian and byte-swap
code paths, with some checks previously only enforced during
byte-swapping.
Critical fix:
code_size validation was bypassable via int truncation. A record with
code_size in [2^31, record_size - 56] passed the existing bounds check
in jit_repipe_code_load() but truncated to a negative int when sent to
jit_process_code_load(), so the code pointer landed ~2GiB past the
record buffer, defeating the memchr() NUL scan and corrupting the
injected ELF.
Before: code_size = 0x80000010 passes the range check, then truncates
to a negative offset
After: code_size > INT_MAX is rejected up front; all subsequent code
size arithmetic stays within the record buffer
Best regards,
- Arnaldo
Changes since v1 (20260805133013.235016-1-acme@kernel.org):
- Rebased onto the current perf-tools-next head (fe3ab00d55aa56b4).
- All 12 patches now carry a Reviewed-by: Ian Rogers <irogers@google.com>.
- Applied the code-convention suggestions from Ian's review of v1:
- Patch "perf jitdump: Check snprintf return before computing header
size": the clamp now uses sizeof(event->mmap2.filename) instead of
PATH_MAX in both jit_repipe_code_load() and
jit_repipe_code_move(), tying the bound to the actual destination
buffer.
- Patch "perf jitdump: Use dirname() return value in jit_open()":
the strlcpy() bound uses sizeof(jd->dir) instead of PATH_MAX.
- A cosmetics-only remark about the include order of <limits.h> was
deliberately not applied.
Issues fixed:
Validation and bounds checks:
- Validate code_size against both the record size and INT_MAX in
jit_repipe_code_load()
- Prevent integer underflow in the debug info size calculation
- Bounds-check the debug entry byte-swap loop
- Validate debug entries on the native (non-swap) path, matching the
existing byte-swap path checks
- Validate sym string NUL-termination in code load, bounding the
strlen() scan to the code blob
- Validate unwinding sizes against the record payload before allocating
- Check the snprintf() return before computing the header size, and
clamp against the actual buffer size
Stream and record handling:
- Fix the extended header read that always failed, causing records to
be misparsed
- Use dirname()'s return value in jit_open(), fixing ENOTDIR failures
- Fix funlockfile() being called on an unlocked stream in the jit_open()
error path
Resource management:
- Free the event in jit_repipe_code_move()
- Fix debug_data and unwinding_data leaks when records are overwritten
Each patch includes a Fixes: tag pointing to the offending commit, dating
back to jitdump mmap injection support (9b07e27f88b9cd78), source line
info support (598b7c6919c7bbcc), and unwinding support
(0284fecd13b6db3e), all from the original 2016 jitdump work.
Testing: Built and tested on x86_64. No existing tests cover jitdump
parsing with malformed input; test suite expansion is left for future
work. The final series was re-reviewed after the fixes and the v1
review (build-checked, Fixes: tags verified); no regressions found.
AI assistance: This series was developed with assistance from Claude
(claude-opus-4.6) and Opencode (deepseek-v4-flash-free) for code
analysis, patch generation, and commit message composition.
Arnaldo Carvalho de Melo (12):
perf jitdump: Fix extended header read that always fails
perf jitdump: Validate code_size against total_size in code load
perf jitdump: Prevent integer underflow in debug info size calculation
perf jitdump: Bounds-check debug entry byte-swap loop
perf jitdump: Check snprintf return before computing header size
perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path
perf jitdump: Free event in jit_repipe_code_move()
perf jitdump: Fix debug_data and unwinding_data leaks
perf jitdump: Use dirname() return value in jit_open()
perf jitdump: Validate debug entries on native (non-swap) path
perf jitdump: Validate sym string NUL-termination in code load
perf jitdump: Validate unwinding sizes against record payload
tools/perf/util/jitdump.c | 126 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 108 insertions(+), 18 deletions(-)
base-commit: fe3ab00d55aa56b4d55cbc1150448f0aadd6732c
Arnaldo Carvalho de Melo (12):
perf jitdump: Fix extended header read that always fails
perf jitdump: Validate code_size against total_size in code load
perf jitdump: Prevent integer underflow in debug info size calculation
perf jitdump: Bounds-check debug entry byte-swap loop
perf jitdump: Check snprintf return before computing header size
perf jitdump: Fix funlockfile on unlocked stream in jit_open() error
path
perf jitdump: Free event in jit_repipe_code_move()
perf jitdump: Fix debug_data and unwinding_data leaks
perf jitdump: Use dirname() return value in jit_open()
perf jitdump: Validate debug entries on native (non-swap) path
perf jitdump: Validate sym string NUL-termination in code load
perf jitdump: Validate unwinding sizes against record payload
tools/perf/util/jitdump.c | 126 ++++++++++++++++++++++++++++++++------
1 file changed, 108 insertions(+), 18 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-05 21:26 [PATCHES v2 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo @ 2026-08-05 21:27 ` Arnaldo Carvalho de Melo 2026-08-05 22:00 ` sashiko-bot 0 siblings, 1 reply; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-05 21:27 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. On native-endian files, nr_entry passes through unvalidated to jit_repipe_debug_info(), which stores it as jd->nr_debug_entries. Downstream, jit_process_debug_info() in genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), which calls strlen() on each entry's name field — a crafted nr_entry causes OOB reads and writes. Add bounds-checked iteration in jit_repipe_debug_info() that validates each debug_entry fits in the payload and its name is NUL-terminated before calling debug_entry_next(). Clamp nr_debug_entries to the count of valid entries. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Claude:claude-opus-4.6 Reviewed-by: Ian Rogers <irogers@google.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index d3de307532d55065..5a3ea2681fb37105 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) { - void *data; - size_t sz; + struct debug_entry *ent; + void *data, *end; + size_t sz, valid; + uint64_t i; if (!(jd && jr)) return -1; @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) jd->debug_data = data; /* - * we must use nr_entry instead of size here because - * we cannot distinguish actual entry from padding otherwise + * Clamp nr_debug_entries to entries that actually fit in the + * payload. The byte-swap path already does this for cross-endian + * files; validate on the native path too, since downstream + * jit_process_debug_info() iterates via debug_entry_next() which + * calls strlen() on each entry's name field. */ - jd->nr_debug_entries = jr->info.nr_entry; + end = data + sz; + ent = data; + valid = 0; + for (i = 0; i < jr->info.nr_entry; i++) { + if ((void *)ent + sizeof(*ent) > end) + break; + /* name must be NUL-terminated within the payload */ + if (!memchr(ent->name, '\0', (char *)end - ent->name)) + break; + ent = debug_entry_next(ent); + valid++; + } + jd->nr_debug_entries = valid; return 0; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-05 21:27 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo @ 2026-08-05 22:00 ` sashiko-bot 0 siblings, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-05 22:00 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: Pre-existing issues: - [High] Missing NUL-termination validation for the symbol string in JIT_CODE_LOAD records causes out-of-bounds reads via strlen(). - [High] In `jit_repipe_unwinding_info()`, missing validation of `unwinding_size` and `eh_frame_hdr_size` causes an integer underflow and massive out-of-bounds read. - [Medium] Dereferencing fields of `struct debug_entry` causes undefined behavior and SIGBUS on strict-alignment architectures. - [Medium] Failing to allocate memory in `jit_repipe_debug_info` causes the next `JIT_CODE_LOAD` to inherit stale debug info. - [Medium] In `jit_repipe_code_move()`, the synthetic MMAP2 event allocation hardcodes a +16 byte hack for the sample ID header, causing an out-of-bounds heap read. -- --- Patch [10]: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path --- commit 6e2ff5c2d1b7c024e8a5cacbadffafaf75094372 Author: Arnaldo Carvalho de Melo <acme@redhat.com> Subject: perf jitdump: Validate debug entries on native (non-swap) path The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. On native-endian files, nr_entry passes through unvalidated to jit_repipe_debug_info(), which stores it as jd->nr_debug_entries. Downstream, jit_process_debug_info() in genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), which calls strlen() on each entry's name field — a crafted nr_entry causes OOB reads and writes. Add bounds-checked iteration in jit_repipe_debug_info() that validates each debug_entry fits in the payload and its name is NUL-terminated before calling debug_entry_next(). Clamp nr_debug_entries to the count of valid entries. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index d3de307532d55..5a3ea2681fb37 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) [Severity: Medium] This is a pre-existing issue, but in jit_repipe_code_move(), the synthetic MMAP2 event allocation hardcodes a +16 byte hack for the sample ID header: tools/perf/util/jitdump.c:jit_repipe_code_move() { ... event = calloc(1, sizeof(*event) + 16); ... } The sample ID header size (idr_size) can be up to 48 or 64 bytes depending on the perf record configuration. If the JIT path length is very long, the clamped size pushes event->mmap2.header.size to exceed the allocated buffer size. When jit_inject_event() writes the event out: tools/perf/util/jitdump.c:jit_repipe_code_move() { ... ret = jit_inject_event(jd, event); ... } Could this read past the allocated heap block and leak uninitialized heap memory into perf.data? > > static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > { > - void *data; > - size_t sz; > + struct debug_entry *ent; > + void *data, *end; > + size_t sz, valid; > + uint64_t i; > > if (!(jd && jr)) > return -1; [Severity: Medium] This is a pre-existing issue, but if malloc() fails in jit_repipe_debug_info(): tools/perf/util/jitdump.c:jit_repipe_debug_info() { ... data = malloc(sz); if (!data) return -1; ... } The function returns early without clearing the previously allocated jd->debug_data. Since the caller jit_process_dump() ignores this error, will the next JIT_CODE_LOAD erroneously use the leftover stale debug_data and attach it to the new code? > @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > jd->debug_data = data; > > /* > - * we must use nr_entry instead of size here because > - * we cannot distinguish actual entry from padding otherwise > + * Clamp nr_debug_entries to entries that actually fit in the > + * payload. The byte-swap path already does this for cross-endian > + * files; validate on the native path too, since downstream > + * jit_process_debug_info() iterates via debug_entry_next() which > + * calls strlen() on each entry's name field. > */ > - jd->nr_debug_entries = jr->info.nr_entry; > + end = data + sz; > + ent = data; > + valid = 0; > + for (i = 0; i < jr->info.nr_entry; i++) { > + if ((void *)ent + sizeof(*ent) > end) > + break; > + /* name must be NUL-terminated within the payload */ > + if (!memchr(ent->name, '\0', (char *)end - ent->name)) > + break; > + ent = debug_entry_next(ent); [Severity: Medium] This is a pre-existing issue, but debug_entry_next() advances the pointer without guaranteeing 8-byte alignment. Later, when unaligned ent pointers are dereferenced to read the uint64_t addr field, either in the byte-swap path: tools/perf/util/jitdump.c:jit_get_next_entry() { ... ent->addr = bswap_64(ent->addr); ... } or downstream during iteration: tools/perf/util/genelf_debug.c:jit_process_debug_info() { ... ent = debug_entry_next(ent); ... } Will this cause undefined behavior and a SIGBUS crash on architectures that enforce strict alignment, like SPARC? > + valid++; > + } > + jd->nr_debug_entries = valid; > > return 0; > } [Severity: High] This isn't a bug introduced by this patch, but while processing JIT_CODE_LOAD records, jit_repipe_code_load() extracts the sym pointer from the payload: tools/perf/util/jitdump.c:jit_repipe_code_load() { ... sym = (void *)((unsigned long)jr + sizeof(jr->load)); ... } This extraction happens without verifying that it is NUL-terminated within the bounds of the available buffer size. Later, when jit_write_elf() computes the symbol length: tools/perf/util/genelf.c:jit_write_elf() { ... symlen = 2 + strlen(sym); ... } Might this lead to an out-of-bounds read via strlen() if a malformed record omits the NUL byte? [Severity: High] This is a pre-existing issue, but in jit_repipe_unwinding_info(), untrusted size fields are copied without validation: tools/perf/util/jitdump.c:jit_repipe_unwinding_info() { ... jd->eh_frame_hdr_size = jr->unwinding.eh_frame_hdr_size; jd->unwinding_size = jr->unwinding.unwinding_size; ... } If unwinding_header_size is greater than unwinding_size, will the calculation in jit_add_eh_frame_info() underflow? tools/perf/util/genelf.c:jit_add_eh_frame_info() { ... uint64_t unwinding_table_size = unwinding_size - unwinding_header_size; ... } Can this underflow result in a massive out-of-bounds read when the huge size is subsequently passed to libelf for the section buffer size? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805212704.267779-1-acme@kernel.org?part=10 ^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCHES v1 0/12] perf jitdump: Input validation hardening
@ 2026-08-05 13:29 Arnaldo Carvalho de Melo
2026-08-05 13:30 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo
0 siblings, 1 reply; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2026-08-05 13:29 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers,
Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users,
Arnaldo Carvalho de Melo, Stephane Eranian, Stefano Sanfilippo
Hi,
This series addresses twelve classes of input validation and resource
handling bugs in the jitdump file format parser that could cause OOB
memory access or memory leaks when processing maliciously crafted or
corrupted jitdump files.
All issues were discovered by sashiko-bot during automated review of the
jitdump code path. The bugs affect both the native-endian and byte-swap
code paths, with some checks previously only enforced during
byte-swapping.
Critical fix:
code_size validation was bypassable via int truncation. A record with
code_size in [2^31, record_size - 56] passed the existing bounds check
in jit_repipe_code_load() but truncated to a negative int when sent to
jit_process_code_load(), so the code pointer landed ~2GiB past the
record buffer, defeating the memchr() NUL scan and corrupting the
injected ELF.
Before: code_size = 0x80000010 passes the range check, then truncates
to a negative offset
After: code_size > INT_MAX is rejected up front; all subsequent code
size arithmetic stays within the record buffer
Issues fixed:
Validation and bounds checks:
- Validate code_size against both the record size and INT_MAX in
jit_repipe_code_load()
- Prevent integer underflow in the debug info size calculation
- Bounds-check the debug entry byte-swap loop
- Validate debug entries on the native (non-swap) path, matching the
existing byte-swap path checks
- Validate sym string NUL-termination in code load, bounding the
strlen() scan to the code blob
- Validate unwinding sizes against the record payload before allocating
- Check the snprintf() return before computing the header size
Stream and record handling:
- Fix the extended header read that always failed, causing records to
be misparsed
- Use dirname()'s return value in jit_open(), fixing ENOTDIR failures
- Fix funlockfile() being called on an unlocked stream in the
jit_open() error path
Resource management:
- Free the event in jit_repipe_code_move()
- Fix debug_data and unwinding_data leaks when records are overwritten
Each patch includes a Fixes: tag pointing to the offending commit,
dating back to jitdump mmap injection support (9b07e27f88b9cd78), source
line info support (598b7c6919c7bbcc), and unwinding support
(0284fecd13b6db3e), all from the original 2016 jitdump work.
Testing: Built and tested on x86_64. No existing tests cover jitdump
parsing with malformed input; test suite expansion is left for future
work. The final series was re-reviewed after the fixes (build-checked,
Fixes: tags verified); no regressions found.
AI assistance: This series was developed with assistance from Claude
(claude-opus-4.6) and Opencode (mimo-v2.5-free) for code analysis, patch
generation, and commit message composition.
Best regards,
- Arnaldo
Arnaldo Carvalho de Melo (12):
perf jitdump: Fix extended header read that always fails
perf jitdump: Validate code_size against total_size in code load
perf jitdump: Prevent integer underflow in debug info size calculation
perf jitdump: Bounds-check debug entry byte-swap loop
perf jitdump: Check snprintf return before computing header size
perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path
perf jitdump: Free event in jit_repipe_code_move()
perf jitdump: Fix debug_data and unwinding_data leaks
perf jitdump: Use dirname() return value in jit_open()
perf jitdump: Validate debug entries on native (non-swap) path
perf jitdump: Validate sym string NUL-termination in code load
perf jitdump: Validate unwinding sizes against record payload
tools/perf/util/jitdump.c | 126 ++++++++++++++++++++++++++++++++------
1 file changed, 108 insertions(+), 18 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 32+ messages in thread* [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-05 13:29 [PATCHES v1 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo @ 2026-08-05 13:30 ` Arnaldo Carvalho de Melo 2026-08-05 14:26 ` sashiko-bot 2026-08-05 19:19 ` Ian Rogers 0 siblings, 2 replies; 32+ messages in thread From: Arnaldo Carvalho de Melo @ 2026-08-05 13:30 UTC (permalink / raw) To: Namhyung Kim Cc: Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Ian Rogers, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian From: Arnaldo Carvalho de Melo <acme@redhat.com> The bounds-checking and nr_entry clamping added for the byte-swap path only runs when jd->needs_bswap is true. On native-endian files, nr_entry passes through unvalidated to jit_repipe_debug_info(), which stores it as jd->nr_debug_entries. Downstream, jit_process_debug_info() in genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), which calls strlen() on each entry's name field — a crafted nr_entry causes OOB reads and writes. Add bounds-checked iteration in jit_repipe_debug_info() that validates each debug_entry fits in the payload and its name is NUL-terminated before calling debug_entry_next(). Clamp nr_debug_entries to the count of valid entries. Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") Reported-by: sashiko-bot <sashiko-bot@kernel.org> Cc: Stephane Eranian <eranian@google.com> Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> --- tools/perf/util/jitdump.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 02840dbf8a1fc16c..87612ef3e232598e 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) { - void *data; - size_t sz; + struct debug_entry *ent; + void *data, *end; + size_t sz, valid; + uint64_t i; if (!(jd && jr)) return -1; @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) jd->debug_data = data; /* - * we must use nr_entry instead of size here because - * we cannot distinguish actual entry from padding otherwise + * Clamp nr_debug_entries to entries that actually fit in the + * payload. The byte-swap path already does this for cross-endian + * files; validate on the native path too, since downstream + * jit_process_debug_info() iterates via debug_entry_next() which + * calls strlen() on each entry's name field. */ - jd->nr_debug_entries = jr->info.nr_entry; + end = data + sz; + ent = data; + valid = 0; + for (i = 0; i < jr->info.nr_entry; i++) { + if ((void *)ent + sizeof(*ent) > end) + break; + /* name must be NUL-terminated within the payload */ + if (!memchr(ent->name, '\0', (char *)end - ent->name)) + break; + ent = debug_entry_next(ent); + valid++; + } + jd->nr_debug_entries = valid; return 0; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 32+ messages in thread
* Re: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-05 13:30 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo @ 2026-08-05 14:26 ` sashiko-bot 2026-08-05 19:19 ` Ian Rogers 1 sibling, 0 replies; 32+ messages in thread From: sashiko-bot @ 2026-08-05 14:26 UTC (permalink / raw) To: Arnaldo Carvalho de Melo; +Cc: linux-perf-users Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: Pre-existing issues: - [High] The JVMTI agent and debug_entry array iterates over tightly packed, variable-length structures without padding, causing unaligned memory accesses when reading or writing 64-bit and 32-bit fields. - [High] The functions `jit_get_next_entry()` and `jit_repipe_code_move()` lack bounds checking to ensure that the parsed `JIT_CODE_MOVE` record is at least `sizeof(struct jr_code_move)` bytes in length. - [High] The arguments `unwinding_header_size` and `unwinding_size` are silently truncated from 64-bit to 32-bit before being passed to `jit_write_elf()`. -- --- Patch [10]: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path --- commit 1922967864de6630181cc1d54ced351d4019f568 Author: Arnaldo Carvalho de Melo <acme@redhat.com> perf jitdump: Validate debug entries on native (non-swap) path This commit fixes an out-of-bounds read and write on native-endian files by adding bounds checking and NUL-termination validation for debug entries in jit_repipe_debug_info(). It clamps nr_debug_entries to the count of valid entries that fit in the payload. > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index 02840dbf8a1fc..87612ef3e2325 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) [Severity: High] This isn't a bug introduced by this patch, but does jit_repipe_code_move() lack bounds checking for the JIT_CODE_MOVE record size? If a crafted JIT dump provides a JIT_CODE_MOVE record with a total_size smaller than sizeof(struct jr_code_move), jit_get_next_entry() might only read the provided smaller size into jd->buf. Could extracting fields like jr->move.new_code_addr in jit_repipe_code_move() then read out-of-bounds heap memory and leak stale data into the generated perf.data file? > > static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > { > - void *data; > - size_t sz; > + struct debug_entry *ent; > + void *data, *end; > + size_t sz, valid; > + uint64_t i; [ ... ] > @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > jd->debug_data = data; > > /* > - * we must use nr_entry instead of size here because > - * we cannot distinguish actual entry from padding otherwise > + * Clamp nr_debug_entries to entries that actually fit in the > + * payload. The byte-swap path already does this for cross-endian > + * files; validate on the native path too, since downstream > + * jit_process_debug_info() iterates via debug_entry_next() which > + * calls strlen() on each entry's name field. > */ > - jd->nr_debug_entries = jr->info.nr_entry; > + end = data + sz; > + ent = data; > + valid = 0; > + for (i = 0; i < jr->info.nr_entry; i++) { > + if ((void *)ent + sizeof(*ent) > end) > + break; > + /* name must be NUL-terminated within the payload */ > + if (!memchr(ent->name, '\0', (char *)end - ent->name)) > + break; > + ent = debug_entry_next(ent); [Severity: High] This is a pre-existing issue, but does advancing the pointer this way lead to unaligned memory accesses? Looking at tools/perf/util/jitdump.h, debug_entry_next() computes the next pointer without enforcing 8-byte alignment: static inline struct debug_entry * debug_entry_next(struct debug_entry *ent) { void *a = ent + 1; size_t l = strlen(ent->name) + 1; return a + l; } Since the variable-length name string is not padded, the returned pointer might not be 64-bit aligned. When jit_process_debug_info() or jit_get_next_entry() subsequently accesses ent->addr (a 64-bit integer), could this trigger a SIGBUS crash on architectures that enforce strict alignment? > + valid++; > + } > + jd->nr_debug_entries = valid; > > return 0; > } [Severity: High] This is also a pre-existing issue, but does jit_emit_elf() silently truncate 64-bit size values? In tools/perf/util/jitdump.c, jit_repipe_code_load() passes the 64-bit fields jd->eh_frame_hdr_size and jd->unwinding_size to jit_emit_elf(): ret = jit_emit_elf(jd, filename, sym, addr, (const void *)uaddr, csize, jd->debug_data, jd->nr_debug_entries, jd->unwinding_data, jd->eh_frame_hdr_size, jd->unwinding_size); However, jit_emit_elf() defines these parameters as 32-bit integers: void *unwinding, uint32_t unwinding_header_size, uint32_t unwinding_size) If a crafted JIT dump provides 64-bit sizes that are truncated when passed to jit_emit_elf(), could this result in an unwinding_size smaller than unwinding_header_size? When jit_write_elf() widens these back to 64-bit and subtracts them, could this underflow the unwinding_table_size and cause massive out-of-bounds operations during ELF generation? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260805133013.235016-1-acme@kernel.org?part=10 ^ permalink raw reply [flat|nested] 32+ messages in thread
* Re: [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path 2026-08-05 13:30 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo 2026-08-05 14:26 ` sashiko-bot @ 2026-08-05 19:19 ` Ian Rogers 1 sibling, 0 replies; 32+ messages in thread From: Ian Rogers @ 2026-08-05 19:19 UTC (permalink / raw) To: Arnaldo Carvalho de Melo Cc: Namhyung Kim, Ingo Molnar, Thomas Gleixner, James Clark, Jiri Olsa, Adrian Hunter, Clark Williams, linux-kernel, linux-perf-users, Arnaldo Carvalho de Melo, sashiko-bot, Stephane Eranian On Wed, Aug 5, 2026 at 6:32 AM Arnaldo Carvalho de Melo <acme@kernel.org> wrote: > > From: Arnaldo Carvalho de Melo <acme@redhat.com> > > The bounds-checking and nr_entry clamping added for the byte-swap path > only runs when jd->needs_bswap is true. On native-endian files, nr_entry > passes through unvalidated to jit_repipe_debug_info(), which stores it > as jd->nr_debug_entries. Downstream, jit_process_debug_info() in > genelf_debug.c iterates nr_debug_entries times via debug_entry_next(), > which calls strlen() on each entry's name field — a crafted nr_entry > causes OOB reads and writes. > > Add bounds-checked iteration in jit_repipe_debug_info() that validates > each debug_entry fits in the payload and its name is NUL-terminated > before calling debug_entry_next(). Clamp nr_debug_entries to the count > of valid entries. > > Fixes: 598b7c6919c7bbcc ("perf jit: add source line info support") > Reported-by: sashiko-bot <sashiko-bot@kernel.org> > Cc: Stephane Eranian <eranian@google.com> > Assisted-by: Claude:claude-opus-4.6 > Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Reviewed-by: Ian Rogers <irogers@google.com> Thanks! Ian > --- > tools/perf/util/jitdump.c | 27 ++++++++++++++++++++++----- > 1 file changed, 22 insertions(+), 5 deletions(-) > > diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c > index 02840dbf8a1fc16c..87612ef3e232598e 100644 > --- a/tools/perf/util/jitdump.c > +++ b/tools/perf/util/jitdump.c > @@ -694,8 +694,10 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) > > static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > { > - void *data; > - size_t sz; > + struct debug_entry *ent; > + void *data, *end; > + size_t sz, valid; > + uint64_t i; > > if (!(jd && jr)) > return -1; > @@ -715,10 +717,25 @@ static int jit_repipe_debug_info(struct jit_buf_desc *jd, union jr_entry *jr) > jd->debug_data = data; > > /* > - * we must use nr_entry instead of size here because > - * we cannot distinguish actual entry from padding otherwise > + * Clamp nr_debug_entries to entries that actually fit in the > + * payload. The byte-swap path already does this for cross-endian > + * files; validate on the native path too, since downstream > + * jit_process_debug_info() iterates via debug_entry_next() which > + * calls strlen() on each entry's name field. > */ > - jd->nr_debug_entries = jr->info.nr_entry; > + end = data + sz; > + ent = data; > + valid = 0; > + for (i = 0; i < jr->info.nr_entry; i++) { > + if ((void *)ent + sizeof(*ent) > end) > + break; > + /* name must be NUL-terminated within the payload */ > + if (!memchr(ent->name, '\0', (char *)end - ent->name)) > + break; > + ent = debug_entry_next(ent); > + valid++; > + } > + jd->nr_debug_entries = valid; > > return 0; > } > -- > 2.55.0 > ^ permalink raw reply [flat|nested] 32+ messages in thread
end of thread, other threads:[~2026-08-31 13:35 UTC | newest] Thread overview: 32+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-31 13:10 [PATCHES v4 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo 2026-08-31 13:10 ` [PATCH 01/12] perf jitdump: Fix extended header read that always fails Arnaldo Carvalho de Melo 2026-08-31 13:22 ` sashiko-bot 2026-08-31 13:10 ` [PATCH 02/12] perf jitdump: Fix debug_data and unwinding_data leaks Arnaldo Carvalho de Melo 2026-08-31 13:24 ` sashiko-bot 2026-08-31 13:10 ` [PATCH 03/12] perf jitdump: Validate code_size against total_size in code load Arnaldo Carvalho de Melo 2026-08-31 13:21 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 04/12] perf jitdump: Prevent integer underflow in debug info size calculation Arnaldo Carvalho de Melo 2026-08-31 13:22 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 05/12] perf jitdump: Bounds-check debug entry byte-swap loop Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 06/12] perf jitdump: Check snprintf return before computing header size Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 07/12] perf jitdump: Fix funlockfile on unlocked stream in jit_open() error path Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 08/12] perf jitdump: Free event in jit_repipe_code_move() Arnaldo Carvalho de Melo 2026-08-31 13:21 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 09/12] perf jitdump: Use dirname() return value in jit_open() Arnaldo Carvalho de Melo 2026-08-31 13:19 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo 2026-08-31 13:23 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 11/12] perf jitdump: Validate sym string NUL-termination in code load Arnaldo Carvalho de Melo 2026-08-31 13:31 ` sashiko-bot 2026-08-31 13:11 ` [PATCH 12/12] perf jitdump: Validate unwinding sizes against record payload Arnaldo Carvalho de Melo 2026-08-31 13:35 ` sashiko-bot -- strict thread matches above, loose matches on Subject: below -- 2026-08-06 12:35 [PATCHES v3 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo 2026-08-06 12:36 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo 2026-08-06 13:10 ` sashiko-bot 2026-08-05 21:26 [PATCHES v2 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo 2026-08-05 21:27 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo 2026-08-05 22:00 ` sashiko-bot 2026-08-05 13:29 [PATCHES v1 0/12] perf jitdump: Input validation hardening Arnaldo Carvalho de Melo 2026-08-05 13:30 ` [PATCH 10/12] perf jitdump: Validate debug entries on native (non-swap) path Arnaldo Carvalho de Melo 2026-08-05 14:26 ` sashiko-bot 2026-08-05 19:19 ` Ian Rogers
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.