]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf sched: Bounds-check prio before test_bit() in timehist
authorArnaldo Carvalho de Melo <acme@redhat.com>
Sun, 7 Jun 2026 00:48:13 +0000 (21:48 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 10 Jun 2026 18:23:53 +0000 (15:23 -0300)
timehist_skip_sample() reads prio from untrusted tracepoint data via
perf_sample__intval(sample, "prev_prio") without bounds validation.
A crafted perf.data with prev_prio >= MAX_PRIO (140) causes test_bit()
to read past the end of the prio_bitmap, which is only MAX_PRIO bits.

Add a prio >= 0 guard before the test_bit() call and skip out-of-range
values (>= MAX_PRIO) that can never match the user's filter set.

The original prio != -1 already let all negatives other than -1 through
(after an undefined-behavior bitmap read); the new prio >= 0 guard
preserves that pass-through behavior — negative means "no priority
info", so the event is shown unfiltered — while fixing the OOB.
Values >= MAX_PRIO are skipped because they cannot be represented in
the filter bitmap.

Fixes: 9b3a48bbe20d9692 ("perf sched timehist: Add --prio option")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Yang Jihong <yangjihong@bytedance.com>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-sched.c

index 1ff01f03d2ad1ad33bb9c13109a9fd4889af6d27..caf05863a54e5eac4a8164c54c595ee1ae811d3e 100644 (file)
@@ -2645,7 +2645,9 @@ static bool timehist_skip_sample(struct perf_sched *sched,
                else if (evsel__name_is(sample->evsel, "sched:sched_switch"))
                        prio = perf_sample__intval(sample, "prev_prio");
 
-               if (prio != -1 && !test_bit(prio, sched->prio_bitmap)) {
+               /* negative prio means no info; out-of-range prio can't match the filter */
+               if (prio >= 0 &&
+                   (prio >= MAX_PRIO || !test_bit(prio, sched->prio_bitmap))) {
                        rc = true;
                        sched->skipped_samples++;
                }