[PATCH v6 03/26] perf trace: Don't read sample padding as an augmented argument

From: Ian Rogers

Date: Mon Sep 28 2026 - 14:32:32 EST


The kernel pads PERF_SAMPLE_RAW data to a u64 boundary without zeroing
the padding, so a syscall record without augmented arguments still has
up to 7 trailing bytes of stale data. syscall__augmented_args() passes
these to the beautifiers as a struct augmented_arg, whose size is then
garbage, causing a crash in syscall_arg__scnprintf_buf().

Ignore trailing data shorter than a struct augmented_arg.

Reported-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
Closes: https://lore.kernel.org/linux-perf-users/arJ-gpzqOHk-gF8T@x2/
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/builtin-trace.c | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d327603ae454..c39de91140a0 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2961,26 +2961,29 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
* traffic to just what is needed for each syscall.
*/
int args_size = raw_augmented_args_size ?: sc->args_size;
+ static uintptr_t argbuf[1024]; /* assuming single-threaded */

*augmented_args_size = sample->raw_size - args_size;
- if (*augmented_args_size > 0) {
- static uintptr_t argbuf[1024]; /* assuming single-threaded */
-
- if ((size_t)(*augmented_args_size) > sizeof(argbuf))
- return NULL;
+ /*
+ * The raw data is padded to a u64 boundary with stale bytes, so less
+ * than a struct augmented_arg is only padding.
+ */
+ if (*augmented_args_size < (int)sizeof(struct augmented_arg) ||
+ (size_t)(*augmented_args_size) > sizeof(argbuf)) {
+ *augmented_args_size = 0;
+ return NULL;
+ }

- /*
- * The perf ring-buffer is 8-byte aligned but sample->raw_data
- * is not because it's preceded by u32 size. Later, beautifier
- * will use the augmented args with stricter alignments like in
- * some struct. To make sure it's aligned, let's copy the args
- * into a static buffer as it's single-threaded for now.
- */
- memcpy(argbuf, sample->raw_data + args_size, *augmented_args_size);
+ /*
+ * The perf ring-buffer is 8-byte aligned but sample->raw_data
+ * is not because it's preceded by u32 size. Later, beautifier
+ * will use the augmented args with stricter alignments like in
+ * some struct. To make sure it's aligned, let's copy the args
+ * into a static buffer as it's single-threaded for now.
+ */
+ memcpy(argbuf, sample->raw_data + args_size, *augmented_args_size);

- return argbuf;
- }
- return NULL;
+ return argbuf;
}

static int trace__sys_enter(struct trace *trace,
--
2.56.0.rc1.315.gc6ed9934b7-goog