Linux Perf Users
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ian Rogers" <irogers@google.com>
Cc: linux-perf-users@vger.kernel.org
Subject: Re: [PATCH v8 4/4] perf aslr: Strip sample registers
Date: Wed, 20 May 2026 08:41:27 +0000	[thread overview]
Message-ID: <20260520084131.2ECFD1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260520063050.3917261-5-irogers@google.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:

New issues:
- [High] Restoring unstripped `evsel` attributes before delegating the stripped sample event corrupts downstream processors.
- [High] In pipe mode, synthesized headers bypass `aslr_tool__process_attr`, causing the output stream to start with unstripped attributes.
- [High] The manual attribute stripping loop in `__cmd_inject` misses `bp_addr` and unsupported sample types, leaking ASLR data in the file header.
- [High] Stripping `sample_type` attributes during pipe mode inline attribute processing corrupts subsequent input sample parsing.
- [Medium] Silently ignoring allocation failures when caching original attributes leads to trace parsing desynchronization and potential out-of-bounds reads.

Pre-existing issues:
- [Critical] Stack buffer overflow when copying a variable-length `perf_event` into a statically sized `union perf_event` local variable.
--

commit fb30fb1bb4e2af08887645a167b8d9c8ef4d7b2b
Author: Ian Rogers <irogers@google.com>

perf aslr: Strip sample registers

When the ASLR tracking tool encounters sample events containing user
or interrupt register dumps, it previously dropped the entire sample event
conservatively to prevent absolute virtual memory pointers leakage.
Refactor the ASLR tool to strip out only the register dump payload by
masking out the relevant perf_event_attr fields when the delegated
tool is handling the data.

> diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
> index f42b315199b3d..a34902ff0e77b 100644
> --- a/tools/perf/builtin-inject.c
> +++ b/tools/perf/builtin-inject.c
> @@ -239,6 +239,8 @@ static int perf_event__repipe_attr(const struct perf_tool *tool,
>  
>  		memcpy(&stripped_event, event, event->header.size);

[Severity: Critical]
This is a pre-existing issue, but stripped_event is a statically sized union
on the stack. 

Since PERF_RECORD_HEADER_ATTR events can be almost 64KB due to the
variable-length ID array, could copying event->header.size bytes cause a
massive stack buffer overflow?

>  		stripped_event.attr.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE;
> +		stripped_event.attr.attr.sample_regs_user = 0;
> +		stripped_event.attr.attr.sample_regs_intr = 0;
>  		return perf_event__repipe_synth(tool, &stripped_event);
>  	}

[ ... ]

> @@ -2470,7 +2472,16 @@ static int __cmd_inject(struct perf_inject *inject)
>  			}
>  		}
>  
> +		if (inject->aslr) {
> +			struct evsel *evsel;
>  
> +			evlist__for_each_entry(session->evlist, evsel) {
> +				evsel__reset_sample_bit(evsel, REGS_USER);
> +				evsel__reset_sample_bit(evsel, REGS_INTR);
> +				evsel->core.attr.sample_regs_user = 0;
> +				evsel->core.attr.sample_regs_intr = 0;
> +			}
> +		}
>  
>  		session->header.data_offset = output_data_offset;
>  		session->header.data_size = inject->bytes_written;

[Severity: High]
This loop strips REGS_USER and REGS_INTR before the file header is
serialized, but it doesn't clear bp_addr for breakpoints or apply the
ASLR_SUPPORTED_SAMPLE_TYPE mask.

Since those are only cleared at the end of cmd_inject() after the header
is written, does this leak breakpoint virtual addresses and defeat ASLR
for those events?

[ ... ]

> @@ -2730,6 +2741,17 @@ int cmd_inject(int argc, const char **argv)
>  	if (zstd_init(&(inject.session->zstd_data), 0) < 0)
>  		pr_warning("Decompression initialization failed.\n");
>  
> +	if (inject.aslr) {
> +		struct evsel *evsel;
> +
> +		evlist__for_each_entry(inject.session->evlist, evsel) {
> +			ret = aslr_tool__cache_orig_attrs(tool, evsel);
> +			if (ret) {
> +				pr_err("Failed to cache original attributes: %d\n", ret);
> +				goto out_delete;
> +			}
> +		}
> +	}

[Severity: High]
When processing pipe output, perf_event__synthesize_for_pipe() uses
perf_event__repipe directly rather than the tool's configured attr callback.

Will the output pipe stream begin with unstripped ATTR headers claiming
registers are present? Does this cause trace consumers to fail when parsing
the stripped SAMPLE records?

[ ... ]

> diff --git a/tools/perf/util/aslr.c b/tools/perf/util/aslr.c
> index 901b563048fa2..457813812a34a 100644
> --- a/tools/perf/util/aslr.c
> +++ b/tools/perf/util/aslr.c

[ ... ]

> @@ -983,8 +1013,22 @@ static int aslr_tool__process_sample(const struct perf_tool *tool,
>  
>  	new_event->sample.header.size = sizeof(struct perf_event_header) + j * sizeof(u64);
>  
> +	/* Temporarily override evsel attributes to match the stripped new_event format! */
> +	orig_sample_size = evsel->sample_size;
> +	evsel->sample_size = __evsel__sample_size(sample_type);
> +	evsel->core.attr.sample_type = sample_type;
> +	evsel->core.attr.sample_regs_user = 0;
> +	evsel->core.attr.sample_regs_intr = 0;
> +
>  	perf_sample__init(&new_sample, /*all=*/ true);
>  	ret = evsel__parse_sample(evsel, new_event, &new_sample);
> +
> +	/* Restore original attributes immediately so trace ingestion never desynchronizes! */
> +	evsel->sample_size = orig_sample_size;
> +	evsel->core.attr.sample_type = orig_sample_type;
> +	evsel->core.attr.sample_regs_user = orig_regs_user;
> +	evsel->core.attr.sample_regs_intr = orig_regs_intr;
> +
>  	if (ret) {
>  		perf_sample__exit(&new_sample);
>  		goto out_put;

[Severity: High]
If downstream delegates like perf_event__convert_sample_callchain use
evsel->core.attr.sample_type to parse the event, will they expect register
data that is no longer present in new_event?

Since we restored the original attributes before calling the delegate, could
this read past the end of new_event and cause data corruption?

Should we restore the attributes after the delegate returns?

[ ... ]

> @@ -1010,6 +1054,7 @@ static int aslr_tool__process_attr(const struct perf_tool *tool,
>  	struct aslr_tool *aslr;
>  	struct perf_tool *delegate;
>  	union perf_event *new_event;
> +	int err;
>  
>  	del_tool = container_of(tool, struct delegate_tool, tool);
>  	aslr = container_of(del_tool, struct aslr_tool, tool);
> @@ -1020,9 +1065,32 @@ static int aslr_tool__process_attr(const struct perf_tool *tool,
>  	if (new_event->attr.attr.type == PERF_TYPE_BREAKPOINT)
>  		new_event->attr.attr.bp_addr = 0;  /* Conservatively remove addresses. */
>  
> +	if (new_event->attr.attr.sample_type & PERF_SAMPLE_REGS_USER) {
> +		new_event->attr.attr.sample_type &= ~PERF_SAMPLE_REGS_USER;
> +		new_event->attr.attr.sample_regs_user = 0;
> +	}
> +	if (new_event->attr.attr.sample_type & PERF_SAMPLE_REGS_INTR) {
> +		new_event->attr.attr.sample_type &= ~PERF_SAMPLE_REGS_INTR;
> +		new_event->attr.attr.sample_regs_intr = 0;
> +	}
> +

[Severity: High]
When processing inline attributes in pipe mode, this strips the register flags
before delegating to perf_event__repipe_attr(). 

When subsequent PERF_RECORD_SAMPLE events arrive from the input pipe, will
evsel__parse_sample() use this stripped evsel to parse the unstripped raw
input buffer? Could this cause the parser to misinterpret the unread register
data as subsequent fields and drop the samples?

>  	new_event->attr.attr.sample_type &= ASLR_SUPPORTED_SAMPLE_TYPE;
>  
> -	return delegate->attr(delegate, new_event, pevlist);
> +	err = delegate->attr(delegate, new_event, pevlist);
> +	if (!err && pevlist && *pevlist) {
> +		struct evsel *evsel = evlist__last(*pevlist);
> +		struct aslr_evsel_priv *priv = zalloc(sizeof(*priv));
> +
> +		if (priv) {
> +			priv->orig_sample_type = event->attr.attr.sample_type;
> +			priv->orig_sample_regs_user = event->attr.attr.sample_regs_user;
> +			priv->orig_sample_regs_intr = event->attr.attr.sample_regs_intr;
> +			if (hashmap__add(&aslr->evsel_orig_attrs, evsel, priv) != 0)
> +				free(priv);
> +		}
> +	}
> +
> +	return err;
>  }

[Severity: Medium]
If zalloc() or hashmap__add() fails here, the error is silently ignored.

When aslr_tool__process_sample() later fails the hashmap lookup, it will fall
back to an evsel->core.attr.sample_type that lacks the register flags. Will
parsing the unstripped raw kernel sample array with this stripped mask cause
the manual parser to desynchronize and misinterpret the unread register data?

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

      reply	other threads:[~2026-05-20  8:41 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-24 22:05 [PATCH v1 1/2] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-04-24 22:05 ` [PATCH v1 2/2] perf test: Add inject ASLR test Ian Rogers
2026-04-24 22:47   ` sashiko-bot
2026-04-24 22:36 ` [PATCH v1 1/2] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses sashiko-bot
2026-04-25  2:05 ` [PATCH v2 " Ian Rogers
2026-04-25  2:05   ` [PATCH v2 2/2] perf test: Add inject ASLR test Ian Rogers
2026-05-04  3:51   ` [PATCH v3 0/4] perf tools: Add inject --aslr feature and prerequisite robustness fixes Ian Rogers
2026-05-04  3:51     ` [PATCH v3 1/4] perf sched: Add missing mmap2 handler in timehist Ian Rogers
2026-05-04  3:51     ` [PATCH v3 2/4] perf tool: Fix missing schedstat delegates and dont_split_sample_group in delegate_tool Ian Rogers
2026-05-04  3:51     ` [PATCH v3 3/4] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-05-04  4:51       ` sashiko-bot
2026-05-04  3:51     ` [PATCH v3 4/4] perf test: Add inject ASLR test Ian Rogers
2026-05-04  5:02       ` sashiko-bot
2026-05-04  7:29     ` [PATCH v4 0/4] perf tools: Add inject --aslr feature and prerequisite robustness fixes Ian Rogers
2026-05-04  7:29       ` [PATCH v4 1/4] perf sched: Add missing mmap2 handler in timehist Ian Rogers
2026-05-04  7:29       ` [PATCH v4 2/4] perf tool: Fix missing schedstat delegates and dont_split_sample_group in delegate_tool Ian Rogers
2026-05-04  7:29       ` [PATCH v4 3/4] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-05-04  8:39         ` sashiko-bot
2026-05-04  7:29       ` [PATCH v4 4/4] perf test: Add inject ASLR test Ian Rogers
2026-05-04  8:48         ` sashiko-bot
2026-05-04  8:23       ` [PATCH v4 0/4] perf tools: Add inject --aslr feature and prerequisite robustness fixes Ian Rogers
2026-05-06  0:45       ` [PATCH v5 0/5] " Ian Rogers
2026-05-06  0:45         ` [PATCH v5 1/5] perf sched: Add missing mmap2 handler in timehist Ian Rogers
2026-05-06 13:22           ` Arnaldo Carvalho de Melo
2026-05-06 16:16             ` Ian Rogers
2026-05-06  0:45         ` [PATCH v5 2/5] perf tool: Fix missing schedstat delegates and dont_split_sample_group in delegate_tool Ian Rogers
2026-05-06  0:45         ` [PATCH v5 3/5] perf symbols: Fix map removal sequence inside dso__process_kernel_symbol() Ian Rogers
2026-05-06  1:45           ` sashiko-bot
2026-05-06  0:45         ` [PATCH v5 4/5] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-05-06  2:40           ` sashiko-bot
2026-05-06 18:52           ` Namhyung Kim
2026-05-06 20:01             ` Ian Rogers
2026-05-06  0:45         ` [PATCH v5 5/5] perf test: Add inject ASLR test Ian Rogers
2026-05-07 15:58           ` James Clark
2026-05-07 16:17             ` Ian Rogers
2026-05-08 10:42               ` James Clark
2026-05-08 10:49                 ` James Clark
2026-05-08  8:27         ` [PATCH v6 0/6] perf tools: Add inject --aslr feature and prerequisite robustness fixes Ian Rogers
2026-05-08  8:27           ` [PATCH v6 1/6] perf sched: Add missing mmap2 handler in timehist Ian Rogers
2026-05-08  8:27           ` [PATCH v6 2/6] perf tool: Missing delegate_tool schedstat delegates and dont_split_sample_group Ian Rogers
2026-05-08  8:27           ` [PATCH v6 3/6] perf maps: Add maps__mutate_mapping Ian Rogers
2026-05-08 10:57             ` James Clark
2026-05-08 20:37             ` sashiko-bot
2026-05-11  7:07             ` Namhyung Kim
2026-05-08  8:27           ` [PATCH v6 4/6] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-05-08 21:22             ` sashiko-bot
2026-05-11  7:32             ` Namhyung Kim
2026-05-08  8:27           ` [PATCH v6 5/6] perf test: Add inject ASLR test Ian Rogers
2026-05-08 13:29             ` James Clark
2026-05-08 14:29               ` James Clark
2026-05-11  7:34             ` Namhyung Kim
2026-05-08  8:27           ` [PATCH v6 6/6] perf aslr: Strip sample registers Ian Rogers
2026-05-08 21:49             ` sashiko-bot
2026-05-19  8:08           ` [PATCH v7 0/4] perf tools: Add inject --aslr feature, early maps loading, and decoupling fixes Ian Rogers
2026-05-19  8:08             ` [PATCH v7 1/4] perf maps: Add maps__mutate_mapping Ian Rogers
2026-05-19  8:38               ` sashiko-bot
2026-05-19  8:08             ` [PATCH v7 2/4] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-05-19  9:14               ` sashiko-bot
2026-05-19  8:08             ` [PATCH v7 3/4] perf test: Add inject ASLR test Ian Rogers
2026-05-19  8:08             ` [PATCH v7 4/4] perf aslr: Strip sample registers Ian Rogers
2026-05-19  9:55               ` sashiko-bot
2026-05-20  6:30             ` [PATCH v8 0/4] perf tools: Add inject --aslr feature, early maps loading, and decoupling fixes Ian Rogers
2026-05-20  6:30               ` [PATCH v8 1/4] perf maps: Add maps__mutate_mapping Ian Rogers
2026-05-20  7:06                 ` sashiko-bot
2026-05-20  6:30               ` [PATCH v8 2/4] perf inject/aslr: Add aslr tool to remap/obfuscate virtual addresses Ian Rogers
2026-05-20  7:50                 ` sashiko-bot
2026-05-20  6:30               ` [PATCH v8 3/4] perf test: Add inject ASLR test Ian Rogers
2026-05-20  8:02                 ` sashiko-bot
2026-05-20  6:30               ` [PATCH v8 4/4] perf aslr: Strip sample registers Ian Rogers
2026-05-20  8:41                 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260520084131.2ECFD1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=irogers@google.com \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox