From nobody Sat Sep 26 07:57:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4F5E843636A; Thu, 3 Sep 2026 11:05:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788433502; cv=none; b=tTVzSXGATY+1qxfYnuAyNo1HJCdUnpvNN4+xN6lCdb7tpHtVHWn1fYICVjgi231nklvPDMcTSIjEodsWPhVaOGW+EoYv+U3rO9absJSFmGb0Czc1ELdikLSiEZ5/g34wUDrPSVxq93IMFZ5fELeu56zASAysjFzC4HVlN0fnhp4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788433502; c=relaxed/simple; bh=iMmhh7e612un5M2KNTkrg/HSz6ZbI48Agss/+UGUoD4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Xn7aweRnb/bW+Tk9cCNhi0tMZi6EJOwnb/fxT3koU6VUduVoXsjt5bIv1idbxAf8B1zVyDN17bH86bHwPRt/YRRAYvyQmt9yeiiLSf0AaG1UST0+iOXHMusVQeyJQYItqHH5E0hvCKJ5/yX0qg9xOfDWJTvaYePwXqjyX8Wmjsk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hznulwf9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hznulwf9" Received: by smtp.kernel.org (Postfix) with ESMTPS id D5304C2BCF5; Thu, 3 Sep 2026 11:05:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788433501; bh=iMmhh7e612un5M2KNTkrg/HSz6ZbI48Agss/+UGUoD4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hznulwf9u192ttU2KTqnlSIVZ3SvLhZ4i3AJ5fsZg3lM+z3ENrXA2NyvgHU0FSO1K BhdAhc5E/QMX2wwyIjDUGJgcEVEvm66bR7k+kHqKTj/gVZk9xUI+VamP4gBgFy60qE CBRNhdC4/wVb8i4WR4+2xYHCsQUTWJqbT/mvob1JX1BAPSiRUhNntCZmWShTp6cFNT GRPRpxBl4NPtTBKJffM5CTT95ibGxMA8Lfejj4jVQjM05jZhdSl7l+gsLpgjdEOznr vuTQBeqUyeuwWSAPFbPNRlgxmq18gxoABhtzQGZM+DgSccCkyx14F7nz5BKCts0Q76 575GiT1RWvycg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id AEA9DC61DD3; Thu, 3 Sep 2026 11:05:01 +0000 (UTC) From: Mark Amirkan via B4 Relay Date: Thu, 03 Sep 2026 04:04:20 -0700 Subject: [PATCH v2 1/2] perf evsel: Validate branch stack before byte swapping Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260903-sympwn-linux-002-final-v2-v2-1-0aee1fca1f95@gmail.com> References: <20260903-sympwn-linux-002-final-v2-v2-0-0aee1fca1f95@gmail.com> In-Reply-To: <20260903-sympwn-linux-002-final-v2-v2-0-0aee1fca1f95@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: Mark Amirkan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788433501; l=3687; i=markdamirkan@gmail.com; s=pscsi-20260818; h=from:subject:message-id; bh=58e7OflNXA7OlGA05i/f/QWuPoVOC00wOH0fz7PzXT4=; b=EPmwj1Tjal5+mJNekCWUSZubAYjydL+rdYgsRfy/U4aF7/xJsUiOhIG2spvr5UWJLbSWpTrRl 13wuHmbzPyeBrgjwY5zs7BnKA9RBU8Nz8ieUrBohavknG3wm7kZk/5U X-Developer-Key: i=markdamirkan@gmail.com; a=ed25519; pk=/wb49ibt4gZFDncmhFQBYtjPvzT1tfJtvK4Mqt1P2Wc= X-Endpoint-Received: by B4 Relay for markdamirkan@gmail.com/pscsi-20260818 with auth_id=961 X-Original-From: Mark Amirkan Reply-To: markdamirkan@gmail.com From: Mark Amirkan When perf reads an opposite-endian branch stack, __evsel__parse_sample() swaps each entry before checking whether all entries fit in the event. A truncated sample can therefore make the swap loop read and write past the event boundary. A truncated perf.data file makes perf report crash with SIGSEGV. ASan reports an out-of-bounds read. A regression test puts an entry just past the declared end and shows that its flags are changed before the parser returns -EFAULT. Move the bounds check before the byte-swap loop. Valid samples are handled as before. Fixes: 63c12ae2f246 ("perf evsel: Add bitfield_swap() to handle branch_stac= k endian issue") Cc: stable@vger.kernel.org Assisted-by: Symbolic Signed-off-by: Mark Amirkan Reviewed-by: Ian Rogers --- tools/perf/tests/sample-parsing.c | 48 +++++++++++++++++++++++++++++++++++= ++++ tools/perf/util/evsel.c | 3 ++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-pa= rsing.c index 32dbc484487a..583951534937 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -417,6 +418,49 @@ static int do_test(u64 sample_type, u64 sample_regs, u= 64 read_format) return ret; } =20 +static int test_truncated_branch_stack(void) +{ + struct perf_event_attr attr =3D { + .sample_type =3D PERF_SAMPLE_BRANCH_STACK, + }; + struct { + struct perf_event_header header; + u64 nr; + struct branch_entry entry; + } input =3D { + .header =3D { + .type =3D PERF_RECORD_SAMPLE, + .size =3D sizeof(input.header) + sizeof(input.nr), + }, + .nr =3D 1, + }; + struct perf_sample sample; + struct evsel *evsel; + u64 flags =3D 1; + int err; + + input.entry.flags.value =3D flags; + evsel =3D evsel__new(&attr); + if (!evsel) + return -1; + + evsel->sample_size =3D __evsel__sample_size(attr.sample_type); + err =3D __evsel__parse_sample(evsel, (union perf_event *)&input, + &sample, /*needs_swap=3D*/true); + perf_sample__exit(&sample); + evsel__put(evsel); + + if (err !=3D -EFAULT) { + pr_debug("truncated branch stack returned %d, expected -EFAULT\n", err); + return -1; + } + if (input.entry.flags.value !=3D flags) { + pr_debug("truncated branch stack modified data past the event\n"); + return -1; + } + return 0; +} + /** * test__sample_parsing - test sample parsing. * @@ -433,6 +477,10 @@ static int test__sample_parsing(struct test_suite *tes= t __maybe_unused, int subt size_t i; int err; =20 + err =3D test_truncated_branch_stack(); + if (err) + return err; + /* * Fail the test if it has not been updated when new sample format bits * were added. Please actually update the test rather than just change diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d4cb455f4a7d..cc0bc0857754 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3639,6 +3639,8 @@ int __evsel__parse_sample(struct evsel *evsel, union = perf_event *event, e =3D (struct branch_entry *)&data->branch_stack->hw_idx; } =20 + OVERFLOW_CHECK(array, sz, max_size); + if (swapped) { /* * struct branch_flag does not have endian @@ -3654,7 +3656,6 @@ int __evsel__parse_sample(struct evsel *evsel, union = perf_event *event, e->flags.value =3D evsel__bitfield_swap_branch_flags(e->flags.value); } =20 - OVERFLOW_CHECK(array, sz, max_size); array =3D (void *)array + sz; =20 if (evsel__has_branch_counters(evsel)) { --=20 Git-146) From nobody Sat Sep 26 07:57:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4FAA543713E; Thu, 3 Sep 2026 11:05:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788433502; cv=none; b=ukhSeAHYBNl/uObcDu5JE7bFX1nzNHr1jd60/suuogeymFYvXCTxz3zJcg+ctuvXCz+jNGlogs4wGvBsddDy1Lw/2pRny8jCYSgV8CZ3GMVLdV9+4gfNiEsEG5Snh3gpoL96vnz1WjKF6Kq/RIWWwXj8YeT+7OwVJfwQ43LoMvQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788433502; c=relaxed/simple; bh=70biVnXZdTszpQN4ocqjee9GNCAdrxxcGK9CdJ0YKwk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fvUC7Ua9jRT313XmiBP0j6FaPTFJdSGTNsP3j6khOgDHhXIeDU79HkiLdaLOOs6Osks82j2R0BWZv2r0uiJSdkOWiv0h+OTvMzzXwXEeyNJqc1binkfx2qiyeenZ7lpENO4+UDAxtrwNCgYc7AcnhZdlBKHyZQSwn421sU3UUUw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sPVwrY+Z; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="sPVwrY+Z" Received: by smtp.kernel.org (Postfix) with ESMTPS id E874EC2BCFF; Thu, 3 Sep 2026 11:05:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788433502; bh=70biVnXZdTszpQN4ocqjee9GNCAdrxxcGK9CdJ0YKwk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=sPVwrY+ZaDf5hyRwgVKkCbkv/bZ4RkiD5gjHzOfzXbdumwynH0CB3AvKQXI2cvTTx JF1Zpe9OsNa8N6ycLasFlO5a2YSS9yWjwAq6LwPaQr+2WAbaZ2xD433dqPOMljFQrN +O91AbNiKv5nqOmu5z5m+RiHMd0ZsqcOc4ZRPQg33yTA86craXmbZYrG0uU6bqj8GU QQ4SzCjw8dgPempsdz/2IUt4E7N3nVaZE4FMmplMgd3p1dcjf8TY9Utl3rTpfK15WW ooYYmid1etnGHjEfbb4SNa4Ijc49tSZat/eCO0mfRYHDTyZs2ZxP8iUfLmbK1mVVZy fqvgl7m0qufuQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C457EC624D7; Thu, 3 Sep 2026 11:05:01 +0000 (UTC) From: Mark Amirkan via B4 Relay Date: Thu, 03 Sep 2026 04:04:21 -0700 Subject: [PATCH v2 2/2] perf evsel: Validate RAW sample before byte swapping Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260903-sympwn-linux-002-final-v2-v2-2-0aee1fca1f95@gmail.com> References: <20260903-sympwn-linux-002-final-v2-v2-0-0aee1fca1f95@gmail.com> In-Reply-To: <20260903-sympwn-linux-002-final-v2-v2-0-0aee1fca1f95@gmail.com> To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark Cc: Mark Amirkan , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788433501; l=4545; i=markdamirkan@gmail.com; s=pscsi-20260818; h=from:subject:message-id; bh=UB7egJdlaxZNL6OHQ6khTPm+2pfri3frePTZlRlCqf8=; b=ie3cYz6bQEfs+7mvYXYFFEqddNBl59PMbYh/SgBtwFegU4qnuAC341JnrdPcbmwXJi6LUG27f t4WHIpSRyzdAH8mL50TibG20qKsbP6WTbEOtkxTRPvdcndh+7VO3akw X-Developer-Key: i=markdamirkan@gmail.com; a=ed25519; pk=/wb49ibt4gZFDncmhFQBYtjPvzT1tfJtvK4Mqt1P2Wc= X-Endpoint-Received: by B4 Relay for markdamirkan@gmail.com/pscsi-20260818 with auth_id=961 X-Original-From: Mark Amirkan Reply-To: markdamirkan@gmail.com From: Mark Amirkan For an opposite-endian RAW sample, __evsel__parse_sample() passes the input-controlled size to mem_bswap_64() before checking whether the payload fits in the event. A truncated record can therefore make the helper read and write past the event boundary. A crafted perf.data file makes perf report crash with SIGSEGV. ASan reports the out-of-bounds access. A regression test puts backed data past the declared end and shows that it is changed before the parser returns -EFAULT. Move the bounds checks before mem_bswap_64(). Check the rounded length too, because the helper accesses complete 64-bit words. Complete records are handled as before. Fixes: f9d8adb345d7 ("perf evsel: Fix swap for samples with raw data") Cc: stable@vger.kernel.org Assisted-by: Symbolic Signed-off-by: Mark Amirkan Reviewed-by: Ian Rogers --- tools/perf/tests/sample-parsing.c | 61 +++++++++++++++++++++++++++++++++++= ++++ tools/perf/util/evsel.c | 17 ++++++----- 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-pa= rsing.c index 583951534937..bd30f6d4c31b 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -461,6 +461,55 @@ static int test_truncated_branch_stack(void) return 0; } =20 +static int test_truncated_swapped_raw(u16 event_size, u32 raw_size) +{ + struct perf_event_attr attr =3D { + .sample_type =3D PERF_SAMPLE_RAW, + }; + struct { + struct perf_event_header header; + union { + u64 value; + u32 words[2]; + } raw; + u64 canary; + } input =3D { + .header =3D { + .type =3D PERF_RECORD_SAMPLE, + .size =3D event_size, + }, + /* Parsing a pre-swapped word exchanges these two u32 values. */ + .raw.words =3D { 0x12345678, raw_size }, + .canary =3D 0x8877665544332211ULL, + }; + struct perf_sample sample; + struct evsel *evsel; + u64 raw =3D input.raw.value; + u64 canary =3D input.canary; + int err; + + evsel =3D evsel__new(&attr); + if (!evsel) + return -1; + + evsel->sample_size =3D __evsel__sample_size(attr.sample_type); + err =3D __evsel__parse_sample(evsel, (union perf_event *)&input, + &sample, /*needs_swap=3D*/true); + perf_sample__exit(&sample); + evsel__put(evsel); + + if (err !=3D -EFAULT) { + pr_debug("truncated swapped RAW sample (size %u, raw %u) returned %d, ex= pected -EFAULT\n", + event_size, raw_size, err); + return -1; + } + if (input.raw.value !=3D raw || input.canary !=3D canary) { + pr_debug("truncated swapped RAW sample modified data before validation\n= "); + return -1; + } + return 0; +} + /** * test__sample_parsing - test sample parsing. * @@ -481,6 +530,18 @@ static int test__sample_parsing(struct test_suite *tes= t __maybe_unused, int subt if (err) return err; =20 + /* The declared RAW payload extends past an otherwise aligned event. */ + err =3D test_truncated_swapped_raw(sizeof(struct perf_event_header) + + sizeof(u64), 16); + if (err) + return err; + + /* The final complete word touched by mem_bswap_64() extends past it. */ + err =3D test_truncated_swapped_raw(sizeof(struct perf_event_header) + + sizeof(u32) + 9, 9); + if (err) + return err; + /* * Fail the test if it has not been updated when new sample format bits * were added. Please actually update the test rather than just change diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index cc0bc0857754..ce429eb247b6 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3584,7 +3584,10 @@ int __evsel__parse_sample(struct evsel *evsel, union= perf_event *event, } =20 if (type & PERF_SAMPLE_RAW) { + const __u64 *raw; + OVERFLOW_CHECK_u64(array); + raw =3D array; u.val64 =3D *array; =20 /* @@ -3600,16 +3603,14 @@ int __evsel__parse_sample(struct evsel *evsel, unio= n perf_event *event, } data->raw_size =3D u.val32[0]; =20 - /* - * The raw data is aligned on 64bits including the - * u32 size, so it's safe to use mem_bswap_64. - */ - if (swapped) - mem_bswap_64((void *) array, data->raw_size); - array =3D (void *)array + sizeof(u32); - OVERFLOW_CHECK(array, data->raw_size, max_size); + if (swapped) { + /* mem_bswap_64() accesses complete 64-bit words. */ + sz =3D roundup((u64)data->raw_size, sizeof(u64)); + OVERFLOW_CHECK(raw, sz, max_size); + mem_bswap_64((void *)raw, data->raw_size); + } data->raw_data =3D (void *)array; array =3D (void *)array + data->raw_size; } --=20 Git-146)