Linux Perf Users
 help / color / mirror / Atom feed
* [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers
@ 2026-09-19  0:55 Aaron Tomlin
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing Aaron Tomlin
                   ` (7 more replies)
  0 siblings, 8 replies; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented syscall arguments in perf trace, raw payload
data captured from BPF programs is passed to various argument formatters
via struct syscall_arg.

However, when processing malformed, truncated, or untrusted perf.data
records (e.g. truncated reads in BPF ringbuffers, cross-architecture
replays, or crafted sample records), the payload can be shorter than
expected or contain invalid size fields:
    1.  Dereferencing augmented_arg fields before validating that
        arg->augmented.size is at least sizeof(struct augmented_arg) can read
        past the available buffer.

    2.  Passing augmented_arg->size to formatters or loop counters without
        bounding it against the remaining buffer can cause out-of-bounds memory
        reads.

    3.  In multi-argument syscalls (e.g. rename*), calculating consumed bytes
        without 64-bit alignment advances arg->augmented.args to unaligned
        addresses. Furthermore, calculating consumed offsets without bounds
        checking can overflow signed integer bounds or cause arg->augmented.size
        to underflow, advancing arg->augmented.args out of bounds and
        corrupting the parsing state for all subsequent arguments.

    4.  Type/family-specific beautifiers (i.e. BTF struct dump, sockaddr,
        timespec, perf_event_attr) can dereference structure fields without
        verifying that the payload contains sufficient bytes for the target
        type, or trust embedded size fields (such as attr->size) that exceed
        the actual captured buffer.

This series adds comprehensive upper-bound and payload-size checks across
all augmented argument beautifiers in perf trace, enforces 64-bit pointer
alignment when consuming multi-argument payloads, and ensures extensible
dispatching for address family formatters. If validation fails in any
beautifier, it cleanly falls back to printing the raw pointer/hex value.

To facilitate clean, conflict-free backports across active LTS kernels,
each fix is isolated to its own commit.

Changes since v2:

 - Expanded the series from 6 to 7 patches by splitting the string
   beautifier pointer advancement and 64-bit alignment logic into a
   dedicated patch

 - Added a new patch to round up consumed payload bytes to 64-bit
   boundaries using PERF_ALIGN(), matching the alignment produced by the
   BPF tracepoint probes (sys_enter_rename*) in
   augmented_raw_syscalls.bpf.c

 - Reset arg->augmented on buffer overrun to prevent corrupted parsing
   state from reading out of bounds on subsequent arguments

 - Validated payload size directly against arg->augmented.size instead of
   reading augmented_arg->size, which is unpopulated by the BPF tracer
   (sys_enter_{clock_,}nanosleep) and contains stale per-CPU map data

 - Refactored af_scnprintfs into a dispatch table associating each
   formatter with its minimum required payload size (.min_size), preserving
   extensibility for future address families without hardcoded conditionals

 - Used offsetof(struct sockaddr_un, sun_path) + 1 for AF_LOCAL rather than
   sizeof(struct sockaddr_un) to correctly accommodate variable-length
   domain socket paths

 - Validated payload size against arg->augmented.size and payload_size
   rather than reading uninitialized augmented_arg->size

 - Validated payload size directly against arg->augmented.size instead of
   reading uninitialized augmented_arg->size, which is unpopulated by
   sys_enter_perf_event_open()

 - Verified that when attr->size is specified, it is at least
   PERF_ATTR_SIZE_VER0 and does not exceed payload_size, preventing
   out-of-bounds reads in perf_event_attr__fprintf() caused by malformed
   records or TOCTOU mutations during trace capture

 - Link to v2: https://lore.kernel.org/lkml/20260907015140.363076-1-atomlin@atomlin.com/

Changes since v1:

 - Expanded the original single patch into a 6-patch series in response to
   reviewer feedback from sashiko-bot regarding similar bounds check
   omissions across other augmented formatters in perf trace

 - Added new patch validating payload bounds and consumed offset
   calculations in syscall_arg__scnprintf_augmented_string()

 - Added new patch validating payload bounds before byte traversal in
   syscall_arg__scnprintf_buf(), isolated to ensure an independent Fixes:
   tag for stable backports

 - Added new patch validating payload size against sizeof(struct timespec)
   in syscall_arg__scnprintf_augmented_timespec()

 - Added new patch validating payload bounds and family-specific lengths in
   syscall_arg__scnprintf_augmented_sockaddr()

 - Added new patch validating payload size against at least
   PERF_ATTR_SIZE_VER0 in
   syscall_arg__scnprintf_augmented_perf_event_attr()

 - Link to v1: https://lore.kernel.org/all/20260906011132.279321-1-atomlin@atomlin.com/

Aaron Tomlin (7):
  perf trace: Add upper bound checks for augmented BTF struct printing
  perf trace: Validate payload bounds in augmented string beautifier
  perf trace: Align pointer advance in augmented string beautifier
  perf trace: Validate payload bounds in augmented buffer beautifier
  perf trace beauty: Validate payload size in augmented timespec
    beautifier
  perf trace beauty: Validate payload size in augmented sockaddr
    beautifier
  perf trace beauty: Validate payload size in augmented perf_event_open
    beautifier

 tools/perf/builtin-trace.c                | 45 +++++++++++++++++------
 tools/perf/trace/beauty/perf_event_open.c | 23 ++++++++++--
 tools/perf/trace/beauty/sockaddr.c        | 35 +++++++++++++-----
 tools/perf/trace/beauty/timespec.c        | 15 ++++++--
 4 files changed, 91 insertions(+), 27 deletions(-)


base-commit: 02f6847e1822714a4201b87e42f92b0d43e8549d
-- 
2.55.0


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:07   ` sashiko-bot
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 2/7] perf trace: Validate payload bounds in augmented string beautifier Aaron Tomlin
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented struct payloads using BTF via
btf_struct_scnprintf(), augmented_arg->size is currently only validated
against values <= 0.

However, several edge cases can result in size mismatches or buffer
over-reads:
    1.  If arg->augmented.size is smaller than sizeof(*augmented_arg),
        dereferencing augmented_arg->size reads past the available
        buffer.

    2.  If augmented_arg->size exceeds arg->augmented.size -
        sizeof(*augmented_arg), calculating consumed =
        sizeof(*augmented_arg) + augmented_arg->size can overflow signed
        integer limits (e.g., with crafted INT_MAX values in an
        untrusted perf.data file) or cause arg->augmented.size to
        underflow. This advances arg->augmented.args out of bounds,
        corrupting the parsing state for subsequent arguments in
        multi-argument syscalls.

    3.  If the captured payload is truncated (e.g., short reads in BPF,
        or during cross-architecture analysis such as replaying a 32-bit
        perf.data on a 64-bit host where host BTF type->size exceeds the
        32-bit target payload), passing type->size to
        btf_dump__dump_type_data() causes libbpf to read past the end of
        the payload buffer.

Enforce an upper bound on augmented_arg->size against the remaining
buffer (arg->augmented.size - sizeof(*augmented_arg)) and verify that the
captured payload contains at least type->size bytes before passing it to
btf_dump__dump_type_data().

Fixes: cb32035214b9 ("perf trace: Pretty print struct data")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/builtin-trace.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index be19d70eba09..20fffc24507b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1133,12 +1133,13 @@ static size_t btf_struct_scnprintf(const struct btf_type *type, struct btf *btf,
 	LIBBPF_OPTS(btf_dump_opts, dump_opts);
 	LIBBPF_OPTS(btf_dump_type_data_opts, dump_data_opts);
 
-	if (arg == NULL || arg->augmented.args == NULL || arg->augmented.size <= 0 ||
+	if (arg == NULL || arg->augmented.args == NULL || arg->augmented.size < (int)sizeof(*augmented_arg) ||
 	    arg->fmt == NULL || !arg->fmt->from_user)
 		return 0;
 
 	augmented_arg = arg->augmented.args;
-	if (augmented_arg->size <= 0)
+	if (augmented_arg->size <= 0 || augmented_arg->size > arg->augmented.size - (int)sizeof(*augmented_arg) ||
+	    (size_t)augmented_arg->size < type->size)
 		return 0;
 
 	dump_data_opts.compact	  = true;
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 2/7] perf trace: Validate payload bounds in augmented string beautifier
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:08   ` sashiko-bot
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 3/7] perf trace: Align pointer advance " Aaron Tomlin
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented string arguments via
syscall_arg__scnprintf_augmented_string(), augmented_arg->size is not
validated against the remaining buffer size (arg->augmented.size).

If a malformed or truncated perf.data record provides an invalid or
excessively large augmented_arg->size:
    1.  If arg->augmented.size is smaller than sizeof(*augmented_arg),
        dereferencing augmented_arg->size reads past the available
        buffer.

    2.  Calculating consumed = sizeof(*augmented_arg) +
        augmented_arg->size can overflow signed integer bounds or cause
        arg->augmented.size to underflow, advancing arg->augmented.args
        out of bounds and corrupting the parsing state for subsequent
        arguments in multi-argument syscalls.

Validate that arg->augmented.size is large enough to hold
sizeof(*augmented_arg) and that augmented_arg->size is within the bounds
of the remaining buffer before printing or calculating consumed bytes.
If validation fails, fall back to printing the raw pointer value.

Fixes: 8195168e8779 ("perf trace: Consume the augmented_raw_syscalls payload")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/builtin-trace.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 20fffc24507b..91461ab927b6 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1898,12 +1898,21 @@ static void thread__set_filename_pos(struct thread *thread, const char *bf,
 static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, char *bf, size_t size)
 {
 	struct augmented_arg *augmented_arg = arg->augmented.args;
-	size_t printed = scnprintf(bf, size, "\"%.*s\"", augmented_arg->size, augmented_arg->value);
+	size_t printed;
+	int consumed;
+
+	if (arg->augmented.size < (int)sizeof(*augmented_arg))
+		return 0;
+
+	if (augmented_arg->size <= 0 || augmented_arg->size > arg->augmented.size - (int)sizeof(*augmented_arg))
+		return 0;
+
+	printed = scnprintf(bf, size, "\"%.*s\"", augmented_arg->size, augmented_arg->value);
 	/*
 	 * So that the next arg with a payload can consume its augmented arg, i.e. for rename* syscalls
 	 * we would have two strings, each prefixed by its size.
 	 */
-	int consumed = sizeof(*augmented_arg) + augmented_arg->size;
+	consumed = sizeof(*augmented_arg) + augmented_arg->size;
 
 	arg->augmented.args = ((void *)arg->augmented.args) + consumed;
 	arg->augmented.size -= consumed;
@@ -1916,8 +1925,12 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
 {
 	unsigned long ptr = arg->val;
 
-	if (arg->augmented.args)
-		return syscall_arg__scnprintf_augmented_string(arg, bf, size);
+	if (arg->augmented.args) {
+		size_t printed = syscall_arg__scnprintf_augmented_string(arg, bf, size);
+
+		if (printed)
+			return printed;
+	}
 
 	if (!arg->trace->vfs_getname)
 		return scnprintf(bf, size, "%#x", ptr);
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 3/7] perf trace: Align pointer advance in augmented string beautifier
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing Aaron Tomlin
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 2/7] perf trace: Validate payload bounds in augmented string beautifier Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:08   ` sashiko-bot
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 4/7] perf trace: Validate payload bounds in augmented buffer beautifier Aaron Tomlin
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented string arguments via
syscall_arg__scnprintf_augmented_string(), the offset to advance to the
next augmented argument is computed as:

    consumed = sizeof(*augmented_arg) + augmented_arg->size;

Because sizeof(*augmented_arg) is 8 bytes, if augmented_arg->size is not
a multiple of 8 (e.g. from an unpadded capture or a malformed perf.data
file), arg->augmented.args is advanced to an unaligned memory address.

Round up the consumed payload bytes to a 64-bit boundary using
PERF_ALIGN(), matching the alignment produced by the BPF tracepoint
programs sys_enter_rename() and sys_enter_renameat2() (attached to
tp/syscalls/sys_enter_rename and tp/syscalls/sys_enter_renameat2).
If the aligned consumed offset exceeds the remaining buffer, reset
arg->augmented to prevent reading out of bounds on subsequent arguments.

Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/builtin-trace.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 91461ab927b6..21c16e4c163a 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1912,10 +1912,15 @@ static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, c
 	 * So that the next arg with a payload can consume its augmented arg, i.e. for rename* syscalls
 	 * we would have two strings, each prefixed by its size.
 	 */
-	consumed = sizeof(*augmented_arg) + augmented_arg->size;
+	consumed = sizeof(*augmented_arg) + PERF_ALIGN(augmented_arg->size, sizeof(u64));
 
-	arg->augmented.args = ((void *)arg->augmented.args) + consumed;
-	arg->augmented.size -= consumed;
+	if (consumed > arg->augmented.size) {
+		arg->augmented.args = NULL;
+		arg->augmented.size = 0;
+	} else {
+		arg->augmented.args = ((void *)arg->augmented.args) + consumed;
+		arg->augmented.size -= consumed;
+	}
 
 	return printed;
 }
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 4/7] perf trace: Validate payload bounds in augmented buffer beautifier
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
                   ` (2 preceding siblings ...)
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 3/7] perf trace: Align pointer advance " Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:09   ` sashiko-bot
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 5/7] perf trace beauty: Validate payload size in augmented timespec beautifier Aaron Tomlin
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing non-string augmented buffers via
syscall_arg__scnprintf_buf(), augmented_arg->size is not validated
against the remaining buffer size (arg->augmented.size).

If a malformed or truncated perf.data record provides an invalid or
excessively large augmented_arg->size:
    1.  If arg->augmented.size is smaller than sizeof(*augmented_arg),
        dereferencing augmented_arg->size reads past the available
        buffer.

    2.  The loop reads up to augmented_arg->size bytes from
        augmented_arg->value without verifying that they exist within
        the buffer, leading to buffer over-reads.

    3.  Calculating consumed = sizeof(*augmented_arg) +
        augmented_arg->size can overflow signed integer bounds or cause
        arg->augmented.size to underflow, advancing arg->augmented.args
        out of bounds and corrupting the parsing state for subsequent
        arguments in multi-argument syscalls.

Validate that arg->augmented.size is large enough to hold
sizeof(*augmented_arg) and that augmented_arg->size is within the bounds
of the remaining buffer before iterating or calculating consumed bytes.
If validation fails, fall back to printing the raw pointer value.

Fixes: b257fac12f38 ("perf trace: Pretty print buffer data")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/builtin-trace.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 21c16e4c163a..af1ca4c02a57 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1950,13 +1950,17 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
 static size_t syscall_arg__scnprintf_buf(char *bf, size_t size, struct syscall_arg *arg)
 {
 	struct augmented_arg *augmented_arg = arg->augmented.args;
-	unsigned char *orig = (unsigned char *)augmented_arg->value;
+	unsigned char *orig;
 	size_t printed = 0;
 	int consumed;
 
-	if (augmented_arg == NULL)
-		return 0;
+	if (augmented_arg == NULL || arg->augmented.size < (int)sizeof(*augmented_arg))
+		return scnprintf(bf, size, "%#lx", arg->val);
+
+	if (augmented_arg->size <= 0 || augmented_arg->size > arg->augmented.size - (int)sizeof(*augmented_arg))
+		return scnprintf(bf, size, "%#lx", arg->val);
 
+	orig = (unsigned char *)augmented_arg->value;
 	for (int j = 0; j < augmented_arg->size; ++j) {
 		bool control_char = orig[j] <= MAX_CONTROL_CHAR || orig[j] >= MAX_ASCII;
 		/* print control characters (0~31 and 127), and non-ascii characters in \(digits) */
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 5/7] perf trace beauty: Validate payload size in augmented timespec beautifier
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
                   ` (3 preceding siblings ...)
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 4/7] perf trace: Validate payload bounds in augmented buffer beautifier Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:08   ` sashiko-bot
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 6/7] perf trace beauty: Validate payload size in augmented sockaddr beautifier Aaron Tomlin
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented timespec arguments via
syscall_arg__scnprintf_augmented_timespec(), arg->augmented.args->value
is cast to struct timespec without verifying that the captured payload
is large enough to hold the structure.

If a malformed or truncated perf.data record provides an augmented
payload smaller than sizeof(struct timespec), accessing ts->tv_sec or
ts->tv_nsec reads memory past the end of the available buffer.

Validate that arg->augmented.size contains at least
sizeof(struct augmented_arg) + sizeof(struct timespec) bytes before
dereferencing ts->tv_sec and ts->tv_nsec. If validation fails, fall back
to printing the raw pointer value.

Fixes: 6ac73820993c ("perf trace: Add augmenter for clock_gettime's rqtp timespec arg")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/trace/beauty/timespec.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/tools/perf/trace/beauty/timespec.c b/tools/perf/trace/beauty/timespec.c
index b14ab72a2738..84755d8d2c87 100644
--- a/tools/perf/trace/beauty/timespec.c
+++ b/tools/perf/trace/beauty/timespec.c
@@ -7,15 +7,24 @@
 
 static size_t syscall_arg__scnprintf_augmented_timespec(struct syscall_arg *arg, char *bf, size_t size)
 {
-	struct timespec *ts = (struct timespec *)arg->augmented.args->value;
+	struct augmented_arg *augmented_arg = arg->augmented.args;
+	struct timespec *ts;
 
+	if (arg->augmented.size < (int)(sizeof(*augmented_arg) + sizeof(*ts)))
+		return 0;
+
+	ts = (struct timespec *)augmented_arg->value;
 	return scnprintf(bf, size, "{ .tv_sec: %" PRIu64 ", .tv_nsec: %" PRIu64 " }", ts->tv_sec, ts->tv_nsec);
 }
 
 size_t syscall_arg__scnprintf_timespec(char *bf, size_t size, struct syscall_arg *arg)
 {
-	if (arg->augmented.args)
-		return syscall_arg__scnprintf_augmented_timespec(arg, bf, size);
+	if (arg->augmented.args) {
+		size_t printed = syscall_arg__scnprintf_augmented_timespec(arg, bf, size);
+
+		if (printed)
+			return printed;
+	}
 
 	return scnprintf(bf, size, "%#lx", arg->val);
 }
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 6/7] perf trace beauty: Validate payload size in augmented sockaddr beautifier
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
                   ` (4 preceding siblings ...)
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 5/7] perf trace beauty: Validate payload size in augmented timespec beautifier Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:05   ` sashiko-bot
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 7/7] perf trace beauty: Validate payload size in augmented perf_event_open beautifier Aaron Tomlin
  2026-09-30 18:29 ` [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented sockaddr arguments via
syscall_arg__scnprintf_augmented_sockaddr(), &arg->augmented.args->value
is cast to struct sockaddr without checking whether the captured payload
is large enough to hold the socket address.

If a malformed or truncated perf.data record provides an augmented
payload smaller than sizeof(sa->sa_family), accessing sa->sa_family or
dereferencing family-specific fields (e.g. struct sockaddr_in,
sockaddr_in6, or sockaddr_un) reads memory past the available buffer.

Validate that arg->augmented.size contains at least
sizeof(struct augmented_arg) + sizeof(sa->sa_family) bytes before
accessing sa->sa_family. Associate each address family formatter in
af_scnprintfs with its minimum required payload size, and ensure that the
captured payload contains sufficient bytes before invoking the
family-specific formatter. If validation fails, fall back to printing
the raw pointer value.

Fixes: d5a7e6613b00 ("perf trace augmented_syscalls: Augment connect's 'sockaddr' arg")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/trace/beauty/sockaddr.c | 35 ++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c
index a17a27ac2a6f..98fdabc99781 100644
--- a/tools/perf/trace/beauty/sockaddr.c
+++ b/tools/perf/trace/beauty/sockaddr.c
@@ -39,31 +39,48 @@ static size_t af_local__scnprintf(struct sockaddr *sa, char *bf, size_t size)
 	return scnprintf(bf, size, ", path: %s", sun->sun_path);
 }
 
-static size_t (*af_scnprintfs[])(struct sockaddr *sa, char *bf, size_t size) = {
-	[AF_LOCAL] = af_local__scnprintf,
-	[AF_INET]  = af_inet__scnprintf,
-	[AF_INET6] = af_inet6__scnprintf,
+static const struct af_scnprintf {
+	size_t (*scnprintf)(struct sockaddr *sa, char *bf, size_t size);
+	size_t min_size;
+} af_scnprintfs[] = {
+	[AF_LOCAL] = { af_local__scnprintf, offsetof(struct sockaddr_un, sun_path) + 1 },
+	[AF_INET]  = { af_inet__scnprintf,  sizeof(struct sockaddr_in) },
+	[AF_INET6] = { af_inet6__scnprintf, sizeof(struct sockaddr_in6) },
 };
 
 static size_t syscall_arg__scnprintf_augmented_sockaddr(struct syscall_arg *arg, char *bf, size_t size)
 {
-	struct sockaddr *sa = (struct sockaddr *)&arg->augmented.args->value;
+	struct augmented_arg *augmented_arg = arg->augmented.args;
+	size_t payload_size;
+	struct sockaddr *sa;
 	char family[32];
 	size_t printed;
 
+	if (arg->augmented.size < (int)(sizeof(*augmented_arg) + sizeof(sa->sa_family)))
+		return 0;
+
+	sa = (struct sockaddr *)augmented_arg->value;
+	payload_size = arg->augmented.size - sizeof(*augmented_arg);
+
 	strarray__scnprintf(&strarray__socket_families, family, sizeof(family), "%d", arg->show_string_prefix, sa->sa_family);
 	printed = scnprintf(bf, size, "{ .family: %s", family);
 
-	if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family])
-		printed += af_scnprintfs[sa->sa_family](sa, bf + printed, size - printed);
+	if (sa->sa_family < ARRAY_SIZE(af_scnprintfs) && af_scnprintfs[sa->sa_family].scnprintf &&
+	    payload_size >= af_scnprintfs[sa->sa_family].min_size)
+		printed += af_scnprintfs[sa->sa_family].scnprintf(sa, bf + printed,
+								  size - printed);
 
 	return printed + scnprintf(bf + printed, size - printed, " }");
 }
 
 size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg *arg)
 {
-	if (arg->augmented.args)
-		return syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size);
+	if (arg->augmented.args) {
+		size_t printed = syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size);
+
+		if (printed)
+			return printed;
+	}
 
 	return scnprintf(bf, size, "%#lx", arg->val);
 }
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v3 perf-tools-next 7/7] perf trace beauty: Validate payload size in augmented perf_event_open beautifier
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
                   ` (5 preceding siblings ...)
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 6/7] perf trace beauty: Validate payload size in augmented sockaddr beautifier Aaron Tomlin
@ 2026-09-19  0:55 ` Aaron Tomlin
  2026-09-19  1:04   ` sashiko-bot
  2026-09-30 18:29 ` [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
  7 siblings, 1 reply; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-19  0:55 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, atomlin, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel

When pretty-printing augmented perf_event_attr arguments via
syscall_arg__scnprintf_augmented_perf_event_attr(),
arg->augmented.args->value is cast to struct perf_event_attr and read
without verifying that the captured payload is large enough to contain
at least PERF_ATTR_SIZE_VER0 bytes.

If a malformed or truncated perf.data record provides an augmented
payload smaller than PERF_ATTR_SIZE_VER0, accessing attr->size or
executing memcpy(&local_attr, attr, PERF_ATTR_SIZE_VER0) reads memory
past the end of the available buffer. Furthermore, when attr->size is
specified, accessing fields up to attr->size without verifying that
the captured payload contains at least that many bytes risks out-of-bounds
reads.

Validate that arg->augmented.size is at least
sizeof(struct augmented_arg) + PERF_ATTR_SIZE_VER0. If attr->size is
non-zero, verify that it is at least PERF_ATTR_SIZE_VER0 and that the
captured payload contains sufficient bytes before proceeding with
pretty-printing. If validation fails, fall back to printing the raw
pointer value.

Fixes: a9cd6c676685 ("perf trace: Add BPF augmenter to perf_event_open()'s 'struct perf_event_attr' arg")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
 tools/perf/trace/beauty/perf_event_open.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
index 6315b46bcdf0..92f84472e7fd 100644
--- a/tools/perf/trace/beauty/perf_event_open.c
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -81,8 +81,16 @@ static size_t perf_event_attr___scnprintf(struct perf_event_attr *attr, char *bf
 
 static size_t syscall_arg__scnprintf_augmented_perf_event_attr(struct syscall_arg *arg, char *bf, size_t size)
 {
-	struct perf_event_attr *attr = (void *)arg->augmented.args->value;
+	struct augmented_arg *augmented_arg = arg->augmented.args;
+	struct perf_event_attr *attr;
 	struct perf_event_attr local_attr;
+	size_t payload_size;
+
+	if (arg->augmented.size < (int)(sizeof(*augmented_arg) + PERF_ATTR_SIZE_VER0))
+		return 0;
+
+	attr = (void *)augmented_arg->value;
+	payload_size = arg->augmented.size - sizeof(*augmented_arg);
 
 	/*
 	 * augmented_raw_syscalls.bpf.c (shipped with perf) copies
@@ -93,7 +101,10 @@ static size_t syscall_arg__scnprintf_augmented_perf_event_attr(struct syscall_ar
 	 * without writing to the potentially read-only augmented
 	 * args buffer.
 	 */
-	if (!attr->size) {
+	if (attr->size) {
+		if (attr->size < PERF_ATTR_SIZE_VER0 || payload_size < attr->size)
+			return 0;
+	} else {
 		memcpy(&local_attr, attr, PERF_ATTR_SIZE_VER0);
 		memset((void *)&local_attr + PERF_ATTR_SIZE_VER0, 0,
 		       sizeof(local_attr) - PERF_ATTR_SIZE_VER0);
@@ -107,8 +118,12 @@ static size_t syscall_arg__scnprintf_augmented_perf_event_attr(struct syscall_ar
 
 size_t syscall_arg__scnprintf_perf_event_attr(char *bf, size_t size, struct syscall_arg *arg)
 {
-	if (arg->augmented.args)
-		return syscall_arg__scnprintf_augmented_perf_event_attr(arg, bf, size);
+	if (arg->augmented.args) {
+		size_t printed = syscall_arg__scnprintf_augmented_perf_event_attr(arg, bf, size);
+
+		if (printed)
+			return printed;
+	}
 
 	return scnprintf(bf, size, "%#lx", arg->val);
 }
-- 
2.55.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 7/7] perf trace beauty: Validate payload size in augmented perf_event_open beautifier
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 7/7] perf trace beauty: Validate payload size in augmented perf_event_open beautifier Aaron Tomlin
@ 2026-09-19  1:04   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:04 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

> When pretty-printing augmented perf_event_attr arguments via
> syscall_arg__scnprintf_augmented_perf_event_attr(),
> arg->augmented.args->value is cast to struct perf_event_attr and read
> without verifying that the captured payload is large enough to contain
> at least PERF_ATTR_SIZE_VER0 bytes.
> 
> If a malformed or truncated perf.data record provides an augmented
> payload smaller than PERF_ATTR_SIZE_VER0, accessing attr->size or
> executing memcpy(&local_attr, attr, PERF_ATTR_SIZE_VER0) reads memory
> past the end of the available buffer. Furthermore, when attr->size is
> specified, accessing fields up to attr->size without verifying that
> the captured payload contains at least that many bytes risks out-of-bounds
> reads.
> 
> Validate that arg->augmented.size is at least
> sizeof(struct augmented_arg) + PERF_ATTR_SIZE_VER0. If attr->size is
> non-zero, verify that it is at least PERF_ATTR_SIZE_VER0 and that the
> captured payload contains sufficient bytes before proceeding with
> pretty-printing. If validation fails, fall back to printing the raw
> pointer value.
> 
> Fixes: a9cd6c676685 ("perf trace: Add BPF augmenter to perf_event_open()'s 'struct perf_event_attr' arg")
> Reported-by: sashiko-bot <sashiko-bot@kernel.org>
> Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=7


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 6/7] perf trace beauty: Validate payload size in augmented sockaddr beautifier
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 6/7] perf trace beauty: Validate payload size in augmented sockaddr beautifier Aaron Tomlin
@ 2026-09-19  1:05   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:05 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] perf: missing stddef.h inclusion for offsetof() violating musl compatibility
--

commit 319d4746425928b01209fdee80a73a7983207fbb
Author: Aaron Tomlin <atomlin@atomlin.com>

perf trace beauty: Validate payload size in augmented sockaddr beautifier

This commit adds payload size validation to the augmented sockaddr beautifier
in perf trace. It prevents reading memory past the available buffer when
parsing malformed or truncated records.

> diff --git a/tools/perf/trace/beauty/sockaddr.c b/tools/perf/trace/beauty/sockaddr.c
> index a17a27ac2a6ff..98fdabc997812 100644
> --- a/tools/perf/trace/beauty/sockaddr.c
> +++ b/tools/perf/trace/beauty/sockaddr.c
> @@ -39,31 +39,48 @@ static size_t af_local__scnprintf(struct sockaddr *sa, char *bf, size_t size)
>  	return scnprintf(bf, size, ", path: %s", sun->sun_path);
>  }
>  
> -static size_t (*af_scnprintfs[])(struct sockaddr *sa, char *bf, size_t size) = {
> -	[AF_LOCAL] = af_local__scnprintf,
> -	[AF_INET]  = af_inet__scnprintf,
> -	[AF_INET6] = af_inet6__scnprintf,
> +static const struct af_scnprintf {
> +	size_t (*scnprintf)(struct sockaddr *sa, char *bf, size_t size);
> +	size_t min_size;
> +} af_scnprintfs[] = {
> +	[AF_LOCAL] = { af_local__scnprintf, offsetof(struct sockaddr_un, sun_path) + 1 },

[Severity: Low]
Does this code need an explicit inclusion of stddef.h for the offsetof macro?

When compiling perf tools against musl libc, relying on implicit includes can
lead to compilation failures because musl does not include headers implicitly
like glibc does. Should an explicit include for stddef.h be added to maintain
compatibility with musl?

> +	[AF_INET]  = { af_inet__scnprintf,  sizeof(struct sockaddr_in) },
> +	[AF_INET6] = { af_inet6__scnprintf, sizeof(struct sockaddr_in6) },
>  };

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=6

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing Aaron Tomlin
@ 2026-09-19  1:07   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:07 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] perf trace: btf_struct_scnprintf() fails to consume short payloads
--

commit ff5721b95fd4d48862773d326029922c1b94fdc7
Author: Aaron Tomlin <atomlin@atomlin.com>

perf trace: Add upper bound checks for augmented BTF struct printing

This commit adds upper bound checks for augmented_arg->size against the
remaining buffer size. It prevents buffer over-reads and integer
overflows when pretty-printing augmented struct payloads using BTF.

> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c

[ ... ]

> @@ -1133,12 +1133,13 @@ static size_t btf_struct_scnprintf(const struct btf_type *type, struct btf *btf,
>  	LIBBPF_OPTS(btf_dump_opts, dump_opts);
>  	LIBBPF_OPTS(btf_dump_type_data_opts, dump_data_opts);
>  
> -	if (arg == NULL || arg->augmented.args == NULL || arg->augmented.size <= 0 ||
> +	if (arg == NULL || arg->augmented.args == NULL || arg->augmented.size < (int)sizeof(*augmented_arg) ||
>  	    arg->fmt == NULL || !arg->fmt->from_user)
>  		return 0;
>  
>  	augmented_arg = arg->augmented.args;
> -	if (augmented_arg->size <= 0)
> +	if (augmented_arg->size <= 0 || augmented_arg->size > arg->augmented.size - (int)sizeof(*augmented_arg) ||
> +	    (size_t)augmented_arg->size < type->size)
>  		return 0;

[Severity: Medium]
Does this early return fail to consume the short payload?

By returning 0 here when the augmented payload is smaller than type->size, it
appears the parser abandons the payload without updating arg->augmented.args.

When the next syscall argument is formatted, will it read this stale struct
payload as its own augmented data, corrupting the parsing state for all
subsequent arguments?

Since short reads can occur legitimately during BPF tracing when capturing
large structs, should this gracefully advance past the short payload rather
than abandoning the update entirely?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=1

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 2/7] perf trace: Validate payload bounds in augmented string beautifier
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 2/7] perf trace: Validate payload bounds in augmented string beautifier Aaron Tomlin
@ 2026-09-19  1:08   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:08 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] perf: parser desynchronization on empty augmented string
--

commit c657a00bfdd12e1a3584bb0cd84d1c32e885c3a9
Author: Aaron Tomlin <atomlin@atomlin.com>

perf trace: Validate payload bounds in augmented string beautifier

This commit adds bounds checking for augmented string sizes in perf trace
to prevent out-of-bounds reads and integer overflows when parsing malformed
perf.data records. If validation fails, it falls back to raw pointer printing.

> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 20fffc24507b5..91461ab927b63 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -1898,12 +1898,21 @@ static void thread__set_filename_pos(struct thread *thread, const char *bf,
>  static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, char *bf, size_t size)
>  {
>  	struct augmented_arg *augmented_arg = arg->augmented.args;
> -	size_t printed = scnprintf(bf, size, "\"%.*s\"", augmented_arg->size, augmented_arg->value);
> +	size_t printed;
> +	int consumed;
> +
> +	if (arg->augmented.size < (int)sizeof(*augmented_arg))
> +		return 0;
> +
> +	if (augmented_arg->size <= 0 || augmented_arg->size > arg->augmented.size - (int)sizeof(*augmented_arg))
> +		return 0;

[Severity: Medium]
When a BPF program pushes an empty augmented string record (e.g., size <= 0
due to a read failure like -EFAULT), does returning early here cause the
payload parser to desynchronize?

By returning 0 without consuming the header (sizeof(*augmented_arg)) and
advancing the parsing pointer arg->augmented.args, it seems this might corrupt
the formatting of subsequent augmented arguments in multi-argument syscalls
(like link), displaying them as raw pointers because the pointer is left at
the wrong offset.

Should the header be consumed even when the size is empty or invalid to
maintain parser synchronization?

> +
> +	printed = scnprintf(bf, size, "\"%.*s\"", augmented_arg->size, augmented_arg->value);
>  	/*
>  	 * So that the next arg with a payload can consume its augmented arg, i.e. for rename* syscalls
>  	 * we would have two strings, each prefixed by its size.
>  	 */
> -	int consumed = sizeof(*augmented_arg) + augmented_arg->size;
> +	consumed = sizeof(*augmented_arg) + augmented_arg->size;
>  
>  	arg->augmented.args = ((void *)arg->augmented.args) + consumed;
>  	arg->augmented.size -= consumed;
>  
>  	return printed;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=2

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 3/7] perf trace: Align pointer advance in augmented string beautifier
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 3/7] perf trace: Align pointer advance " Aaron Tomlin
@ 2026-09-19  1:08   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:08 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] perf trace: unpadded augmented arguments corruption due to unconditional PERF_ALIGN
--

commit edc9d58d23d30decc9c0076b0136df1e5ab01c70
Author: Aaron Tomlin <atomlin@atomlin.com>

perf trace: Align pointer advance in augmented string beautifier

This commit updates the augmented string beautifier in perf trace to
round up the consumed payload bytes to an 8-byte boundary using PERF_ALIGN.
It also adds bounds checking to prevent reading out of bounds if the aligned
consumed offset exceeds the remaining buffer.

> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -1912,10 +1912,15 @@ static size_t syscall_arg__scnprintf_augmented_string(struct syscall_arg *arg, c
>  	 * So that the next arg with a payload can consume its augmented arg, i.e. for rename* syscalls
>  	 * we would have two strings, each prefixed by its size.
>  	 */
> -	consumed = sizeof(*augmented_arg) + augmented_arg->size;
> +	consumed = sizeof(*augmented_arg) + PERF_ALIGN(augmented_arg->size, sizeof(u64));

[Severity: High]
Does this unconditional alignment cause corruption when reading arguments 
produced by the generic BPF tracepoint?

The generic BPF producer, specifically augment_arg() in 
tools/perf/util/bpf_skel/augmented_raw_syscalls.bpf.c, emits unpadded, 
tightly-packed arguments. When tracing syscalls with multiple string or 
pointer arguments (such as linkat, symlinkat, or move_mount), the BPF 
program packs the strings consecutively.

Since PERF_ALIGN skips non-existent padding bytes here, could this 
over-advance the pointer and misalign the reader for the second argument, 
causing it to read arbitrary payload bytes as the size and value fields? 

Additionally, might this affect backward compatibility when analyzing 
older, unpadded perf.data files where augmented string arguments are not 
aligned to an 8-byte boundary?

>  
> -	arg->augmented.args = ((void *)arg->augmented.args) + consumed;
> -	arg->augmented.size -= consumed;
> +	if (consumed > arg->augmented.size) {
> +		arg->augmented.args = NULL;
> +		arg->augmented.size = 0;
> +	} else {
> +		arg->augmented.args = ((void *)arg->augmented.args) + consumed;
> +		arg->augmented.size -= consumed;
> +	}
>  
>  	return printed;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=3

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 5/7] perf trace beauty: Validate payload size in augmented timespec beautifier
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 5/7] perf trace beauty: Validate payload size in augmented timespec beautifier Aaron Tomlin
@ 2026-09-19  1:08   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:08 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] perf: Silently disables nanosleep augmentation on 64-bit due to BPF size mismatch
--

commit d5a8c844e701a29578b91e18d924a25e7e3167e6
Author: Aaron Tomlin <atomlin@atomlin.com>

perf trace beauty: Validate payload size in augmented timespec beautifier

This commit introduces bounds checking in the timespec beautifier to prevent
reading past the end of the available buffer if a malformed or truncated
perf.data record is provided.

> diff --git a/tools/perf/trace/beauty/timespec.c b/tools/perf/trace/beauty/timespec.c
> index b14ab72a2738e..84755d8d2c87f 100644
> --- a/tools/perf/trace/beauty/timespec.c
> +++ b/tools/perf/trace/beauty/timespec.c
> @@ -7,15 +7,24 @@
>  
>  static size_t syscall_arg__scnprintf_augmented_timespec(struct syscall_arg *arg, char *bf, size_t size)
>  {
> -	struct timespec *ts = (struct timespec *)arg->augmented.args->value;
> +	struct augmented_arg *augmented_arg = arg->augmented.args;
> +	struct timespec *ts;
>  
> +	if (arg->augmented.size < (int)(sizeof(*augmented_arg) + sizeof(*ts)))
> +		return 0;

[Severity: High]
Does this bounds check deterministically fail for the nanosleep syscall on
64-bit platforms?

When tracing the nanosleep syscall using perf trace, the BPF script
sys_enter_nanosleep incorrectly calculates its output length by omitting
sizeof(u64) for the augmented_arg header, outputting exactly 16 bytes.

The bounds check introduced here requires sizeof(*augmented_arg) + sizeof(*ts),
which is 24 bytes on 64-bit systems. Since 16 < 24, the check deterministically
fails and silently returns 0.

This disables the nanosleep augmentation feature on 64-bit systems, falling
back to raw pointer printing instead of showing the timespec structure.

> +
> +	ts = (struct timespec *)augmented_arg->value;
>  	return scnprintf(bf, size, "{ .tv_sec: %" PRIu64 ", .tv_nsec: %" PRIu64 " }", ts->tv_sec, ts->tv_nsec);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=5

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 4/7] perf trace: Validate payload bounds in augmented buffer beautifier
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 4/7] perf trace: Validate payload bounds in augmented buffer beautifier Aaron Tomlin
@ 2026-09-19  1:09   ` sashiko-bot
  0 siblings, 0 replies; 16+ messages in thread
From: sashiko-bot @ 2026-09-19  1:09 UTC (permalink / raw)
  To: Aaron Tomlin; +Cc: linux-perf-users

> When pretty-printing non-string augmented buffers via
> syscall_arg__scnprintf_buf(), augmented_arg->size is not validated
> against the remaining buffer size (arg->augmented.size).
> 
> If a malformed or truncated perf.data record provides an invalid or
> excessively large augmented_arg->size:
>     1.  If arg->augmented.size is smaller than sizeof(*augmented_arg),
>         dereferencing augmented_arg->size reads past the available
>         buffer.
> 
>     2.  The loop reads up to augmented_arg->size bytes from
>         augmented_arg->value without verifying that they exist within
>         the buffer, leading to buffer over-reads.
> 
>     3.  Calculating consumed = sizeof(*augmented_arg) +
>         augmented_arg->size can overflow signed integer bounds or cause
>         arg->augmented.size to underflow, advancing arg->augmented.args
>         out of bounds and corrupting the parsing state for subsequent
>         arguments in multi-argument syscalls.
> 
> Validate that arg->augmented.size is large enough to hold
> sizeof(*augmented_arg) and that augmented_arg->size is within the bounds
> of the remaining buffer before iterating or calculating consumed bytes.
> If validation fails, fall back to printing the raw pointer value.
> 
> Fixes: b257fac12f38 ("perf trace: Pretty print buffer data")
> Reported-by: sashiko-bot <sashiko-bot@kernel.org>
> Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260919005530.728615-1-atomlin@atomlin.com?part=4


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers
  2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
                   ` (6 preceding siblings ...)
  2026-09-19  0:55 ` [PATCH v3 perf-tools-next 7/7] perf trace beauty: Validate payload size in augmented perf_event_open beautifier Aaron Tomlin
@ 2026-09-30 18:29 ` Aaron Tomlin
  7 siblings, 0 replies; 16+ messages in thread
From: Aaron Tomlin @ 2026-09-30 18:29 UTC (permalink / raw)
  To: peterz, mingo, acme, namhyung
  Cc: mark.rutland, alexander.shishkin, jolsa, irogers, adrian.hunter,
	james.clark, howardchu95, neelx, chjohnst, sean, steve,
	rishil1999, linux-perf-users, linux-kernel, sashiko-bot

On Fri, Sep 18, 2026 at 08:55:23PM -0400, Aaron Tomlin wrote:
> When pretty-printing augmented syscall arguments in perf trace, raw payload
> data captured from BPF programs is passed to various argument formatters
> via struct syscall_arg.
> 
> However, when processing malformed, truncated, or untrusted perf.data
> records (e.g. truncated reads in BPF ringbuffers, cross-architecture
> replays, or crafted sample records), the payload can be shorter than
> expected or contain invalid size fields:
>     1.  Dereferencing augmented_arg fields before validating that
>         arg->augmented.size is at least sizeof(struct augmented_arg) can read
>         past the available buffer.
> 
>     2.  Passing augmented_arg->size to formatters or loop counters without
>         bounding it against the remaining buffer can cause out-of-bounds memory
>         reads.
> 
>     3.  In multi-argument syscalls (e.g. rename*), calculating consumed bytes
>         without 64-bit alignment advances arg->augmented.args to unaligned
>         addresses. Furthermore, calculating consumed offsets without bounds
>         checking can overflow signed integer bounds or cause arg->augmented.size
>         to underflow, advancing arg->augmented.args out of bounds and
>         corrupting the parsing state for all subsequent arguments.
> 
>     4.  Type/family-specific beautifiers (i.e. BTF struct dump, sockaddr,
>         timespec, perf_event_attr) can dereference structure fields without
>         verifying that the payload contains sufficient bytes for the target
>         type, or trust embedded size fields (such as attr->size) that exceed
>         the actual captured buffer.
> 
> This series adds comprehensive upper-bound and payload-size checks across
> all augmented argument beautifiers in perf trace, enforces 64-bit pointer
> alignment when consuming multi-argument payloads, and ensures extensible
> dispatching for address family formatters. If validation fails in any
> beautifier, it cleanly falls back to printing the raw pointer/hex value.
> 
> To facilitate clean, conflict-free backports across active LTS kernels,
> each fix is isolated to its own commit.
> 
> Changes since v2:
> 
>  - Expanded the series from 6 to 7 patches by splitting the string
>    beautifier pointer advancement and 64-bit alignment logic into a
>    dedicated patch
> 
>  - Added a new patch to round up consumed payload bytes to 64-bit
>    boundaries using PERF_ALIGN(), matching the alignment produced by the
>    BPF tracepoint probes (sys_enter_rename*) in
>    augmented_raw_syscalls.bpf.c
> 
>  - Reset arg->augmented on buffer overrun to prevent corrupted parsing
>    state from reading out of bounds on subsequent arguments
> 
>  - Validated payload size directly against arg->augmented.size instead of
>    reading augmented_arg->size, which is unpopulated by the BPF tracer
>    (sys_enter_{clock_,}nanosleep) and contains stale per-CPU map data
> 
>  - Refactored af_scnprintfs into a dispatch table associating each
>    formatter with its minimum required payload size (.min_size), preserving
>    extensibility for future address families without hardcoded conditionals
> 
>  - Used offsetof(struct sockaddr_un, sun_path) + 1 for AF_LOCAL rather than
>    sizeof(struct sockaddr_un) to correctly accommodate variable-length
>    domain socket paths
> 
>  - Validated payload size against arg->augmented.size and payload_size
>    rather than reading uninitialized augmented_arg->size
> 
>  - Validated payload size directly against arg->augmented.size instead of
>    reading uninitialized augmented_arg->size, which is unpopulated by
>    sys_enter_perf_event_open()
> 
>  - Verified that when attr->size is specified, it is at least
>    PERF_ATTR_SIZE_VER0 and does not exceed payload_size, preventing
>    out-of-bounds reads in perf_event_attr__fprintf() caused by malformed
>    records or TOCTOU mutations during trace capture
> 
>  - Link to v2: https://lore.kernel.org/lkml/20260907015140.363076-1-atomlin@atomlin.com/
> 
> Changes since v1:
> 
>  - Expanded the original single patch into a 6-patch series in response to
>    reviewer feedback from sashiko-bot regarding similar bounds check
>    omissions across other augmented formatters in perf trace
> 
>  - Added new patch validating payload bounds and consumed offset
>    calculations in syscall_arg__scnprintf_augmented_string()
> 
>  - Added new patch validating payload bounds before byte traversal in
>    syscall_arg__scnprintf_buf(), isolated to ensure an independent Fixes:
>    tag for stable backports
> 
>  - Added new patch validating payload size against sizeof(struct timespec)
>    in syscall_arg__scnprintf_augmented_timespec()
> 
>  - Added new patch validating payload bounds and family-specific lengths in
>    syscall_arg__scnprintf_augmented_sockaddr()
> 
>  - Added new patch validating payload size against at least
>    PERF_ATTR_SIZE_VER0 in
>    syscall_arg__scnprintf_augmented_perf_event_attr()
> 
>  - Link to v1: https://lore.kernel.org/all/20260906011132.279321-1-atomlin@atomlin.com/
> 
> Aaron Tomlin (7):
>   perf trace: Add upper bound checks for augmented BTF struct printing
>   perf trace: Validate payload bounds in augmented string beautifier
>   perf trace: Align pointer advance in augmented string beautifier
>   perf trace: Validate payload bounds in augmented buffer beautifier
>   perf trace beauty: Validate payload size in augmented timespec
>     beautifier
>   perf trace beauty: Validate payload size in augmented sockaddr
>     beautifier
>   perf trace beauty: Validate payload size in augmented perf_event_open
>     beautifier
> 
>  tools/perf/builtin-trace.c                | 45 +++++++++++++++++------
>  tools/perf/trace/beauty/perf_event_open.c | 23 ++++++++++--
>  tools/perf/trace/beauty/sockaddr.c        | 35 +++++++++++++-----
>  tools/perf/trace/beauty/timespec.c        | 15 ++++++--
>  4 files changed, 91 insertions(+), 27 deletions(-)
> 
> 
> base-commit: 02f6847e1822714a4201b87e42f92b0d43e8549d
> -- 
> 2.55.0
> 

Ian, Namhyung, Arnaldo,

Please drop this series from consideration in favour of Ian's series
"[PATCH v6 00/26] perf trace: Fix BPF filtering and make tracing tests
non-exclusive" (specifically patches 4 [1] and 5 [2]).

Ian's series covers the same vulnerabilities using a consolidated helper
function and addresses the unaligned packing in the BTF augmenter.

[1]: https://lore.kernel.org/lkml/20260928182605.3649015-5-irogers@google.com/
[2]: https://lore.kernel.org/lkml/20260928182605.3649015-6-irogers@google.com/

-- 
Aaron Tomlin

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-09-30 18:29 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-19  0:55 [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 1/7] perf trace: Add upper bound checks for augmented BTF struct printing Aaron Tomlin
2026-09-19  1:07   ` sashiko-bot
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 2/7] perf trace: Validate payload bounds in augmented string beautifier Aaron Tomlin
2026-09-19  1:08   ` sashiko-bot
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 3/7] perf trace: Align pointer advance " Aaron Tomlin
2026-09-19  1:08   ` sashiko-bot
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 4/7] perf trace: Validate payload bounds in augmented buffer beautifier Aaron Tomlin
2026-09-19  1:09   ` sashiko-bot
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 5/7] perf trace beauty: Validate payload size in augmented timespec beautifier Aaron Tomlin
2026-09-19  1:08   ` sashiko-bot
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 6/7] perf trace beauty: Validate payload size in augmented sockaddr beautifier Aaron Tomlin
2026-09-19  1:05   ` sashiko-bot
2026-09-19  0:55 ` [PATCH v3 perf-tools-next 7/7] perf trace beauty: Validate payload size in augmented perf_event_open beautifier Aaron Tomlin
2026-09-19  1:04   ` sashiko-bot
2026-09-30 18:29 ` [PATCH v3 perf-tools-next 0/7] perf trace: Validate payload bounds across augmented argument beautifiers Aaron Tomlin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox