]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
drop 6.12 perf patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jul 2026 13:16:14 +0000 (15:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jul 2026 13:16:14 +0000 (15:16 +0200)
72 files changed:
queue-6.12/perf-arm-spe-add-branch-stack.patch [deleted file]
queue-6.12/perf-arm-spe-correctly-set-sample-flags.patch [deleted file]
queue-6.12/perf-arm-spe-use-arm_spe_op_branch_eret-when-synthes.patch [deleted file]
queue-6.12/perf-arm-spe-use-metadata-to-decide-the-data-source-.patch [deleted file]
queue-6.12/perf-arm-spe-use-old-behavior-when-opening-old-spe-files.patch [deleted file]
queue-6.12/perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch [deleted file]
queue-6.12/perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch [deleted file]
queue-6.12/perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch [deleted file]
queue-6.12/perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch [deleted file]
queue-6.12/perf-build-id-change-sprintf-functions-to-snprintf.patch [deleted file]
queue-6.12/perf-build-id-ensure-snprintf-string-is-empty-when-size-is-0.patch [deleted file]
queue-6.12/perf-build-id-fix-off-by-one-bug-when-printing-kernel-module-build-id.patch [deleted file]
queue-6.12/perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch [deleted file]
queue-6.12/perf-c2c-bounds-check-cpu-ids-in-setup_nodes-topolog.patch [deleted file]
queue-6.12/perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch [deleted file]
queue-6.12/perf-callchain-handle-multiple-address-spaces.patch [deleted file]
queue-6.12/perf-cs-etm-bounds-check-cpu-in-cs_etm__get_queue.patch [deleted file]
queue-6.12/perf-cs-etm-queue-context-packets-for-frontend.patch [deleted file]
queue-6.12/perf-cs-etm-reject-cpu-ids-that-would-overflow-signe.patch [deleted file]
queue-6.12/perf-cs-etm-require-full-global-header-in-auxtrace_i.patch [deleted file]
queue-6.12/perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch [deleted file]
queue-6.12/perf-debuginfo-fix-libdw-api-contract-violations.patch [deleted file]
queue-6.12/perf-dso-add-support-for-reading-the-e_machine-type-.patch [deleted file]
queue-6.12/perf-dso-move-build_id-to-dso_id.patch [deleted file]
queue-6.12/perf-dso-use-lock-annotations-to-fix-asan-deadlock.patch [deleted file]
queue-6.12/perf-header-sanity-check-header_event_desc-attr.size.patch [deleted file]
queue-6.12/perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch [deleted file]
queue-6.12/perf-inject-add-convert-callchain-option.patch [deleted file]
queue-6.12/perf-inject-with-convert-callchain-ignore-the-dummy-event-for-dwarf-stacks.patch [deleted file]
queue-6.12/perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch [deleted file]
queue-6.12/perf-libunwind-arm64-fix-missing-close-parens-in-an-if-statement.patch [deleted file]
queue-6.12/perf-machine-use-snprintf-for-guestmount-path-constr.patch [deleted file]
queue-6.12/perf-maps-add-maps__mutate_mapping.patch [deleted file]
queue-6.12/perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch [deleted file]
queue-6.12/perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch [deleted file]
queue-6.12/perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch [deleted file]
queue-6.12/perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch [deleted file]
queue-6.12/perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch [deleted file]
queue-6.12/perf-remove-redundant-kernel.h-include.patch [deleted file]
queue-6.12/perf-sched-add-missing-mmap2-handler-in-timehist.patch [deleted file]
queue-6.12/perf-sched-bounds-check-prio-before-test_bit-in-time.patch [deleted file]
queue-6.12/perf-sched-clean-up-idle_threads-entry-on-init-failu.patch [deleted file]
queue-6.12/perf-sched-fix-idle-hist-callchain-display-using-wro.patch [deleted file]
queue-6.12/perf-sched-fix-null-dereference-in-latency_runtime_e.patch [deleted file]
queue-6.12/perf-sched-fix-register_pid-overflow-strcpy-and-bug_.patch [deleted file]
queue-6.12/perf-sched-fix-thread-leaks-in-perf-sched-timehist.patch [deleted file]
queue-6.12/perf-sched-fix-thread-reference-leak-in-latency_swit.patch [deleted file]
queue-6.12/perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch [deleted file]
queue-6.12/perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch [deleted file]
queue-6.12/perf-sched-timehist-add-pre-migration-wait-time-opti.patch [deleted file]
queue-6.12/perf-sched-use-thread__put-in-free_idle_threads.patch [deleted file]
queue-6.12/perf-stat-bounds-check-cpu-index-in-topology-aggrega.patch [deleted file]
queue-6.12/perf-stat-introduce-perf_env__get_cpu_topology-to-gu.patch [deleted file]
queue-6.12/perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch [deleted file]
queue-6.12/perf-symbols-add-bounds-checks-to-read_build_id-note.patch [deleted file]
queue-6.12/perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch [deleted file]
queue-6.12/perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch [deleted file]
queue-6.12/perf-symbols-break-infinite-loop-on-zero-filled-note.patch [deleted file]
queue-6.12/perf-symbols-fix-bswap-copy-paste-error-for-32-bit-e.patch [deleted file]
queue-6.12/perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch [deleted file]
queue-6.12/perf-symbols-validate-p_filesz-before-use-in-filenam.patch [deleted file]
queue-6.12/perf-synthetic-events-fix-stale-build-id-in-module-mmap2-records.patch [deleted file]
queue-6.12/perf-timechart-fix-cpu2y-oob-read-on-untrusted-cpu-i.patch [deleted file]
queue-6.12/perf-tools-add-bounds-check-to-cpu__get_node.patch [deleted file]
queue-6.12/perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch [deleted file]
queue-6.12/perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch [deleted file]
queue-6.12/perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch [deleted file]
queue-6.12/perf-tools-use-perf_env__get_cpu_topology-in-machine.patch [deleted file]
queue-6.12/perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch [deleted file]
queue-6.12/perf-tools-use-snprintf-for-root_dir-path-constructi.patch [deleted file]
queue-6.12/perf-tools-use-snprintf-in-dso__read_running_kernel_.patch [deleted file]
queue-6.12/series

diff --git a/queue-6.12/perf-arm-spe-add-branch-stack.patch b/queue-6.12/perf-arm-spe-add-branch-stack.patch
deleted file mode 100644 (file)
index a8cb3c9..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-From 6eb077ed90cb41ccf685ed405d72d9e5a7b8299e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 4 Mar 2025 11:12:39 +0000
-Subject: perf arm-spe: Add branch stack
-
-From: Leo Yan <leo.yan@arm.com>
-
-[ Upstream commit 73cb57f56f749ac640b889f076d5db96264020f8 ]
-
-Although Arm SPE cannot generate continuous branch records, this commit
-creates a branch stack with only one branch entry.  A single branch info
-can be used for performance optimization.
-
-A branch stack structure is dynamically allocated in the decode queue.
-The branch stack and stack flags are synthesized based on branch types
-and associated events.
-
-After:
-
-  # perf script --itrace=bl1 -F flags,addr,brstack
-
-  jcc                   ffffc0fad9c6b214 0xffffc0fad9c6b234/0xffffc0fad9c6b214/P/-/-/7/COND/-
-  jcc/miss,not_taken/   ffffc0fadaaebb30 0xffffc0fadaaebb2c/0xffffc0fadaaebb30/MN/-/-/7/COND/-
-  jmp                   ffffc0fadaaea358 0xffffc0fadaaea5ec/0xffffc0fadaaea358/P/-/-/5//-
-  jcc/not_taken/        ffffc0fadaae6494 0xffffc0fadaae6490/0xffffc0fadaae6494/PN/-/-/11/COND/-
-  jcc/not_taken/            ffff7f83ab54 0xffff7f83ab50/0xffff7f83ab54/PN/-/-/13/COND/-
-  jcc/not_taken/            ffff7f83ab08 0xffff7f83ab04/0xffff7f83ab08/PN/-/-/8/COND/-
-  jcc                       ffff7f83aa80 0xffff7f83aa58/0xffff7f83aa80/P/-/-/10/COND/-
-  jcc                       ffff7f9a45d0 0xffff7f9a43f0/0xffff7f9a45d0/P/-/-/29/COND/-
-  jcc/not_taken/        ffffc0fad9ba6db4 0xffffc0fad9ba6db0/0xffffc0fad9ba6db4/PN/-/-/44/COND/-
-  jcc                   ffffc0fadaac2964 0xffffc0fadaac2970/0xffffc0fadaac2964/P/-/-/6/COND/-
-  jcc                   ffffc0fad99ddc10 0xffffc0fad99ddc04/0xffffc0fad99ddc10/P/-/-/72/COND/-
-  jcc/not_taken/        ffffc0fad9b3f21c 0xffffc0fad9b3f218/0xffffc0fad9b3f21c/PN/-/-/64/COND/-
-  jcc                   ffffc0fad9c3b604 0xffffc0fad9c3b5f8/0xffffc0fad9c3b604/P/-/-/13/COND/-
-  jcc                   ffffc0fadaad6048 0xffffc0fadaad5f8c/0xffffc0fadaad6048/P/-/-/5/COND/-
-  return/miss/              ffff7f84e614 0xffffc0fad98a2274/0xffff7f84e614/M/-/-/13/RET/-
-  jcc/not_taken/        ffffc0fadaac4eb4 0xffffc0fadaac4eb0/0xffffc0fadaac4eb4/PN/-/-/5/COND/-
-  jmp                       ffff7f8e3130 0xffff7f87555c/0xffff7f8e3130/P/-/-/5//-
-  jcc/not_taken/        ffffc0fad9b3d9b0 0xffffc0fad9b3d9ac/0xffffc0fad9b3d9b0/PN/-/-/14/COND/-
-  return                ffffc0fad9b91950 0xffffc0fad98c3e28/0xffffc0fad9b91950/P/-/-/12/RET/-
-
-Reviewed-by: Ian Rogers <irogers@google.com>
-Reviewed-by: James Clark <james.clark@linaro.org>
-Signed-off-by: Leo Yan <leo.yan@arm.com>
-Link: https://lore.kernel.org/r/20250304111240.3378214-12-leo.yan@arm.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 059e9100d82a ("perf event: Fix size of synthesized sample with branch stacks")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/arm-spe.c | 99 +++++++++++++++++++++++++++++++++++++++
- 1 file changed, 99 insertions(+)
-
-diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
-index a004e1721a1ff1..80fcb8b10f52e4 100644
---- a/tools/perf/util/arm-spe.c
-+++ b/tools/perf/util/arm-spe.c
-@@ -99,6 +99,7 @@ struct arm_spe_queue {
-       struct thread                   *thread;
-       u64                             period_instructions;
-       u32                             flags;
-+      struct branch_stack             *last_branch;
- };
- static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
-@@ -217,6 +218,16 @@ static struct arm_spe_queue *arm_spe__alloc_queue(struct arm_spe *spe,
-       params.get_trace = arm_spe_get_trace;
-       params.data = speq;
-+      if (spe->synth_opts.last_branch) {
-+              size_t sz = sizeof(struct branch_stack);
-+
-+              /* Allocate one entry for TGT */
-+              sz += sizeof(struct branch_entry);
-+              speq->last_branch = zalloc(sz);
-+              if (!speq->last_branch)
-+                      goto out_free;
-+      }
-+
-       /* create new decoder */
-       speq->decoder = arm_spe_decoder_new(&params);
-       if (!speq->decoder)
-@@ -226,6 +237,7 @@ static struct arm_spe_queue *arm_spe__alloc_queue(struct arm_spe *spe,
- out_free:
-       zfree(&speq->event_buf);
-+      zfree(&speq->last_branch);
-       free(speq);
-       return NULL;
-@@ -332,6 +344,73 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
-       event->sample.header.size = sizeof(struct perf_event_header);
- }
-+static void arm_spe__prep_branch_stack(struct arm_spe_queue *speq)
-+{
-+      struct arm_spe_record *record = &speq->decoder->record;
-+      struct branch_stack *bstack = speq->last_branch;
-+      struct branch_flags *bs_flags;
-+      size_t sz = sizeof(struct branch_stack) +
-+                  sizeof(struct branch_entry) /* TGT */;
-+
-+      /* Clean up branch stack */
-+      memset(bstack, 0x0, sz);
-+
-+      if (!(speq->flags & PERF_IP_FLAG_BRANCH))
-+              return;
-+
-+      bstack->entries[0].from = record->from_ip;
-+      bstack->entries[0].to = record->to_ip;
-+
-+      bs_flags = &bstack->entries[0].flags;
-+      bs_flags->value = 0;
-+
-+      if (record->op & ARM_SPE_OP_BR_CR_BL) {
-+              if (record->op & ARM_SPE_OP_BR_COND)
-+                      bs_flags->type |= PERF_BR_COND_CALL;
-+              else
-+                      bs_flags->type |= PERF_BR_CALL;
-+      /*
-+       * Indirect branch instruction without link (e.g. BR),
-+       * take this case as function return.
-+       */
-+      } else if (record->op & ARM_SPE_OP_BR_CR_RET ||
-+                 record->op & ARM_SPE_OP_BR_INDIRECT) {
-+              if (record->op & ARM_SPE_OP_BR_COND)
-+                      bs_flags->type |= PERF_BR_COND_RET;
-+              else
-+                      bs_flags->type |= PERF_BR_RET;
-+      } else if (record->op & ARM_SPE_OP_BR_CR_NON_BL_RET) {
-+              if (record->op & ARM_SPE_OP_BR_COND)
-+                      bs_flags->type |= PERF_BR_COND;
-+              else
-+                      bs_flags->type |= PERF_BR_UNCOND;
-+      } else {
-+              if (record->op & ARM_SPE_OP_BR_COND)
-+                      bs_flags->type |= PERF_BR_COND;
-+              else
-+                      bs_flags->type |= PERF_BR_UNKNOWN;
-+      }
-+
-+      if (record->type & ARM_SPE_BRANCH_MISS) {
-+              bs_flags->mispred = 1;
-+              bs_flags->predicted = 0;
-+      } else {
-+              bs_flags->mispred = 0;
-+              bs_flags->predicted = 1;
-+      }
-+
-+      if (record->type & ARM_SPE_BRANCH_NOT_TAKEN)
-+              bs_flags->not_taken = 1;
-+
-+      if (record->type & ARM_SPE_IN_TXN)
-+              bs_flags->in_tx = 1;
-+
-+      bs_flags->cycles = min(record->latency, 0xFFFFU);
-+
-+      bstack->nr = 1;
-+      bstack->hw_idx = -1ULL;
-+}
-+
- static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
- {
-       event->header.size = perf_event__sample_event_size(sample, type, 0);
-@@ -394,6 +473,7 @@ static int arm_spe__synth_branch_sample(struct arm_spe_queue *speq,
-       sample.addr = record->to_ip;
-       sample.weight = record->latency;
-       sample.flags = speq->flags;
-+      sample.branch_stack = speq->last_branch;
-       return arm_spe_deliver_synth_event(spe, speq, event, &sample);
- }
-@@ -424,6 +504,7 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq,
-       sample.period = spe->instructions_sample_period;
-       sample.weight = record->latency;
-       sample.flags = speq->flags;
-+      sample.branch_stack = speq->last_branch;
-       return arm_spe_deliver_synth_event(spe, speq, event, &sample);
- }
-@@ -685,6 +766,10 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
-               }
-       }
-+      if (spe->synth_opts.last_branch &&
-+          (spe->sample_branch || spe->sample_instructions))
-+              arm_spe__prep_branch_stack(speq);
-+
-       if (spe->sample_branch && (record->op & ARM_SPE_OP_BRANCH_ERET)) {
-               err = arm_spe__synth_branch_sample(speq, spe->branch_id);
-               if (err)
-@@ -1109,6 +1194,7 @@ static void arm_spe_free_queue(void *priv)
-       thread__zput(speq->thread);
-       arm_spe_decoder_free(speq->decoder);
-       zfree(&speq->event_buf);
-+      zfree(&speq->last_branch);
-       free(speq);
- }
-@@ -1283,6 +1369,19 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
-               id += 1;
-       }
-+      if (spe->synth_opts.last_branch) {
-+              if (spe->synth_opts.last_branch_sz > 1)
-+                      pr_debug("Arm SPE supports only one bstack entry (TGT).\n");
-+
-+              attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
-+              /*
-+               * We don't use the hardware index, but the sample generation
-+               * code uses the new format branch_stack with this field,
-+               * so the event attributes must indicate that it's present.
-+               */
-+              attr.branch_sample_type |= PERF_SAMPLE_BRANCH_HW_INDEX;
-+      }
-+
-       if (spe->synth_opts.branches) {
-               spe->sample_branch = true;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-arm-spe-correctly-set-sample-flags.patch b/queue-6.12/perf-arm-spe-correctly-set-sample-flags.patch
deleted file mode 100644 (file)
index eb8ac25..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-From f86107d0af421f668696ed5516ebc773614aa3b0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 25 Oct 2024 15:30:08 +0100
-Subject: perf arm-spe: Correctly set sample flags
-
-From: Graham Woodward <graham.woodward@arm.com>
-
-[ Upstream commit edff8dad3f9a483259140fb814586b39da430a38 ]
-
-Set flags on all synthesized instruction and branch samples.
-
-Signed-off-by: Graham Woodward <graham.woodward@arm.com>
-Reviewed-by: James Clark <james.clark@linaro.org>
-Tested-by: Leo Yan <leo.yan@arm.com>
-Cc: nd@arm.com
-Cc: mike.leach@linaro.org
-Cc: linux-arm-kernel@lists.infradead.org
-Link: https://lore.kernel.org/r/20241025143009.25419-4-graham.woodward@arm.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 059e9100d82a ("perf event: Fix size of synthesized sample with branch stacks")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-script.c |  1 +
- tools/perf/util/arm-spe.c   | 17 +++++++++++++++++
- tools/perf/util/event.h     |  1 +
- 3 files changed, 19 insertions(+)
-
-diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
-index a644787fa9e1dc..6f3db073786f96 100644
---- a/tools/perf/builtin-script.c
-+++ b/tools/perf/builtin-script.c
-@@ -1728,6 +1728,7 @@ static struct {
-       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
-       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"},
-       {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"},
-+      {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_BRANCH_MISS, "br miss"},
-       {0, NULL}
- };
-diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
-index ce34cc5a2e7163..a004e1721a1ff1 100644
---- a/tools/perf/util/arm-spe.c
-+++ b/tools/perf/util/arm-spe.c
-@@ -98,6 +98,7 @@ struct arm_spe_queue {
-       u64                             timestamp;
-       struct thread                   *thread;
-       u64                             period_instructions;
-+      u32                             flags;
- };
- static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
-@@ -392,6 +393,7 @@ static int arm_spe__synth_branch_sample(struct arm_spe_queue *speq,
-       sample.stream_id = spe_events_id;
-       sample.addr = record->to_ip;
-       sample.weight = record->latency;
-+      sample.flags = speq->flags;
-       return arm_spe_deliver_synth_event(spe, speq, event, &sample);
- }
-@@ -421,6 +423,7 @@ static int arm_spe__synth_instruction_sample(struct arm_spe_queue *speq,
-       sample.data_src = data_src;
-       sample.period = spe->instructions_sample_period;
-       sample.weight = record->latency;
-+      sample.flags = speq->flags;
-       return arm_spe_deliver_synth_event(spe, speq, event, &sample);
- }
-@@ -432,6 +435,19 @@ static const struct midr_range common_ds_encoding_cpus[] = {
-       {},
- };
-+static void arm_spe__sample_flags(struct arm_spe_queue *speq)
-+{
-+      const struct arm_spe_record *record = &speq->decoder->record;
-+
-+      speq->flags = 0;
-+      if (record->op & ARM_SPE_OP_BRANCH_ERET) {
-+              speq->flags = PERF_IP_FLAG_BRANCH;
-+
-+              if (record->type & ARM_SPE_BRANCH_MISS)
-+                      speq->flags |= PERF_IP_FLAG_BRANCH_MISS;
-+      }
-+}
-+
- static void arm_spe__synth_data_source_common(const struct arm_spe_record *record,
-                                             union perf_mem_data_src *data_src)
- {
-@@ -618,6 +634,7 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
-       u64 data_src;
-       int err;
-+      arm_spe__sample_flags(speq);
-       data_src = arm_spe__synth_data_source(speq, record);
-       if (spe->sample_flc) {
-diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
-index f8742e6230a5ab..2744c54f404e7b 100644
---- a/tools/perf/util/event.h
-+++ b/tools/perf/util/event.h
-@@ -66,6 +66,7 @@ enum {
-       PERF_IP_FLAG_VMEXIT             = 1ULL << 12,
-       PERF_IP_FLAG_INTR_DISABLE       = 1ULL << 13,
-       PERF_IP_FLAG_INTR_TOGGLE        = 1ULL << 14,
-+      PERF_IP_FLAG_BRANCH_MISS        = 1ULL << 15,
- };
- #define PERF_IP_FLAG_CHARS "bcrosyiABExghDt"
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-arm-spe-use-arm_spe_op_branch_eret-when-synthes.patch b/queue-6.12/perf-arm-spe-use-arm_spe_op_branch_eret-when-synthes.patch
deleted file mode 100644 (file)
index 2336875..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-From 979a3078c6ef80cfc382e67d88d4fc01e7c392dd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 25 Oct 2024 15:30:07 +0100
-Subject: perf arm-spe: Use ARM_SPE_OP_BRANCH_ERET when synthesizing branches
-
-From: Graham Woodward <graham.woodward@arm.com>
-
-[ Upstream commit c1b67c85108f99af0a80aa9e59a2b94ad95428d7 ]
-
-Instead of checking the type for just branch misses, we can instead
-check for the OP_BRANCH_ERET and synthesise branches as well as
-branch misses.
-
-Signed-off-by: Graham Woodward <graham.woodward@arm.com>
-Reviewed-by: James Clark <james.clark@linaro.org>
-Tested-by: Leo Yan <leo.yan@arm.com>
-Cc: nd@arm.com
-Cc: mike.leach@linaro.org
-Cc: linux-arm-kernel@lists.infradead.org
-Link: https://lore.kernel.org/r/20241025143009.25419-3-graham.woodward@arm.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 059e9100d82a ("perf event: Fix size of synthesized sample with branch stacks")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/arm-spe.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
-diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
-index fcacdd87c0d2b4..ce34cc5a2e7163 100644
---- a/tools/perf/util/arm-spe.c
-+++ b/tools/perf/util/arm-spe.c
-@@ -71,7 +71,7 @@ struct arm_spe {
-       u64                             llc_access_id;
-       u64                             tlb_miss_id;
-       u64                             tlb_access_id;
--      u64                             branch_miss_id;
-+      u64                             branch_id;
-       u64                             remote_access_id;
-       u64                             memory_id;
-       u64                             instructions_id;
-@@ -668,8 +668,8 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
-               }
-       }
--      if (spe->sample_branch && (record->type & ARM_SPE_BRANCH_MISS)) {
--              err = arm_spe__synth_branch_sample(speq, spe->branch_miss_id);
-+      if (spe->sample_branch && (record->op & ARM_SPE_OP_BRANCH_ERET)) {
-+              err = arm_spe__synth_branch_sample(speq, spe->branch_id);
-               if (err)
-                       return err;
-       }
-@@ -1269,12 +1269,12 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
-       if (spe->synth_opts.branches) {
-               spe->sample_branch = true;
--              /* Branch miss */
-+              /* Branch */
-               err = perf_session__deliver_synth_attr_event(session, &attr, id);
-               if (err)
-                       return err;
--              spe->branch_miss_id = id;
--              arm_spe_set_event_name(evlist, id, "branch-miss");
-+              spe->branch_id = id;
-+              arm_spe_set_event_name(evlist, id, "branch");
-               id += 1;
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-arm-spe-use-metadata-to-decide-the-data-source-.patch b/queue-6.12/perf-arm-spe-use-metadata-to-decide-the-data-source-.patch
deleted file mode 100644 (file)
index c1f82c4..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-From 475db7c808a106211ccfd69a597980a561daf49f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 3 Oct 2024 19:53:19 +0100
-Subject: perf arm-spe: Use metadata to decide the data source feature
-
-From: Leo Yan <leo.yan@arm.com>
-
-[ Upstream commit ba5e7169e5483a61899497e23fa18f7ef33aa827 ]
-
-Use the info in the metadata to decide if the data source feature is
-supported. The CPU MIDR must be in the CPU list for the common data
-source encoding.
-
-For the metadata version 1, it doesn't include info for MIDR. In this
-case, due to absent info for making decision, print out warning to
-remind users to upgrade tool and returns false.
-
-Signed-off-by: Leo Yan <leo.yan@arm.com>
-Reviewed-by: James Clark <james.clark@linaro.org>
-Link: https://lore.kernel.org/r/20241003185322.192357-5-leo.yan@arm.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 059e9100d82a ("perf event: Fix size of synthesized sample with branch stacks")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/arm-spe.c | 67 +++++++++++++++++++++++++++++++++++++--
- 1 file changed, 64 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
-index 9890b17241c34a..fcacdd87c0d2b4 100644
---- a/tools/perf/util/arm-spe.c
-+++ b/tools/perf/util/arm-spe.c
-@@ -275,6 +275,20 @@ static int arm_spe_set_tid(struct arm_spe_queue *speq, pid_t tid)
-       return 0;
- }
-+static u64 *arm_spe__get_metadata_by_cpu(struct arm_spe *spe, u64 cpu)
-+{
-+      u64 i;
-+
-+      if (!spe->metadata)
-+              return NULL;
-+
-+      for (i = 0; i < spe->metadata_nr_cpu; i++)
-+              if (spe->metadata[i][ARM_SPE_CPU] == cpu)
-+                      return spe->metadata[i];
-+
-+      return NULL;
-+}
-+
- static struct simd_flags arm_spe__synth_simd_flags(const struct arm_spe_record *record)
- {
-       struct simd_flags simd_flags = {};
-@@ -517,10 +531,57 @@ static void arm_spe__synth_data_source_generic(const struct arm_spe_record *reco
-               data_src->mem_remote = PERF_MEM_REMOTE_REMOTE;
- }
--static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr)
-+static bool arm_spe__is_common_ds_encoding(struct arm_spe_queue *speq)
-+{
-+      struct arm_spe *spe = speq->spe;
-+      bool is_in_cpu_list;
-+      u64 *metadata = NULL;
-+      u64 midr = 0;
-+
-+      /*
-+       * Metadata version 1 doesn't contain any info for MIDR.
-+       * Simply return false in this case.
-+       */
-+      if (spe->metadata_ver == 1) {
-+              pr_warning_once("The data file contains metadata version 1, "
-+                              "which is absent the info for data source. "
-+                              "Please upgrade the tool to record data.\n");
-+              return false;
-+      }
-+
-+      /* CPU ID is -1 for per-thread mode */
-+      if (speq->cpu < 0) {
-+              /*
-+               * On the heterogeneous system, due to CPU ID is -1,
-+               * cannot confirm the data source packet is supported.
-+               */
-+              if (!spe->is_homogeneous)
-+                      return false;
-+
-+              /* In homogeneous system, simply use CPU0's metadata */
-+              if (spe->metadata)
-+                      metadata = spe->metadata[0];
-+      } else {
-+              metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu);
-+      }
-+
-+      if (!metadata)
-+              return false;
-+
-+      midr = metadata[ARM_SPE_CPU_MIDR];
-+
-+      is_in_cpu_list = is_midr_in_range_list(midr, common_ds_encoding_cpus);
-+      if (is_in_cpu_list)
-+              return true;
-+      else
-+              return false;
-+}
-+
-+static u64 arm_spe__synth_data_source(struct arm_spe_queue *speq,
-+                                    const struct arm_spe_record *record)
- {
-       union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA };
--      bool is_common = is_midr_in_range_list(midr, common_ds_encoding_cpus);
-+      bool is_common = arm_spe__is_common_ds_encoding(speq);
-       /* Only synthesize data source for LDST operations */
-       if (!is_ldst_op(record->op))
-@@ -557,7 +618,7 @@ static int arm_spe_sample(struct arm_spe_queue *speq)
-       u64 data_src;
-       int err;
--      data_src = arm_spe__synth_data_source(record, spe->midr);
-+      data_src = arm_spe__synth_data_source(speq, record);
-       if (spe->sample_flc) {
-               if (record->type & ARM_SPE_L1D_MISS) {
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-arm-spe-use-old-behavior-when-opening-old-spe-files.patch b/queue-6.12/perf-arm-spe-use-old-behavior-when-opening-old-spe-files.patch
deleted file mode 100644 (file)
index 6701a20..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-From ba993e5ada1ddce7a71140dc85ef65bc2cd981bc Mon Sep 17 00:00:00 2001
-From: James Clark <james.clark@linaro.org>
-Date: Tue, 29 Oct 2024 14:37:33 +0000
-Subject: perf arm-spe: Use old behavior when opening old SPE files
-
-From: James Clark <james.clark@linaro.org>
-
-commit ba993e5ada1ddce7a71140dc85ef65bc2cd981bc upstream.
-
-Since the linked commit, we stopped interpreting data source if the
-perf.data file doesn't have the new metadata version. This means that
-perf c2c will show no samples in this case.
-
-Keep the old behavior so old files can be opened, but also still show
-the new warning that updating might improve the decoding.
-
-Also re-write the warning to be more concise and specific to a user.
-
-Fixes: ba5e7169e548 ("perf arm-spe: Use metadata to decide the data source feature")
-Signed-off-by: James Clark <james.clark@linaro.org>
-Reviewed-by: Leo Yan <leo.yan@arm.com>
-Cc: Julio.Suarez@arm.com
-Cc: Kiel.Friedt@arm.com
-Cc: Ryan.Roberts@arm.com
-Cc: Will Deacon <will@kernel.org>
-Cc: Mike Leach <mike.leach@linaro.org>
-Cc: linux-arm-kernel@lists.infradead.org
-Cc: Besar Wicaksono <bwicaksono@nvidia.com>
-Cc: John Garry <john.g.garry@oracle.com>
-Link: https://lore.kernel.org/r/20241029143734.291638-1-james.clark@linaro.org
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/util/arm-spe.c |   50 ++++++++++++++++++++++------------------------
- 1 file changed, 24 insertions(+), 26 deletions(-)
-
---- a/tools/perf/util/arm-spe.c
-+++ b/tools/perf/util/arm-spe.c
-@@ -635,37 +635,35 @@ static bool arm_spe__is_common_ds_encodi
-       u64 *metadata = NULL;
-       u64 midr = 0;
--      /*
--       * Metadata version 1 doesn't contain any info for MIDR.
--       * Simply return false in this case.
--       */
-+      /* Metadata version 1 assumes all CPUs are the same (old behavior) */
-       if (spe->metadata_ver == 1) {
--              pr_warning_once("The data file contains metadata version 1, "
--                              "which is absent the info for data source. "
--                              "Please upgrade the tool to record data.\n");
--              return false;
--      }
--
--      /* CPU ID is -1 for per-thread mode */
--      if (speq->cpu < 0) {
--              /*
--               * On the heterogeneous system, due to CPU ID is -1,
--               * cannot confirm the data source packet is supported.
--               */
--              if (!spe->is_homogeneous)
--                      return false;
-+              const char *cpuid;
--              /* In homogeneous system, simply use CPU0's metadata */
--              if (spe->metadata)
--                      metadata = spe->metadata[0];
-+              pr_warning_once("Old SPE metadata, re-record to improve decode accuracy\n");
-+              cpuid = perf_env__cpuid(spe->session->evlist->env);
-+              midr = strtol(cpuid, NULL, 16);
-       } else {
--              metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu);
--      }
-+              /* CPU ID is -1 for per-thread mode */
-+              if (speq->cpu < 0) {
-+                      /*
-+                       * On the heterogeneous system, due to CPU ID is -1,
-+                       * cannot confirm the data source packet is supported.
-+                       */
-+                      if (!spe->is_homogeneous)
-+                              return false;
-+
-+                      /* In homogeneous system, simply use CPU0's metadata */
-+                      if (spe->metadata)
-+                              metadata = spe->metadata[0];
-+              } else {
-+                      metadata = arm_spe__get_metadata_by_cpu(spe, speq->cpu);
-+              }
--      if (!metadata)
--              return false;
-+              if (!metadata)
-+                      return false;
--      midr = metadata[ARM_SPE_CPU_MIDR];
-+              midr = metadata[ARM_SPE_CPU_MIDR];
-+      }
-       is_in_cpu_list = is_midr_in_range_list(midr, common_ds_encoding_cpus);
-       if (is_in_cpu_list)
diff --git a/queue-6.12/perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch b/queue-6.12/perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch
deleted file mode 100644 (file)
index 24bc65e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 04779f87f572c359f1d6f02092cb2332481df5eb Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 8 Jun 2026 08:10:43 -0300
-Subject: perf bpf: Add NULL check for btf__type_by_id() in
- synthesize_bpf_prog_name()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 903b0526dcf86d030c5970b4b0a67f9c227368e2 ]
-
-synthesize_bpf_prog_name() calls btf__type_by_id() and immediately
-dereferences the result via t->name_off without checking for NULL.
-btf__type_by_id() returns NULL when the type_id is invalid or out
-of range.  When processing perf.data files, finfo->type_id comes from
-untrusted input, so an invalid ID causes a NULL pointer dereference.
-
-Fix by checking t for NULL before dereferencing.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: fc462ac75b36daaa ("perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog()")
-Cc: Song Liu <songliubraving@fb.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/bpf-event.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
-index 8919fc52eecd45..6c9a4a1b80a24c 100644
---- a/tools/perf/util/bpf-event.c
-+++ b/tools/perf/util/bpf-event.c
-@@ -138,7 +138,8 @@ static int synthesize_bpf_prog_name(char *buf, int size,
-       if (btf) {
-               finfo = func_infos + sub_id * info->func_info_rec_size;
-               t = btf__type_by_id(btf, finfo->type_id);
--              short_name = btf__name_by_offset(btf, t->name_off);
-+              if (t)
-+                      short_name = btf__name_by_offset(btf, t->name_off);
-       } else if (sub_id == 0 && sub_prog_cnt == 1) {
-               /* no subprog */
-               if (info->name[0])
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch b/queue-6.12/perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch
deleted file mode 100644 (file)
index 6a0f3eb..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From d728900c519019491aaf8d451d942733edcf3615 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 21:03:16 -0300
-Subject: perf bpf: Bounds-check array offsets in bpil_offs_to_addr()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 033e85edfbf271f92979d2a39aeaf40f8472a795 ]
-
-bpil_offs_to_addr() converts offsets stored in perf.data's
-bpf_prog_info_linear structure into heap pointers by adding the offset
-to the data allocation base.  The offsets come from untrusted file input
-and are not validated against data_len.
-
-If an offset exceeds data_len, the computed address points outside the
-allocated data buffer.  Callers like synthesize_bpf_prog_name() then
-dereference prog_tags[sub_id] or func_info pointers, reading arbitrary
-heap memory.
-
-Add a bounds check: when an offset exceeds data_len, zero the field
-and skip the conversion.  This prevents out-of-bounds pointer
-construction from crafted perf.data files.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: 6ac22d036f86c4e2 ("perf bpf: Pull in bpf_program__get_prog_info_linear()")
-Cc: Dave Marchevsky <davemarchevsky@fb.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/bpf-utils.c | 16 ++++++++++++++++
- 1 file changed, 16 insertions(+)
-
-diff --git a/tools/perf/util/bpf-utils.c b/tools/perf/util/bpf-utils.c
-index 5a66dc8594aa88..03a621a0c5dcd5 100644
---- a/tools/perf/util/bpf-utils.c
-+++ b/tools/perf/util/bpf-utils.c
-@@ -264,12 +264,28 @@ void bpil_offs_to_addr(struct perf_bpil *info_linear)
-       for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) {
-               const struct bpil_array_desc *desc = &bpil_array_desc[i];
-               __u64 addr, offs;
-+              __u32 count, size;
-               if ((info_linear->arrays & (1UL << i)) == 0)
-                       continue;
-               offs = bpf_prog_info_read_offset_u64(&info_linear->info,
-                                                    desc->array_offset);
-+              count = bpf_prog_info_read_offset_u32(&info_linear->info,
-+                                                    desc->count_offset);
-+              size = bpf_prog_info_read_offset_u32(&info_linear->info,
-+                                                   desc->size_offset);
-+              /* offset and extent from perf.data are untrusted â€” keep within data[] */
-+              if (offs >= info_linear->data_len ||
-+                  (u64)count * size > info_linear->data_len - offs) {
-+                      bpf_prog_info_set_offset_u64(&info_linear->info,
-+                                                   desc->array_offset, 0);
-+                      bpf_prog_info_set_offset_u32(&info_linear->info,
-+                                                   desc->count_offset, 0);
-+                      /* clear the bit so bpil_addr_to_offs() won't reverse a zeroed address */
-+                      info_linear->arrays &= ~(1UL << i);
-+                      continue;
-+              }
-               addr = offs + ptr_to_u64(info_linear->data);
-               bpf_prog_info_set_offset_u64(&info_linear->info,
-                                            desc->array_offset, addr);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch b/queue-6.12/perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch
deleted file mode 100644 (file)
index 054d1f6..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From 8733e9bbace794b8cd131440af75c81186fe1502 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 14:23:15 -0300
-Subject: perf bpf: Use scnprintf() in snprintf_hex() and
- synthesize_bpf_prog_name()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit cab3a9331ed0b3f884dd61c8a25b3cf123705982 ]
-
-Both functions accumulate formatted output via ret += snprintf(buf + ret,
-size - ret, ...).  If the buffer is too small and snprintf() returns more
-than the remaining space, ret exceeds size and the next 'size - ret'
-underflows, causing snprintf() to write past the buffer end.
-
-Switch to scnprintf() which returns the actual number of bytes written,
-making the accumulation safe.
-
-Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Song Liu <song@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/bpf-event.c | 11 ++++++-----
- 1 file changed, 6 insertions(+), 5 deletions(-)
-
-diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
-index d9123c9637baaf..8919fc52eecd45 100644
---- a/tools/perf/util/bpf-event.c
-+++ b/tools/perf/util/bpf-event.c
-@@ -28,7 +28,7 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len)
-       size_t i;
-       for (i = 0; i < len; i++)
--              ret += snprintf(buf + ret, size - ret, "%02x", data[i]);
-+              ret += scnprintf(buf + ret, size - ret, "%02x", data[i]);
-       return ret;
- }
-@@ -132,7 +132,7 @@ static int synthesize_bpf_prog_name(char *buf, int size,
-       const struct btf_type *t;
-       int name_len;
--      name_len = snprintf(buf, size, "bpf_prog_");
-+      name_len = scnprintf(buf, size, "bpf_prog_");
-       name_len += snprintf_hex(buf + name_len, size - name_len,
-                                prog_tags[sub_id], BPF_TAG_SIZE);
-       if (btf) {
-@@ -145,9 +145,10 @@ static int synthesize_bpf_prog_name(char *buf, int size,
-                       short_name = info->name;
-       } else
-               short_name = "F";
--      if (short_name)
--              name_len += snprintf(buf + name_len, size - name_len,
--                                   "_%s", short_name);
-+      if (short_name) {
-+              name_len += scnprintf(buf + name_len, size - name_len,
-+                                    "_%s", short_name);
-+      }
-       return name_len;
- }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch b/queue-6.12/perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch
deleted file mode 100644 (file)
index 6f46487..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-From 8a9e06475407592b6ea1cfa70f569f373cdd6a39 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 21:01:15 -0300
-Subject: perf bpf: Validate func_info_rec_size and sub_id in
- synthesize_bpf_prog_name()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 10b3c3d63ecc17c6acb855bac5f40367f1115765 ]
-
-synthesize_bpf_prog_name() computes a pointer into the func_info array
-using sub_id * info->func_info_rec_size without validating either value.
-Both come from perf.data and are untrusted:
-
-- A func_info_rec_size smaller than sizeof(struct bpf_func_info) means
-  the finfo pointer would reference a truncated entry, reading past it
-  into adjacent data.
-
-- A sub_id >= nr_func_info computes an offset past the func_info buffer,
-  causing an out-of-bounds read.
-
-Add bounds checks for both values before computing the pointer offset.
-When validation fails, fall through to the non-BTF name path instead
-of reading garbage.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs")
-Cc: Song Liu <songliubraving@fb.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/bpf-event.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c
-index 6c9a4a1b80a24c..db89053ce96808 100644
---- a/tools/perf/util/bpf-event.c
-+++ b/tools/perf/util/bpf-event.c
-@@ -135,7 +135,9 @@ static int synthesize_bpf_prog_name(char *buf, int size,
-       name_len = scnprintf(buf, size, "bpf_prog_");
-       name_len += snprintf_hex(buf + name_len, size - name_len,
-                                prog_tags[sub_id], BPF_TAG_SIZE);
--      if (btf) {
-+      if (btf &&
-+          info->func_info_rec_size >= sizeof(*finfo) &&
-+          sub_id < info->nr_func_info) {
-               finfo = func_infos + sub_id * info->func_info_rec_size;
-               t = btf__type_by_id(btf, finfo->type_id);
-               if (t)
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-build-id-change-sprintf-functions-to-snprintf.patch b/queue-6.12/perf-build-id-change-sprintf-functions-to-snprintf.patch
deleted file mode 100644 (file)
index daacf1c..0000000
+++ /dev/null
@@ -1,429 +0,0 @@
-From b68d22b74b85ac8084e7b59d6a88b4542ec75792 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 24 Jul 2025 09:32:43 -0700
-Subject: perf build-id: Change sprintf functions to snprintf
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit fccaaf6fbbc59910edcf276f97a5b2ef5778c55e ]
-
-Pass in a size argument rather than implying all build id strings must
-be SBUILD_ID_SIZE.
-
-Signed-off-by: Ian Rogers <irogers@google.com>
-Link: https://lore.kernel.org/r/20250724163302.596743-4-irogers@google.com
-[ fixed some build errors ]
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 2ea64782a428 ("perf tools: Use snprintf() in dso__read_running_kernel_build_id()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-buildid-cache.c            | 12 +++----
- tools/perf/builtin-buildid-list.c             |  6 ++--
- tools/perf/tests/sdt.c                        |  2 +-
- tools/perf/util/build-id.c                    | 33 ++++++++-----------
- tools/perf/util/build-id.h                    |  6 ++--
- tools/perf/util/disasm.c                      |  2 +-
- tools/perf/util/dso.c                         |  4 +--
- tools/perf/util/dsos.c                        |  2 +-
- tools/perf/util/event.c                       |  2 +-
- tools/perf/util/header.c                      |  2 +-
- tools/perf/util/map.c                         |  2 +-
- tools/perf/util/probe-event.c                 |  4 +--
- tools/perf/util/probe-file.c                  |  4 +--
- tools/perf/util/probe-finder.c                |  2 +-
- .../scripting-engines/trace-event-python.c    |  7 ++--
- tools/perf/util/symbol.c                      |  2 +-
- 16 files changed, 42 insertions(+), 50 deletions(-)
-
-diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
-index b0511d16aeb6c7..3f7739b21148bd 100644
---- a/tools/perf/builtin-buildid-cache.c
-+++ b/tools/perf/builtin-buildid-cache.c
-@@ -31,7 +31,7 @@
- #include <linux/string.h>
- #include <linux/err.h>
--static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
-+static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid, size_t sbuildid_size)
- {
-       char root_dir[PATH_MAX];
-       char *p;
-@@ -42,7 +42,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
-       if (!p)
-               return -1;
-       *p = '\0';
--      return sysfs__sprintf_build_id(root_dir, sbuildid);
-+      return sysfs__snprintf_build_id(root_dir, sbuildid, sbuildid_size);
- }
- static int build_id_cache__kcore_dir(char *dir, size_t sz)
-@@ -128,7 +128,7 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
-               return -1;
-       *p = '\0';
--      if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0)
-+      if (build_id_cache__kcore_buildid(from_dir, sbuildid, sizeof(sbuildid)) < 0)
-               return -1;
-       scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s",
-@@ -187,7 +187,7 @@ static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
-               return -1;
-       }
--      build_id__sprintf(&bid, sbuild_id);
-+      build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-       err = build_id_cache__add_s(sbuild_id, filename, nsi,
-                                   false, false);
-       pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
-@@ -211,7 +211,7 @@ static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi)
-               return -1;
-       }
--      build_id__sprintf(&bid, sbuild_id);
-+      build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-       err = build_id_cache__remove_s(sbuild_id);
-       pr_debug("Removing %s %s: %s\n", sbuild_id, filename,
-                err ? "FAIL" : "Ok");
-@@ -317,7 +317,7 @@ static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
-       }
-       err = 0;
--      build_id__sprintf(&bid, sbuild_id);
-+      build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-       if (build_id_cache__cached(sbuild_id))
-               err = build_id_cache__remove_s(sbuild_id);
-diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
-index 52dfacaff8e39f..ba8ba0303920c5 100644
---- a/tools/perf/builtin-buildid-list.c
-+++ b/tools/perf/builtin-buildid-list.c
-@@ -31,7 +31,7 @@ static int buildid__map_cb(struct map *map, void *arg __maybe_unused)
-       memset(bid_buf, 0, sizeof(bid_buf));
-       if (dso__has_build_id(dso))
--              build_id__sprintf(dso__bid_const(dso), bid_buf);
-+              build_id__snprintf(dso__bid_const(dso), bid_buf, sizeof(bid_buf));
-       printf("%s %16" PRIx64 " %16" PRIx64, bid_buf, map__start(map), map__end(map));
-       if (dso_long_name != NULL)
-               printf(" %s", dso_long_name);
-@@ -57,7 +57,7 @@ static int sysfs__fprintf_build_id(FILE *fp)
-       char sbuild_id[SBUILD_ID_SIZE];
-       int ret;
--      ret = sysfs__sprintf_build_id("/", sbuild_id);
-+      ret = sysfs__snprintf_build_id("/", sbuild_id, sizeof(sbuild_id));
-       if (ret != sizeof(sbuild_id))
-               return ret < 0 ? ret : -EINVAL;
-@@ -69,7 +69,7 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
-       char sbuild_id[SBUILD_ID_SIZE];
-       int ret;
--      ret = filename__sprintf_build_id(name, sbuild_id);
-+      ret = filename__snprintf_build_id(name, sbuild_id, sizeof(sbuild_id));
-       if (ret != sizeof(sbuild_id))
-               return ret < 0 ? ret : -EINVAL;
-diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
-index 91971289925102..663c8f700069d4 100644
---- a/tools/perf/tests/sdt.c
-+++ b/tools/perf/tests/sdt.c
-@@ -37,7 +37,7 @@ static int build_id_cache__add_file(const char *filename)
-               return err;
-       }
--      build_id__sprintf(&bid, sbuild_id);
-+      build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-       err = build_id_cache__add_s(sbuild_id, filename, NULL, false, false);
-       if (err < 0)
-               pr_debug("Failed to add build id cache of %s\n", filename);
-diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
-index ee00313d5d7e2a..ac642c758d5a17 100644
---- a/tools/perf/util/build-id.c
-+++ b/tools/perf/util/build-id.c
-@@ -67,24 +67,17 @@ int build_id__mark_dso_hit(const struct perf_tool *tool __maybe_unused,
-       return 0;
- }
--int build_id__sprintf(const struct build_id *build_id, char *bf)
-+int build_id__snprintf(const struct build_id *build_id, char *bf, size_t bf_size)
- {
--      char *bid = bf;
--      const u8 *raw = build_id->data;
--      size_t i;
--
--      bf[0] = 0x0;
-+      size_t offs = 0;
--      for (i = 0; i < build_id->size; ++i) {
--              sprintf(bid, "%02x", *raw);
--              ++raw;
--              bid += 2;
--      }
-+      for (size_t i = 0; i < build_id->size && offs < bf_size; ++i)
-+              offs += snprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]);
--      return (bid - bf) + 1;
-+      return offs;
- }
--int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
-+int sysfs__snprintf_build_id(const char *root_dir, char *sbuild_id, size_t sbuild_id_size)
- {
-       char notes[PATH_MAX];
-       struct build_id bid;
-@@ -99,10 +92,10 @@ int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
-       if (ret < 0)
-               return ret;
--      return build_id__sprintf(&bid, sbuild_id);
-+      return build_id__snprintf(&bid, sbuild_id, sbuild_id_size);
- }
--int filename__sprintf_build_id(const char *pathname, char *sbuild_id)
-+int filename__snprintf_build_id(const char *pathname, char *sbuild_id, size_t sbuild_id_size)
- {
-       struct build_id bid;
-       int ret;
-@@ -111,7 +104,7 @@ int filename__sprintf_build_id(const char *pathname, char *sbuild_id)
-       if (ret < 0)
-               return ret;
--      return build_id__sprintf(&bid, sbuild_id);
-+      return build_id__snprintf(&bid, sbuild_id, sbuild_id_size);
- }
- /* asnprintf consolidates asprintf and snprintf */
-@@ -212,9 +205,9 @@ static bool build_id_cache__valid_id(char *sbuild_id)
-               return false;
-       if (!strcmp(pathname, DSO__NAME_KALLSYMS))
--              ret = sysfs__sprintf_build_id("/", real_sbuild_id);
-+              ret = sysfs__snprintf_build_id("/", real_sbuild_id, sizeof(real_sbuild_id));
-       else if (pathname[0] == '/')
--              ret = filename__sprintf_build_id(pathname, real_sbuild_id);
-+              ret = filename__snprintf_build_id(pathname, real_sbuild_id, sizeof(real_sbuild_id));
-       else
-               ret = -EINVAL;  /* Should we support other special DSO cache? */
-       if (ret >= 0)
-@@ -243,7 +236,7 @@ char *__dso__build_id_filename(const struct dso *dso, char *bf, size_t size,
-       if (!dso__has_build_id(dso))
-               return NULL;
--      build_id__sprintf(dso__bid_const(dso), sbuild_id);
-+      build_id__snprintf(dso__bid_const(dso), sbuild_id, sizeof(sbuild_id));
-       linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
-       if (!linkname)
-               return NULL;
-@@ -769,7 +762,7 @@ static int build_id_cache__add_b(const struct build_id *bid,
- {
-       char sbuild_id[SBUILD_ID_SIZE];
--      build_id__sprintf(bid, sbuild_id);
-+      build_id__snprintf(bid, sbuild_id, sizeof(sbuild_id));
-       return __build_id_cache__add_s(sbuild_id, name, nsi, is_kallsyms,
-                                      is_vdso, proper_name, root_dir);
-diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
-index a212497bfdb0a5..37b8f00f8314c3 100644
---- a/tools/perf/util/build-id.h
-+++ b/tools/perf/util/build-id.h
-@@ -21,10 +21,10 @@ struct feat_fd;
- struct nsinfo;
- void build_id__init(struct build_id *bid, const u8 *data, size_t size);
--int build_id__sprintf(const struct build_id *build_id, char *bf);
-+int build_id__snprintf(const struct build_id *build_id, char *bf, size_t bf_size);
- bool build_id__is_defined(const struct build_id *bid);
--int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
--int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
-+int sysfs__snprintf_build_id(const char *root_dir, char *sbuild_id, size_t sbuild_id_size);
-+int filename__snprintf_build_id(const char *pathname, char *sbuild_id, size_t sbuild_id_size);
- char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
-                                   size_t size);
-diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c
-index 8f35232f7f22c7..d8c27921332238 100644
---- a/tools/perf/util/disasm.c
-+++ b/tools/perf/util/disasm.c
-@@ -1220,7 +1220,7 @@ int symbol__strerror_disassemble(struct map_symbol *ms, int errnum, char *buf, s
-               char *build_id_msg = NULL;
-               if (dso__has_build_id(dso)) {
--                      build_id__sprintf(dso__bid(dso), bf + 15);
-+                      build_id__snprintf(dso__bid(dso), bf + 15, sizeof(bf) - 15);
-                       build_id_msg = bf;
-               }
-               scnprintf(buf, buflen,
-diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
-index 7c12d53656887d..aae754b1cc624a 100644
---- a/tools/perf/util/dso.c
-+++ b/tools/perf/util/dso.c
-@@ -215,7 +215,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
-                       break;
-               }
--              build_id__sprintf(dso__bid_const(dso), build_id_hex);
-+              build_id__snprintf(dso__bid_const(dso), build_id_hex, sizeof(build_id_hex));
-               len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
-               snprintf(filename + len, size - len, "%.2s/%s.debug",
-                        build_id_hex, build_id_hex + 2);
-@@ -1694,7 +1694,7 @@ static size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
- {
-       char sbuild_id[SBUILD_ID_SIZE];
--      build_id__sprintf(dso__bid(dso), sbuild_id);
-+      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-       return fprintf(fp, "%s", sbuild_id);
- }
-diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c
-index e0998e2a7c4e75..b2172632b3cdd7 100644
---- a/tools/perf/util/dsos.c
-+++ b/tools/perf/util/dsos.c
-@@ -370,7 +370,7 @@ static int dsos__fprintf_buildid_cb(struct dso *dso, void *data)
-       if (args->skip && args->skip(dso, args->parm))
-               return 0;
--      build_id__sprintf(dso__bid(dso), sbuild_id);
-+      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-       args->ret += fprintf(args->fp, "%-40s %s\n", sbuild_id, dso__long_name(dso));
-       return 0;
- }
-diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
-index 1e5085817e8250..ce6c70c1d3ee53 100644
---- a/tools/perf/util/event.c
-+++ b/tools/perf/util/event.c
-@@ -330,7 +330,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
-               build_id__init(&bid, event->mmap2.build_id,
-                              event->mmap2.build_id_size);
--              build_id__sprintf(&bid, sbuild_id);
-+              build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-               return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
-                                  " <%s>]: %c%c%c%c %s\n",
-diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
-index 8c15ce90466997..2d8eda9b614ef1 100644
---- a/tools/perf/util/header.c
-+++ b/tools/perf/util/header.c
-@@ -2374,7 +2374,7 @@ static int __event_process_build_id(struct perf_record_header_build_id *bev,
-                       free(m.name);
-               }
--              build_id__sprintf(dso__bid(dso), sbuild_id);
-+              build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-               pr_debug("build id event received for %s: %s [%zu]\n",
-                        dso__long_name(dso), sbuild_id, size);
-               dso__put(dso);
-diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
-index d729438b7d6573..0f6b185f95896a 100644
---- a/tools/perf/util/map.c
-+++ b/tools/perf/util/map.c
-@@ -354,7 +354,7 @@ int map__load(struct map *map)
-               if (dso__has_build_id(dso)) {
-                       char sbuild_id[SBUILD_ID_SIZE];
--                      build_id__sprintf(dso__bid(dso), sbuild_id);
-+                      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-                       pr_debug("%s with build id %s not found", name, sbuild_id);
-               } else
-                       pr_debug("Failed to open %s", name);
-diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
-index a17c9b8a7a792d..72a71acf17c8c6 100644
---- a/tools/perf/util/probe-event.c
-+++ b/tools/perf/util/probe-event.c
-@@ -498,7 +498,7 @@ static struct debuginfo *open_from_debuginfod(struct dso *dso, struct nsinfo *ns
-       if (!c)
-               return NULL;
--      build_id__sprintf(dso__bid(dso), sbuild_id);
-+      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-       fd = debuginfod_find_debuginfo(c, (const unsigned char *)sbuild_id,
-                                       0, &path);
-       if (fd >= 0)
-@@ -1071,7 +1071,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
-       }
-       if (dinfo->build_id) {
-               build_id__init(&bid, dinfo->build_id, BUILD_ID_SIZE);
--              build_id__sprintf(&bid, sbuild_id);
-+              build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-       }
-       debuginfo__delete(dinfo);
-       if (ret == 0 || ret == -ENOENT) {
-diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
-index 3d50de3217d50a..9ea0a838f59310 100644
---- a/tools/perf/util/probe-file.c
-+++ b/tools/perf/util/probe-file.c
-@@ -467,10 +467,10 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target,
-       if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
-               target = DSO__NAME_KALLSYMS;
-               is_kallsyms = true;
--              ret = sysfs__sprintf_build_id("/", sbuildid);
-+              ret = sysfs__snprintf_build_id("/", sbuildid, sizeof(sbuildid));
-       } else {
-               nsinfo__mountns_enter(nsi, &nsc);
--              ret = filename__sprintf_build_id(target, sbuildid);
-+              ret = filename__snprintf_build_id(target, sbuildid, sizeof(sbuildid));
-               nsinfo__mountns_exit(&nsc);
-       }
-diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
-index a30f88ed030044..cd6da777c16170 100644
---- a/tools/perf/util/probe-finder.c
-+++ b/tools/perf/util/probe-finder.c
-@@ -848,7 +848,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
-               comp_dir = cu_get_comp_dir(&pf->cu_die);
-               if (pf->dbg->build_id) {
-                       build_id__init(&bid, pf->dbg->build_id, BUILD_ID_SIZE);
--                      build_id__sprintf(&bid, sbuild_id);
-+                      build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id));
-               }
-               ret = find_source_path(pf->fname, sbuild_id, comp_dir, &fpath);
-               if (ret < 0) {
-diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
-index d7183134b66993..780f7e720849ea 100644
---- a/tools/perf/util/scripting-engines/trace-event-python.c
-+++ b/tools/perf/util/scripting-engines/trace-event-python.c
-@@ -795,14 +795,13 @@ static void set_sym_in_dict(PyObject *dict, struct addr_location *al,
-                           const char *dso_map_start, const char *dso_map_end,
-                           const char *sym_field, const char *symoff_field)
- {
--      char sbuild_id[SBUILD_ID_SIZE];
--
-       if (al->map) {
-+              char sbuild_id[SBUILD_ID_SIZE];
-               struct dso *dso = map__dso(al->map);
-               pydict_set_item_string_decref(dict, dso_field,
-                                             _PyUnicode_FromString(dso__name(dso)));
--              build_id__sprintf(dso__bid(dso), sbuild_id);
-+              build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-               pydict_set_item_string_decref(dict, dso_bid_field,
-                       _PyUnicode_FromString(sbuild_id));
-               pydict_set_item_string_decref(dict, dso_map_start,
-@@ -1250,7 +1249,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
-       char sbuild_id[SBUILD_ID_SIZE];
-       PyObject *t;
--      build_id__sprintf(dso__bid(dso), sbuild_id);
-+      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-       t = tuple_new(5);
-diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
-index 249de806f8e0d3..b1b4a2d4b7e46c 100644
---- a/tools/perf/util/symbol.c
-+++ b/tools/perf/util/symbol.c
-@@ -2135,7 +2135,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
-                       goto proc_kallsyms;
-       }
--      build_id__sprintf(dso__bid(dso), sbuild_id);
-+      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-       /* Find kallsyms in build-id cache with kcore */
-       scnprintf(path, sizeof(path), "%s/%s/%s",
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-build-id-ensure-snprintf-string-is-empty-when-size-is-0.patch b/queue-6.12/perf-build-id-ensure-snprintf-string-is-empty-when-size-is-0.patch
deleted file mode 100644 (file)
index c111220..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 0dc96cae063cbf9ebf6631b33b08e9ba02324248 Mon Sep 17 00:00:00 2001
-From: Ian Rogers <irogers@google.com>
-Date: Thu, 18 Sep 2025 10:24:16 -0700
-Subject: perf build-id: Ensure snprintf string is empty when size is 0
-
-From: Ian Rogers <irogers@google.com>
-
-commit 0dc96cae063cbf9ebf6631b33b08e9ba02324248 upstream.
-
-The string result of build_id__snprintf() is unconditionally used in
-places like dsos__fprintf_buildid_cb(). If the build id has size 0 then
-this creates a use of uninitialized memory. Add null termination for the
-size 0 case.
-
-A similar fix was written by Jiri Olsa in commit 6311951d4f8f28c4 ("perf
-tools: Initialize output buffer in build_id__sprintf") but lost in the
-transition to snprintf.
-
-Fixes: fccaaf6fbbc59910 ("perf build-id: Change sprintf functions to snprintf")
-Signed-off-by: Ian Rogers <irogers@google.com>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-Cc: Howard Chu <howardchu95@gmail.com>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Kan Liang <kan.liang@linux.intel.com>
-Cc: Mark Rutland <mark.rutland@arm.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/util/build-id.c |    7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/tools/perf/util/build-id.c
-+++ b/tools/perf/util/build-id.c
-@@ -71,6 +71,13 @@ int build_id__snprintf(const struct buil
- {
-       size_t offs = 0;
-+      if (build_id->size == 0) {
-+              /* Ensure bf is always \0 terminated. */
-+              if (bf_size > 0)
-+                      bf[0] = '\0';
-+              return 0;
-+      }
-+
-       for (size_t i = 0; i < build_id->size && offs < bf_size; ++i)
-               offs += snprintf(bf + offs, bf_size - offs, "%02x", build_id->data[i]);
diff --git a/queue-6.12/perf-build-id-fix-off-by-one-bug-when-printing-kernel-module-build-id.patch b/queue-6.12/perf-build-id-fix-off-by-one-bug-when-printing-kernel-module-build-id.patch
deleted file mode 100644 (file)
index 4ad7ead..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From 017bca78e4d72b1ff027d368c20a1b2c654edaf7 Mon Sep 17 00:00:00 2001
-From: Michael Petlan <mpetlan@redhat.com>
-Date: Wed, 20 May 2026 00:38:55 +0200
-Subject: perf build-id: Fix off-by-one bug when printing kernel/module build-id
-
-From: Michael Petlan <mpetlan@redhat.com>
-
-commit 017bca78e4d72b1ff027d368c20a1b2c654edaf7 upstream.
-
-When changing sprintf functions to snprintf, one byte got lost. Since
-snprintf ones do not handle the '\0' terminating character, the number
-of printed characters is 40, while sizeof(sbuild_id) is 41, including
-the terminating '\0' character.
-
-This makes the later check fail so that nothing is printed.
-
-Fix that.
-
-Before:
-
-    [Michael@Carbon ~]$ perf buildid-list -k
-    [Michael@Carbon ~]$
-
-After:
-
-    [Michael@Carbon ~]$ perf buildid-list -k
-    a527806324d543c4bc3ff2f9c9519d494fed5f68
-    [Michael@Carbon ~]$
-
-Fixes: fccaaf6fbbc59910 ("perf build-id: Change sprintf functions to snprintf")
-Signed-off-by: Michael Petlan <mpetlan@redhat.com>
-Tested-by: Ian Rogers <irogers@google.com>
-Cc: Ian Rogers <irogers@google.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/builtin-buildid-list.c |    4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/tools/perf/builtin-buildid-list.c
-+++ b/tools/perf/builtin-buildid-list.c
-@@ -58,7 +58,7 @@ static int sysfs__fprintf_build_id(FILE
-       int ret;
-       ret = sysfs__snprintf_build_id("/", sbuild_id, sizeof(sbuild_id));
--      if (ret != sizeof(sbuild_id))
-+      if (ret + 1 != sizeof(sbuild_id))
-               return ret < 0 ? ret : -EINVAL;
-       return fprintf(fp, "%s\n", sbuild_id);
-@@ -70,7 +70,7 @@ static int filename__fprintf_build_id(co
-       int ret;
-       ret = filename__snprintf_build_id(name, sbuild_id, sizeof(sbuild_id));
--      if (ret != sizeof(sbuild_id))
-+      if (ret + 1 != sizeof(sbuild_id))
-               return ret < 0 ? ret : -EINVAL;
-       return fprintf(fp, "%s\n", sbuild_id);
diff --git a/queue-6.12/perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch b/queue-6.12/perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch
deleted file mode 100644 (file)
index 8c716f3..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-From 7f9eb9343a7e7e5e0c62b1a3a1e3299d46cc8b55 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 11:05:13 -0300
-Subject: perf c2c: Bounds-check CPU and node IDs before bitmap and array
- access
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 65117c3da50f749f4c22eb7a7effc53453dff57f ]
-
-c2c_he__set_cpu() passes sample->cpu directly to __set_bit(cpu, cpuset)
-after only checking for the (u32)-1 sentinel.  The cpuset bitmap is
-allocated with c2c.cpus_cnt bits (from env->nr_cpus_avail), so a crafted
-perf.data with CPU IDs exceeding that count causes out-of-bounds heap
-writes.
-
-c2c_he__set_node() similarly passes the node ID from mem2node__node()
-to __set_bit(node, nodeset) after only checking for negative values.
-The nodeset bitmap is sized to c2c.nodes_cnt (from env->nr_numa_nodes),
-so a node ID exceeding that causes OOB writes.
-
-process_sample_event() indexes c2c.cpu2node[cpu] and
-c2c_he->node_stats[node] without bounds checking.  Both arrays are
-sized to c2c.cpus_cnt and c2c.nodes_cnt respectively.
-
-Add bounds checks in all three paths:
-  - c2c_he__set_cpu(): return if sample->cpu >= c2c.cpus_cnt
-  - c2c_he__set_node(): return if node >= c2c.nodes_cnt
-  - process_sample_event(): clamp cpu to 0 if >= cpus_cnt,
-    guard node_stats access with bounds check
-
-Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-c2c.c | 19 +++++++++++++++++--
- 1 file changed, 17 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
-index 15e1fce71c7225..8dd371cb94ca5f 100644
---- a/tools/perf/builtin-c2c.c
-+++ b/tools/perf/builtin-c2c.c
-@@ -230,6 +230,10 @@ static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
-                     "WARNING: no sample cpu value"))
-               return;
-+      /* cpuset bitmap has c2c.cpus_cnt bits from env->nr_cpus_avail */
-+      if (sample->cpu >= (unsigned int)c2c.cpus_cnt)
-+              return;
-+
-       __set_bit(sample->cpu, c2c_he->cpuset);
- }
-@@ -247,6 +251,10 @@ static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
-       if (WARN_ONCE(node < 0, "WARNING: failed to find node\n"))
-               return;
-+      /* nodeset bitmap has c2c.nodes_cnt bits from env->nr_numa_nodes */
-+      if (node >= c2c.nodes_cnt)
-+              return;
-+
-       __set_bit(node, c2c_he->nodeset);
-       if (c2c_he->paddr != sample->phys_addr) {
-@@ -346,7 +354,12 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
-                * Doing node stats only for single callchain data.
-                */
-               int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu;
--              int node = c2c.cpu2node[cpu];
-+              int node;
-+
-+              /* cpu2node[] has c2c.cpus_cnt entries; large u32 wraps signed negative */
-+              if (cpu < 0 || cpu >= c2c.cpus_cnt)
-+                      cpu = 0;
-+              node = c2c.cpu2node[cpu];
-               mi = mi_dup;
-@@ -363,7 +376,9 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
-               c2c_he = container_of(he, struct c2c_hist_entry, he);
-               c2c_add_stats(&c2c_he->stats, &stats);
-               c2c_add_stats(&c2c_hists->stats, &stats);
--              c2c_add_stats(&c2c_he->node_stats[node], &stats);
-+              /* node_stats[] has c2c.nodes_cnt entries */
-+              if (node >= 0 && node < c2c.nodes_cnt)
-+                      c2c_add_stats(&c2c_he->node_stats[node], &stats);
-               compute_stats(c2c_he, &stats, sample->weight);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-c2c-bounds-check-cpu-ids-in-setup_nodes-topolog.patch b/queue-6.12/perf-c2c-bounds-check-cpu-ids-in-setup_nodes-topolog.patch
deleted file mode 100644 (file)
index e39161c..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From 516cd92913df6b15f4920ae05f05b51f761786a0 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 11:06:30 -0300
-Subject: perf c2c: Bounds-check CPU IDs in setup_nodes() topology loop
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 5fb2e6ad8c5d6b3b380f94c7456595511f3731be ]
-
-setup_nodes() iterates CPU maps from the perf.data topology header and
-uses cpu.cpu directly as an array index into cpu2node[] (allocated with
-c2c.cpus_cnt = env->nr_cpus_avail entries) and __set_bit(cpu.cpu, set)
-(bitmap also sized to c2c.cpus_cnt).
-
-A crafted perf.data with topology CPU IDs exceeding nr_cpus_avail causes
-out-of-bounds heap writes into both the cpu2node array and the per-node
-bitmap.
-
-Add a bounds check to skip CPU IDs that fall outside the valid range.
-
-Fixes: 1e181b92a2da ("perf c2c report: Add 'node' sort key")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-c2c.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
-index 8dd371cb94ca5f..9b1482786d81cd 100644
---- a/tools/perf/builtin-c2c.c
-+++ b/tools/perf/builtin-c2c.c
-@@ -2318,6 +2318,10 @@ static int setup_nodes(struct perf_session *session)
-               nodes[node] = set;
-               perf_cpu_map__for_each_cpu_skip_any(cpu, idx, map) {
-+                      /* topology CPU IDs from perf.data may exceed nr_cpus_avail */
-+                      if (cpu.cpu < 0 || cpu.cpu >= c2c.cpus_cnt)
-+                              continue;
-+
-                       __set_bit(cpu.cpu, set);
-                       if (WARN_ONCE(cpu2node[cpu.cpu] != -1, "node/cpu topology bug"))
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch b/queue-6.12/perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch
deleted file mode 100644 (file)
index c9abf0d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-From 108a7a9016771f2dd391beece48df21d5761d3ec Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 11:19:10 -0300
-Subject: perf c2c: Fix use-after-free in he__get_c2c_hists() error path
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 5e5e6196d737c5be03d20647428316b36621608d ]
-
-he__get_c2c_hists() assigns c2c_he->hists before calling
-c2c_hists__init().  If init fails, the error path calls free(hists)
-but leaves c2c_he->hists pointing to freed memory.  On teardown,
-c2c_he_free() finds the non-NULL pointer and calls
-hists__delete_entries() on it, causing a use-after-free.
-
-Set c2c_he->hists to NULL before freeing so teardown skips the
-already-freed allocation.
-
-Fixes: b2252ae67b687d2b ("perf c2c report: Decode c2c_stats for hist entries")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-c2c.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
-index 9b1482786d81cd..b02b41059730f9 100644
---- a/tools/perf/builtin-c2c.c
-+++ b/tools/perf/builtin-c2c.c
-@@ -216,6 +216,7 @@ he__get_c2c_hists(struct hist_entry *he,
-       ret = c2c_hists__init(hists, sort, nr_header_lines);
-       if (ret) {
-+              c2c_he->hists = NULL;
-               free(hists);
-               return NULL;
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-callchain-handle-multiple-address-spaces.patch b/queue-6.12/perf-callchain-handle-multiple-address-spaces.patch
deleted file mode 100644 (file)
index 290c854..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-From ae15db3e9b639491007cc1e9e99638e4b6091781 Mon Sep 17 00:00:00 2001
-From: Thomas Richter <tmricht@linux.ibm.com>
-Date: Tue, 14 Apr 2026 14:42:41 +0200
-Subject: perf callchain: Handle multiple address spaces
-
-From: Thomas Richter <tmricht@linux.ibm.com>
-
-commit ae15db3e9b639491007cc1e9e99638e4b6091781 upstream.
-
-perf test 'perf inject to convert DWARF callchains to regular ones'
-fails on s390. It was introduced with commit 92ea788d2af4e65a ("perf
-inject: Add --convert-callchain option")
-
-The failure comes the difference in output. Without the inject script to
-convert DWARF the callchains is:
-
- # perf record -F 999 --call-graph dwarf -- perf test -w noploop
- # perf report -i perf.data --stdio --no-children -q \
-                                        --percent-limit=1 > /tmp/111
- # cat /tmp/111
-    99.30%  perf-noploop  perf               [.] noploop
-            |
-            ---noploop
-               run_workload (inlined)
-               cmd_test
-               run_builtin (inlined)
-               handle_internal_command
-               run_argv (inlined)
-               main
-               __libc_start_call_main
-               __libc_start_main_impl (inlined)
-               _start
- #
-
-With the inject script step the output is:
-
- # perf inject -i perf.data --convert-callchain -o /tmp/perf-inject-1.out
- # perf report -i /tmp/perf-inject-1.out --stdio --no-children -q \
-               --percent-limit=1 > /tmp/222
- # cat /tmp/222
-    99.40%  perf-noploop  perf               [.] noploop
-            |
-            ---noploop
-               run_workload (inlined)
-               cmd_test
-               run_builtin (inlined)
-               handle_internal_command
-               run_argv (inlined)
-               main
-               _start
- # diff /tmp/111 /tmp/222
- 1c1
- <     99.30%  perf-noploop  perf               [.] noploop
- ---
- >     99.40%  perf-noploop  perf               [.] noploop
- 10,11d9
- <                __libc_start_call_main
- <                __libc_start_main_impl (inlined)
- #
-
-The difference are the symbols __libc_start_call_main and
-__libc_start_main_impl.
-
-On x86_64, kernel and user space share a single virtual address space,
-with the kernel mapped to the upper end of memory. The instruction
-pointer value alone is sufficient to distinguish between user space and
-kernel space addresses.
-
-This is not true for s390, which uses separate address spaces for user
-and kernel.
-
-The same virtual address can be valid in both address spaces, so the
-instruction pointer value alone cannot determine whether an address
-belongs to the kernel or user space.
-
-Instead, perf must rely on the cpumode metadata derived from the
-processor status word (PSW) at sample time.
-
-In function perf_event__convert_sample_callchain() the first part
-copies a kernel callchain and context entries, if any.
-
-It then appends additional entries ignoring the address space
-architecture. Taking that into account, the symbols at addresses
-
-   0x3ff970348cb __libc_start_call_main
-   0x3ff970349c5 __libc_start_main_impl
-
-(located after the kernel address space on s390) are now included.
-
-Output before:
-
- # perf test 83
- 83: perf inject to convert DWARF callchains to regular ones : FAILED!
-
-Output after:
- # perf test 83
- 83: perf inject to convert DWARF callchains to regular ones : Ok
-
-Question to Namhyung:
-
-In function perf_event__convert_sample_callchain() just before the
-for() loop this patch modifies, the kernel callchain is copied,
-see this comment and the next 5 lines:
-
-   /* copy kernel callchain and context entries */
-
-Then why is machine__kernel_ip() needed in the for() loop, when
-the kernel entries have been copied just before the loop?
-
-Note: This patch was tested on x86_64 virtual machine and succeeded.
-
-Fixes: 92ea788d2af4e65a ("perf inject: Add --convert-callchain option")
-Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
-Acked-by: Namhyung Kim <namhyung@kernel.org>
-Cc: Alexander Gordeev <agordeev@linux.ibm.com>
-Cc: Heiko Carstens <hca@linux.ibm.com>
-Cc: Jan Polensky <japo@linux.ibm.com>
-Cc: linux-s390@vger.kernel.org
-Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
-Cc: Vasily Gorbik <gor@linux.ibm.com>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/arch/common.c    |    4 +++-
- tools/perf/builtin-inject.c |    3 ++-
- 2 files changed, 5 insertions(+), 2 deletions(-)
-
---- a/tools/perf/arch/common.c
-+++ b/tools/perf/arch/common.c
-@@ -237,5 +237,7 @@ int perf_env__lookup_objdump(struct perf
-  */
- bool perf_env__single_address_space(struct perf_env *env)
- {
--      return strcmp(perf_env__arch(env), "sparc");
-+      const char *arch = perf_env__arch(env);
-+
-+      return strcmp(arch, "s390") && strcmp(arch, "sparc");
- }
---- a/tools/perf/builtin-inject.c
-+++ b/tools/perf/builtin-inject.c
-@@ -452,7 +452,8 @@ static int perf_event__convert_sample_ca
-       node = cursor->first;
-       for (k = 0; k < cursor->nr && i < PERF_MAX_STACK_DEPTH; k++) {
--              if (machine__kernel_ip(machine, node->ip))
-+              if (machine->single_address_space &&
-+                  machine__kernel_ip(machine, node->ip))
-                       /* kernel IPs were added already */;
-               else if (node->ms.sym && node->ms.sym->inlined)
-                       /* we can't handle inlined callchains */;
diff --git a/queue-6.12/perf-cs-etm-bounds-check-cpu-in-cs_etm__get_queue.patch b/queue-6.12/perf-cs-etm-bounds-check-cpu-in-cs_etm__get_queue.patch
deleted file mode 100644 (file)
index 352add5..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-From c2b8092feb71592b928681be3b68c7626c07a38e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 13 Jun 2026 14:55:32 -0300
-Subject: perf cs-etm: Bounds-check CPU in cs_etm__get_queue()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 9a989e60cc6e29d98aed2087425cba53bf4b392d ]
-
-cs_etm__get_queue() indexes etm->queues.queue_array[cpu] without
-validating that cpu is within nr_queues.  When processing
-AUX_OUTPUT_HW_ID events, the cpu value comes from untrusted perf.data
-trace payload and flows through cs_etm__process_trace_id_v0_1() and
-cs_etm__queue_aux_fragment() without bounds checking, allowing an
-out-of-bounds read with a crafted file.
-
-Add a bounds check in cs_etm__get_queue() and NULL checks in all
-callers.
-
-Also add NULL checks for queue_array[i].priv in the queue iteration
-loops in cs_etm__map_trace_id_v0() and cs_etm__process_trace_id_v0_1()
-— after auxtrace_queues__grow() new entries are zero-initialized so
-.priv can be NULL.  Add a get_cpu_data() NULL check in
-cs_etm__process_trace_id_v0_1(), matching the existing check in
-cs_etm__process_trace_id_v0().
-
-Fixes: 77c123f53e97ad4b ("perf: cs-etm: Move traceid_list to each queue")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: James Clark <james.clark@arm.com>
-Cc: Leo Yan <leo.yan@linaro.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cs-etm.c |   25 +++++++++++++++++++++++--
- 1 file changed, 23 insertions(+), 2 deletions(-)
-
---- a/tools/perf/util/cs-etm.c
-+++ b/tools/perf/util/cs-etm.c
-@@ -292,8 +292,11 @@ static struct cs_etm_queue *cs_etm__get_
- {
-       if (etm->per_thread_decoding)
-               return etm->queues.queue_array[0].priv;
--      else
--              return etm->queues.queue_array[cpu].priv;
-+
-+      if (cpu < 0 || cpu >= (int)etm->queues.nr_queues)
-+              return NULL;
-+
-+      return etm->queues.queue_array[cpu].priv;
- }
- static int cs_etm__map_trace_id_v0(struct cs_etm_auxtrace *etm, u8 trace_chan_id,
-@@ -306,6 +309,9 @@ static int cs_etm__map_trace_id_v0(struc
-        * queue associated with that CPU so only one decoder is made.
-        */
-       etmq = cs_etm__get_queue(etm, cpu_metadata[CS_ETM_CPU]);
-+      if (!etmq)
-+              return -EINVAL;
-+
-       if (etmq->format == UNFORMATTED)
-               return cs_etm__insert_trace_id_node(etmq, trace_chan_id,
-                                                   cpu_metadata);
-@@ -318,6 +324,9 @@ static int cs_etm__map_trace_id_v0(struc
-               int ret;
-               etmq = etm->queues.queue_array[i].priv;
-+              if (!etmq)
-+                      continue;
-+
-               ret = cs_etm__insert_trace_id_node(etmq, trace_chan_id,
-                                                  cpu_metadata);
-               if (ret)
-@@ -358,6 +367,9 @@ static int cs_etm__process_trace_id_v0_1
-       u32 sink_id = FIELD_GET(CS_AUX_HW_ID_SINK_ID_MASK, hw_id);
-       u8 trace_id = FIELD_GET(CS_AUX_HW_ID_TRACE_ID_MASK, hw_id);
-+      if (!etmq)
-+              return -EINVAL;
-+
-       /*
-        * Check sink id hasn't changed in per-cpu mode. In per-thread mode,
-        * let it pass for now until an actual overlapping trace ID is hit. In
-@@ -375,6 +387,9 @@ static int cs_etm__process_trace_id_v0_1
-       for (unsigned int i = 0; i < etm->queues.nr_queues; ++i) {
-               struct cs_etm_queue *other_etmq = etm->queues.queue_array[i].priv;
-+              if (!other_etmq)
-+                      continue;
-+
-               /* Different sinks, skip */
-               if (other_etmq->sink_id != etmq->sink_id)
-                       continue;
-@@ -396,6 +411,9 @@ static int cs_etm__process_trace_id_v0_1
-       }
-       cpu_data = get_cpu_data(etm, cpu);
-+      if (!cpu_data)
-+              return -EINVAL;
-+
-       ret = cs_etm__insert_trace_id_node(etmq, trace_id, cpu_data);
-       if (ret)
-               return ret;
-@@ -3128,6 +3146,9 @@ static int cs_etm__queue_aux_fragment(st
-           aux_offset + aux_size <= auxtrace_event->offset + auxtrace_event->size) {
-               struct cs_etm_queue *etmq = etm->queues.queue_array[auxtrace_event->idx].priv;
-+              if (!etmq)
-+                      return -EINVAL;
-+
-               /*
-                * If this AUX event was inside this buffer somewhere, create a new auxtrace event
-                * based on the sizes of the aux event, and queue that fragment.
diff --git a/queue-6.12/perf-cs-etm-queue-context-packets-for-frontend.patch b/queue-6.12/perf-cs-etm-queue-context-packets-for-frontend.patch
deleted file mode 100644 (file)
index cbdf200..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-From 05f90ec3fd0040a17a2967ff06eb10a9cc543b8f Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 9 Jun 2026 15:40:06 +0100
-Subject: perf cs-etm: Queue context packets for frontend
-
-From: James Clark <james.clark@linaro.org>
-
-[ Upstream commit 68ca50bc0fa64841cd73b8a1538df1d7f7eb4108 ]
-
-PE_CONTEXT elements update the context ID and exception level, but the
-decoder may still have prior packets cached for frontend processing.
-Updating the context immediately in the decoder backend can make those
-cached packets get consumed with the wrong thread or EL state.
-
-Add a CS_ETM_CONTEXT packet carrying the TID and EL to the frontend,
-this keeps context changes ordered with the rest of the packet stream
-and avoids mismatches when synthesizing samples from cached packets.
-
-Separate the memory access function into one for the frontend and one
-for decoding. The frontend also needs memory access to attach the
-instruction to samples. Because the frontend does memory access for
-both previous and current packets, change all the frontend memory access
-function signatures to take both a tidq and packet. But backend always
-uses the current backend EL and thread from the tidq.
-
-Treat context packets as a boundary for branch sample generation and
-remove tidq->prev_packet_thread because it's not possible to branch to a
-different thread, so only tracking the current thread is required for
-sample generation.
-
-Fixes: e573e978fb12e160 ("perf cs-etm: Inject capabilitity for CoreSight traces")
-Reported-by: Amir Ayupov <aaupov@meta.com>
-Closes: https://lore.kernel.org/linux-perf-users/20260515021135.1729028-1-aaupov@meta.com/
-Co-authored-by: James Clark <james.clark@linaro.org>
-Signed-off-by: Leo Yan <leo.yan@arm.com>
-Cc: Ian Rogers <irogers@google.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Jonathan Corbet <corbet@lwn.net>
-Cc: linux-doc@vger.kernel.org
-Cc: Mike Leach <mike.leach@arm.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Paschalis Mpeis <Paschalis.Mpeis@arm.com>
-Cc: Robert Walker <robert.walker@arm.com>
-Cc: Shuah Khan <skhan@linuxfoundation.org>
-Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
-Signed-off-by: James Clark <james.clark@linaro.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cs-etm-decoder/cs-etm-decoder.c |   21 +-
- tools/perf/util/cs-etm.c                        |  236 ++++++++++++++----------
- tools/perf/util/cs-etm.h                        |    8 
- 3 files changed, 163 insertions(+), 102 deletions(-)
-
---- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
-+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
-@@ -399,6 +399,8 @@ cs_etm_decoder__buffer_packet(struct cs_
-       packet_queue->packet_buffer[et].flags = 0;
-       packet_queue->packet_buffer[et].exception_number = UINT32_MAX;
-       packet_queue->packet_buffer[et].trace_chan_id = trace_chan_id;
-+      packet_queue->packet_buffer[et].el = ocsd_EL_unknown;
-+      packet_queue->packet_buffer[et].tid = -1;
-       if (packet_queue->packet_count == CS_ETM_PACKET_MAX_BUFFER - 1)
-               return OCSD_RESP_WAIT;
-@@ -446,6 +448,7 @@ cs_etm_decoder__buffer_range(struct cs_e
-       packet->last_instr_type = elem->last_i_type;
-       packet->last_instr_subtype = elem->last_i_subtype;
-       packet->last_instr_cond = elem->last_instr_cond;
-+      packet->el = elem->context.exception_level;
-       if (elem->last_i_type == OCSD_INSTR_BR || elem->last_i_type == OCSD_INSTR_BR_INDIRECT)
-               packet->last_instr_taken_branch = elem->last_instr_exec;
-@@ -522,7 +525,9 @@ cs_etm_decoder__set_tid(struct cs_etm_qu
-                       const ocsd_generic_trace_elem *elem,
-                       const uint8_t trace_chan_id)
- {
-+      struct cs_etm_packet *packet;
-       pid_t tid = -1;
-+      int ret;
-       /*
-        * Process the PE_CONTEXT packets if we have a valid contextID or VMID.
-@@ -543,12 +548,18 @@ cs_etm_decoder__set_tid(struct cs_etm_qu
-               break;
-       }
--      if (cs_etm__etmq_set_tid_el(etmq, tid, trace_chan_id,
--                                  elem->context.exception_level))
-+      if (cs_etm__etmq_update_decode_context(etmq, trace_chan_id,
-+                              elem->context.exception_level, tid))
-               return OCSD_RESP_FATAL_SYS_ERR;
--      if (tid == -1)
--              return OCSD_RESP_CONT;
-+      ret = cs_etm_decoder__buffer_packet(etmq, packet_queue, trace_chan_id,
-+                                          CS_ETM_CONTEXT);
-+      if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT)
-+              return ret;
-+
-+      packet = &packet_queue->packet_buffer[packet_queue->tail];
-+      packet->tid = tid;
-+      packet->el = elem->context.exception_level;
-       /*
-        * A timestamp is generated after a PE_CONTEXT element so make sure
-@@ -556,7 +567,7 @@ cs_etm_decoder__set_tid(struct cs_etm_qu
-        */
-       cs_etm_decoder__reset_timestamp(packet_queue);
--      return OCSD_RESP_CONT;
-+      return ret;
- }
- static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
---- a/tools/perf/util/cs-etm.c
-+++ b/tools/perf/util/cs-etm.c
-@@ -86,15 +86,22 @@ struct cs_etm_traceid_queue {
-       u64 period_instructions;
-       size_t last_branch_pos;
-       union perf_event *event_buf;
--      struct thread *thread;
--      struct thread *prev_packet_thread;
--      ocsd_ex_level prev_packet_el;
--      ocsd_ex_level el;
-       struct branch_stack *last_branch;
-       struct branch_stack *last_branch_rb;
-       struct cs_etm_packet *prev_packet;
-       struct cs_etm_packet *packet;
-       struct cs_etm_packet_queue packet_queue;
-+
-+      struct thread *decode_thread;
-+      ocsd_ex_level decode_el;
-+
-+      /*
-+       * The frontend accesses the EL from '[prev_]packet' because it needs
-+       * previous EL for branch and current EL for instruction samples. It's
-+       * not possible to change thread in a single branch sample so no need to
-+       * store or access the thread through the packet.
-+       */
-+      struct thread *frontend_thread;
- };
- enum cs_etm_format {
-@@ -608,10 +615,11 @@ static int cs_etm__init_traceid_queue(st
-       queue = &etmq->etm->queues.queue_array[etmq->queue_nr];
-       tidq->trace_chan_id = trace_chan_id;
--      tidq->el = tidq->prev_packet_el = ocsd_EL_unknown;
--      tidq->thread = machine__findnew_thread(&etm->session->machines.host, -1,
-+      tidq->decode_el = ocsd_EL_unknown;
-+      tidq->frontend_thread = machine__findnew_thread(&etm->session->machines.host, -1,
-+                                             queue->tid);
-+      tidq->decode_thread = machine__findnew_thread(&etm->session->machines.host, -1,
-                                              queue->tid);
--      tidq->prev_packet_thread = machine__idle_thread(&etm->session->machines.host);
-       tidq->packet = zalloc(sizeof(struct cs_etm_packet));
-       if (!tidq->packet)
-@@ -744,21 +752,10 @@ static void cs_etm__packet_swap(struct c
-               /*
-                * Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
-                * the next incoming packet.
--               *
--               * Threads and exception levels are also tracked for both the
--               * previous and current packets. This is because the previous
--               * packet is used for the 'from' IP for branch samples, so the
--               * thread at that time must also be assigned to that sample.
--               * Across discontinuity packets the thread can change, so by
--               * tracking the thread for the previous packet the branch sample
--               * will have the correct info.
-                */
-               tmp = tidq->packet;
-               tidq->packet = tidq->prev_packet;
-               tidq->prev_packet = tmp;
--              tidq->prev_packet_el = tidq->el;
--              thread__put(tidq->prev_packet_thread);
--              tidq->prev_packet_thread = thread__get(tidq->thread);
-       }
- }
-@@ -931,8 +928,8 @@ static void cs_etm__free_traceid_queues(
-               /* Free this traceid_queue from the array */
-               tidq = etmq->traceid_queues[idx];
--              thread__zput(tidq->thread);
--              thread__zput(tidq->prev_packet_thread);
-+              thread__zput(tidq->frontend_thread);
-+              thread__zput(tidq->decode_thread);
-               zfree(&tidq->event_buf);
-               zfree(&tidq->last_branch);
-               zfree(&tidq->last_branch_rb);
-@@ -1077,47 +1074,43 @@ static u8 cs_etm__cpu_mode(struct cs_etm
-       }
- }
--static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
--                            u64 address, size_t size, u8 *buffer,
--                            const ocsd_mem_space_acc_t mem_space)
-+static u32 __cs_etm__mem_access(struct cs_etm_queue *etmq,
-+                              u64 address, size_t size, u8 *buffer,
-+                              const ocsd_mem_space_acc_t mem_space,
-+                              ocsd_ex_level el, struct thread *thread)
- {
-       u8  cpumode;
-       u64 offset;
-       int len;
-       struct addr_location al;
-       struct dso *dso;
--      struct cs_etm_traceid_queue *tidq;
-       int ret = 0;
-       if (!etmq)
-               return 0;
-       addr_location__init(&al);
--      tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
--      if (!tidq)
--              goto out;
-       /*
--       * We've already tracked EL along side the PID in cs_etm__set_thread()
--       * so double check that it matches what OpenCSD thinks as well. It
--       * doesn't distinguish between EL0 and EL1 for this mem access callback
--       * so we had to do the extra tracking. Skip validation if it's any of
--       * the 'any' values.
-+       * We track EL for the frontend and the backend when receiving context
-+       * and range packets. OpenCSD doesn't distinguish between EL0 and EL1
-+       * for this mem access callback so we had to do the extra tracking. Skip
-+       * validation if it's any of the 'any' values.
-        */
-       if (!(mem_space == OCSD_MEM_SPACE_ANY ||
-             mem_space == OCSD_MEM_SPACE_N || mem_space == OCSD_MEM_SPACE_S)) {
-               if (mem_space & OCSD_MEM_SPACE_EL1N) {
-                       /* Includes both non secure EL1 and EL0 */
--                      assert(tidq->el == ocsd_EL1 || tidq->el == ocsd_EL0);
-+                      assert(el == ocsd_EL1 || el == ocsd_EL0);
-               } else if (mem_space & OCSD_MEM_SPACE_EL2)
--                      assert(tidq->el == ocsd_EL2);
-+                      assert(el == ocsd_EL2);
-               else if (mem_space & OCSD_MEM_SPACE_EL3)
--                      assert(tidq->el == ocsd_EL3);
-+                      assert(el == ocsd_EL3);
-       }
--      cpumode = cs_etm__cpu_mode(etmq, address, tidq->el);
-+      cpumode = cs_etm__cpu_mode(etmq, address, el);
--      if (!thread__find_map(tidq->thread, cpumode, address, &al))
-+      if (!thread__find_map(thread, cpumode, address, &al))
-               goto out;
-       dso = map__dso(al.map);
-@@ -1132,7 +1125,7 @@ static u32 cs_etm__mem_access(struct cs_
-       map__load(al.map);
--      len = dso__data_read_offset(dso, maps__machine(thread__maps(tidq->thread)),
-+      len = dso__data_read_offset(dso, maps__machine(thread__maps(thread)),
-                                   offset, buffer, size);
-       if (len <= 0) {
-@@ -1152,6 +1145,30 @@ out:
-       return ret;
- }
-+static u32 cs_etm__frontend_mem_access(struct cs_etm_queue *etmq,
-+                                     struct cs_etm_traceid_queue *tidq,
-+                                     struct cs_etm_packet *packet,
-+                                     u64 address, size_t size, u8 *buffer)
-+{
-+      return __cs_etm__mem_access(etmq, address, size, buffer, 0, packet->el,
-+                                  tidq->frontend_thread);
-+}
-+
-+static u32 cs_etm__decoder_mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
-+                                    u64 address, size_t size, u8 *buffer,
-+                                    const ocsd_mem_space_acc_t mem_space)
-+{
-+      struct cs_etm_traceid_queue *tidq;
-+
-+      tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
-+      if (!tidq)
-+              return 0;
-+
-+      return __cs_etm__mem_access(etmq, address, size, buffer,
-+                                  mem_space, tidq->decode_el,
-+                                  tidq->decode_thread);
-+}
-+
- static struct cs_etm_queue *cs_etm__alloc_queue(void)
- {
-       struct cs_etm_queue *etmq = zalloc(sizeof(*etmq));
-@@ -1327,12 +1344,13 @@ void cs_etm__reset_last_branch_rb(struct
- }
- static inline int cs_etm__t32_instr_size(struct cs_etm_queue *etmq,
--                                       u8 trace_chan_id, u64 addr)
-+                                       struct cs_etm_traceid_queue *tidq,
-+                                       struct cs_etm_packet *packet, u64 addr)
- {
-       u8 instrBytes[2];
--      cs_etm__mem_access(etmq, trace_chan_id, addr, ARRAY_SIZE(instrBytes),
--                         instrBytes, 0);
-+      cs_etm__frontend_mem_access(etmq, tidq, packet, addr,
-+                                  ARRAY_SIZE(instrBytes), instrBytes);
-       /*
-        * T32 instruction size is indicated by bits[15:11] of the first
-        * 16-bit word of the instruction: 0b11101, 0b11110 and 0b11111
-@@ -1365,16 +1383,16 @@ u64 cs_etm__last_executed_instr(const st
- }
- static inline u64 cs_etm__instr_addr(struct cs_etm_queue *etmq,
--                                   u64 trace_chan_id,
--                                   const struct cs_etm_packet *packet,
-+                                   struct cs_etm_traceid_queue *tidq,
-+                                   struct cs_etm_packet *packet,
-                                    u64 offset)
- {
-       if (packet->isa == CS_ETM_ISA_T32) {
-               u64 addr = packet->start_addr;
-               while (offset) {
--                      addr += cs_etm__t32_instr_size(etmq,
--                                                     trace_chan_id, addr);
-+                      addr += cs_etm__t32_instr_size(etmq, tidq, packet,
-+                                                     addr);
-                       offset--;
-               }
-               return addr;
-@@ -1466,34 +1484,51 @@ cs_etm__get_trace(struct cs_etm_queue *e
-       return etmq->buf_len;
- }
--static void cs_etm__set_thread(struct cs_etm_queue *etmq,
--                             struct cs_etm_traceid_queue *tidq, pid_t tid,
--                             ocsd_ex_level el)
-+/*
-+ * Convert a raw thread number to a thread struct and assign it to **thread.
-+ */
-+static int cs_etm__etmq_update_thread(struct cs_etm_queue *etmq,
-+                                    ocsd_ex_level el, pid_t tid,
-+                                    struct thread **thread)
- {
-       struct machine *machine = cs_etm__get_machine(etmq, el);
-+      if (!machine || !*thread)
-+              return -EINVAL;
-+
-       if (tid != -1) {
--              thread__zput(tidq->thread);
--              tidq->thread = machine__find_thread(machine, -1, tid);
-+              thread__zput(*thread);
-+              *thread = machine__find_thread(machine, -1, tid);
-       }
-       /* Couldn't find a known thread */
--      if (!tidq->thread)
--              tidq->thread = machine__idle_thread(machine);
-+      if (!*thread)
-+              *thread = machine__idle_thread(machine);
--      tidq->el = el;
-+      return 0;
- }
--int cs_etm__etmq_set_tid_el(struct cs_etm_queue *etmq, pid_t tid,
--                          u8 trace_chan_id, ocsd_ex_level el)
-+/*
-+ * Set the thread and EL of the decode context which is ahead in time of the
-+ * frontend context.
-+ */
-+int cs_etm__etmq_update_decode_context(struct cs_etm_queue *etmq,
-+                                     u8 trace_chan_id,
-+                                     ocsd_ex_level el, pid_t tid)
- {
-       struct cs_etm_traceid_queue *tidq;
-+      int ret;
-       tidq = cs_etm__etmq_get_traceid_queue(etmq, trace_chan_id);
-       if (!tidq)
-               return -EINVAL;
--      cs_etm__set_thread(etmq, tidq, tid, el);
-+      ret = cs_etm__etmq_update_thread(etmq, el, tid,
-+                                       &tidq->decode_thread);
-+      if (ret)
-+              return ret;
-+
-+      tidq->decode_el = el;
-       return 0;
- }
-@@ -1503,8 +1538,8 @@ bool cs_etm__etmq_is_timeless(struct cs_
- }
- static void cs_etm__copy_insn(struct cs_etm_queue *etmq,
--                            u64 trace_chan_id,
--                            const struct cs_etm_packet *packet,
-+                            struct cs_etm_traceid_queue *tidq,
-+                            struct cs_etm_packet *packet,
-                             struct perf_sample *sample)
- {
-       /*
-@@ -1521,14 +1556,14 @@ static void cs_etm__copy_insn(struct cs_
-        * cs_etm__t32_instr_size().
-        */
-       if (packet->isa == CS_ETM_ISA_T32)
--              sample->insn_len = cs_etm__t32_instr_size(etmq, trace_chan_id,
-+              sample->insn_len = cs_etm__t32_instr_size(etmq, tidq, packet,
-                                                         sample->ip);
-       /* Otherwise, A64 and A32 instruction size are always 32-bit. */
-       else
-               sample->insn_len = 4;
--      cs_etm__mem_access(etmq, trace_chan_id, sample->ip, sample->insn_len,
--                         (void *)sample->insn, 0);
-+      cs_etm__frontend_mem_access(etmq, tidq, packet, sample->ip,
-+                                  sample->insn_len, (void *)sample->insn);
- }
- u64 cs_etm__convert_sample_time(struct cs_etm_queue *etmq, u64 cs_timestamp)
-@@ -1555,6 +1590,7 @@ static inline u64 cs_etm__resolve_sample
- static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
-                                           struct cs_etm_traceid_queue *tidq,
-+                                          struct cs_etm_packet *packet,
-                                           u64 addr, u64 period)
- {
-       int ret = 0;
-@@ -1563,23 +1599,23 @@ static int cs_etm__synth_instruction_sam
-       struct perf_sample sample = {.ip = 0,};
-       event->sample.header.type = PERF_RECORD_SAMPLE;
--      event->sample.header.misc = cs_etm__cpu_mode(etmq, addr, tidq->el);
-+      event->sample.header.misc = cs_etm__cpu_mode(etmq, addr, packet->el);
-       event->sample.header.size = sizeof(struct perf_event_header);
-       /* Set time field based on etm auxtrace config. */
-       sample.time = cs_etm__resolve_sample_time(etmq, tidq);
-       sample.ip = addr;
--      sample.pid = thread__pid(tidq->thread);
--      sample.tid = thread__tid(tidq->thread);
-+      sample.pid = thread__pid(tidq->frontend_thread);
-+      sample.tid = thread__tid(tidq->frontend_thread);
-       sample.id = etmq->etm->instructions_id;
-       sample.stream_id = etmq->etm->instructions_id;
-       sample.period = period;
--      sample.cpu = tidq->packet->cpu;
-+      sample.cpu = packet->cpu;
-       sample.flags = tidq->prev_packet->flags;
-       sample.cpumode = event->sample.header.misc;
--      cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->packet, &sample);
-+      cs_etm__copy_insn(etmq, tidq, packet, &sample);
-       if (etm->synth_opts.last_branch)
-               sample.branch_stack = tidq->last_branch;
-@@ -1623,15 +1659,15 @@ static int cs_etm__synth_branch_sample(s
-       event->sample.header.type = PERF_RECORD_SAMPLE;
-       event->sample.header.misc = cs_etm__cpu_mode(etmq, ip,
--                                                   tidq->prev_packet_el);
-+                                                   tidq->prev_packet->el);
-       event->sample.header.size = sizeof(struct perf_event_header);
-       /* Set time field based on etm auxtrace config. */
-       sample.time = cs_etm__resolve_sample_time(etmq, tidq);
-       sample.ip = ip;
--      sample.pid = thread__pid(tidq->prev_packet_thread);
--      sample.tid = thread__tid(tidq->prev_packet_thread);
-+      sample.pid = thread__pid(tidq->frontend_thread);
-+      sample.tid = thread__tid(tidq->frontend_thread);
-       sample.addr = cs_etm__first_executed_instr(tidq->packet);
-       sample.id = etmq->etm->branches_id;
-       sample.stream_id = etmq->etm->branches_id;
-@@ -1640,8 +1676,7 @@ static int cs_etm__synth_branch_sample(s
-       sample.flags = tidq->prev_packet->flags;
-       sample.cpumode = event->sample.header.misc;
--      cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->prev_packet,
--                        &sample);
-+      cs_etm__copy_insn(etmq, tidq, tidq->prev_packet, &sample);
-       /*
-        * perf report cannot handle events without a branch stack
-@@ -1765,7 +1800,6 @@ static int cs_etm__sample(struct cs_etm_
- {
-       struct cs_etm_auxtrace *etm = etmq->etm;
-       int ret;
--      u8 trace_chan_id = tidq->trace_chan_id;
-       u64 instrs_prev;
-       /* Get instructions remainder from previous packet */
-@@ -1851,10 +1885,10 @@ static int cs_etm__sample(struct cs_etm_
-                        * been executed, but PC has not advanced to next
-                        * instruction)
-                        */
--                      addr = cs_etm__instr_addr(etmq, trace_chan_id,
--                                                tidq->packet, offset - 1);
-+                      addr = cs_etm__instr_addr(etmq, tidq, tidq->packet,
-+                                                offset - 1);
-                       ret = cs_etm__synth_instruction_sample(
--                              etmq, tidq, addr,
-+                              etmq, tidq, tidq->packet, addr,
-                               etm->instructions_sample_period);
-                       if (ret)
-                               return ret;
-@@ -1936,7 +1970,7 @@ static int cs_etm__flush(struct cs_etm_q
-               addr = cs_etm__last_executed_instr(tidq->prev_packet);
-               err = cs_etm__synth_instruction_sample(
--                      etmq, tidq, addr,
-+                      etmq, tidq, tidq->prev_packet, addr,
-                       tidq->period_instructions);
-               if (err)
-                       return err;
-@@ -1991,7 +2025,7 @@ static int cs_etm__end_block(struct cs_e
-               addr = cs_etm__last_executed_instr(tidq->prev_packet);
-               err = cs_etm__synth_instruction_sample(
--                      etmq, tidq, addr,
-+                      etmq, tidq, tidq->prev_packet, addr,
-                       tidq->period_instructions);
-               if (err)
-                       return err;
-@@ -2028,9 +2062,9 @@ static int cs_etm__get_data_block(struct
-       return etmq->buf_len;
- }
--static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id,
--                               struct cs_etm_packet *packet,
--                               u64 end_addr)
-+static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq,
-+                               struct cs_etm_traceid_queue *tidq,
-+                               struct cs_etm_packet *packet, u64 end_addr)
- {
-       /* Initialise to keep compiler happy */
-       u16 instr16 = 0;
-@@ -2052,8 +2086,8 @@ static bool cs_etm__is_svc_instr(struct
-                * so below only read 2 bytes as instruction size for T32.
-                */
-               addr = end_addr - 2;
--              cs_etm__mem_access(etmq, trace_chan_id, addr, sizeof(instr16),
--                                 (u8 *)&instr16, 0);
-+              cs_etm__frontend_mem_access(etmq, tidq, packet, addr,
-+                                          sizeof(instr16), (u8 *)&instr16);
-               if ((instr16 & 0xFF00) == 0xDF00)
-                       return true;
-@@ -2068,8 +2102,8 @@ static bool cs_etm__is_svc_instr(struct
-                * +---------+---------+-------------------------+
-                */
-               addr = end_addr - 4;
--              cs_etm__mem_access(etmq, trace_chan_id, addr, sizeof(instr32),
--                                 (u8 *)&instr32, 0);
-+              cs_etm__frontend_mem_access(etmq, tidq, packet, addr,
-+                                          sizeof(instr32), (u8 *)&instr32);
-               if ((instr32 & 0x0F000000) == 0x0F000000 &&
-                   (instr32 & 0xF0000000) != 0xF0000000)
-                       return true;
-@@ -2085,8 +2119,8 @@ static bool cs_etm__is_svc_instr(struct
-                * +-----------------------+---------+-----------+
-                */
-               addr = end_addr - 4;
--              cs_etm__mem_access(etmq, trace_chan_id, addr, sizeof(instr32),
--                                 (u8 *)&instr32, 0);
-+              cs_etm__frontend_mem_access(etmq, tidq, packet, addr,
-+                                          sizeof(instr32), (u8 *)&instr32);
-               if ((instr32 & 0xFFE0001F) == 0xd4000001)
-                       return true;
-@@ -2102,7 +2136,6 @@ static bool cs_etm__is_svc_instr(struct
- static bool cs_etm__is_syscall(struct cs_etm_queue *etmq,
-                              struct cs_etm_traceid_queue *tidq, u64 magic)
- {
--      u8 trace_chan_id = tidq->trace_chan_id;
-       struct cs_etm_packet *packet = tidq->packet;
-       struct cs_etm_packet *prev_packet = tidq->prev_packet;
-@@ -2117,7 +2150,7 @@ static bool cs_etm__is_syscall(struct cs
-        */
-       if (magic == __perf_cs_etmv4_magic) {
-               if (packet->exception_number == CS_ETMV4_EXC_CALL &&
--                  cs_etm__is_svc_instr(etmq, trace_chan_id, prev_packet,
-+                  cs_etm__is_svc_instr(etmq, tidq, prev_packet,
-                                        prev_packet->end_addr))
-                       return true;
-       }
-@@ -2155,7 +2188,6 @@ static bool cs_etm__is_sync_exception(st
-                                     struct cs_etm_traceid_queue *tidq,
-                                     u64 magic)
- {
--      u8 trace_chan_id = tidq->trace_chan_id;
-       struct cs_etm_packet *packet = tidq->packet;
-       struct cs_etm_packet *prev_packet = tidq->prev_packet;
-@@ -2181,7 +2213,7 @@ static bool cs_etm__is_sync_exception(st
-                * (SMC, HVC) are taken as sync exceptions.
-                */
-               if (packet->exception_number == CS_ETMV4_EXC_CALL &&
--                  !cs_etm__is_svc_instr(etmq, trace_chan_id, prev_packet,
-+                  !cs_etm__is_svc_instr(etmq, tidq, prev_packet,
-                                         prev_packet->end_addr))
-                       return true;
-@@ -2205,7 +2237,6 @@ static int cs_etm__set_sample_flags(stru
- {
-       struct cs_etm_packet *packet = tidq->packet;
-       struct cs_etm_packet *prev_packet = tidq->prev_packet;
--      u8 trace_chan_id = tidq->trace_chan_id;
-       u64 magic;
-       int ret;
-@@ -2286,11 +2317,11 @@ static int cs_etm__set_sample_flags(stru
-               if (prev_packet->flags == (PERF_IP_FLAG_BRANCH |
-                                          PERF_IP_FLAG_RETURN |
-                                          PERF_IP_FLAG_INTERRUPT) &&
--                  cs_etm__is_svc_instr(etmq, trace_chan_id,
--                                       packet, packet->start_addr))
-+                  cs_etm__is_svc_instr(etmq, tidq, packet, packet->start_addr)) {
-                       prev_packet->flags = PERF_IP_FLAG_BRANCH |
-                                            PERF_IP_FLAG_RETURN |
-                                            PERF_IP_FLAG_SYSCALLRET;
-+              }
-               break;
-       case CS_ETM_DISCONTINUITY:
-               /*
-@@ -2371,6 +2402,7 @@ static int cs_etm__set_sample_flags(stru
-                                            PERF_IP_FLAG_RETURN |
-                                            PERF_IP_FLAG_INTERRUPT;
-               break;
-+      case CS_ETM_CONTEXT:
-       case CS_ETM_EMPTY:
-       default:
-               break;
-@@ -2446,6 +2478,19 @@ static int cs_etm__process_traceid_queue
-                        */
-                       cs_etm__sample(etmq, tidq);
-                       break;
-+              case CS_ETM_CONTEXT:
-+                      /*
-+                       * Update context but don't swap packet. Keep the
-+                       * previous one for branch source address info, if
-+                       * tracing the kernel the context packet will be emitted
-+                       * between two ranges.
-+                       */
-+                      ret = cs_etm__etmq_update_thread(etmq, tidq->packet->el,
-+                                                       tidq->packet->tid,
-+                                                       &tidq->frontend_thread);
-+                      if (ret)
-+                              goto out;
-+                      break;
-               case CS_ETM_EXCEPTION:
-               case CS_ETM_EXCEPTION_RET:
-                       /*
-@@ -2474,6 +2519,7 @@ static int cs_etm__process_traceid_queue
-               }
-       }
-+out:
-       return ret;
- }
-@@ -2597,7 +2643,7 @@ static int cs_etm__process_timeless_queu
-                       if (!tidq)
-                               continue;
--                      if (tid == -1 || thread__tid(tidq->thread) == tid)
-+                      if (tid == -1 || thread__tid(tidq->frontend_thread) == tid)
-                               cs_etm__run_per_thread_timeless_decoder(etmq);
-               } else
-                       cs_etm__run_per_cpu_timeless_decoder(etmq);
-@@ -3308,7 +3354,7 @@ static int cs_etm__create_queue_decoders
-        */
-       if (cs_etm_decoder__add_mem_access_cb(etmq->decoder,
-                                             0x0L, ((u64) -1L),
--                                            cs_etm__mem_access))
-+                                            cs_etm__decoder_mem_access))
-               goto out_free_decoder;
-       zfree(&t_params);
---- a/tools/perf/util/cs-etm.h
-+++ b/tools/perf/util/cs-etm.h
-@@ -158,6 +158,7 @@ enum cs_etm_sample_type {
-       CS_ETM_DISCONTINUITY,
-       CS_ETM_EXCEPTION,
-       CS_ETM_EXCEPTION_RET,
-+      CS_ETM_CONTEXT,
- };
- enum cs_etm_isa {
-@@ -184,6 +185,8 @@ struct cs_etm_packet {
-       u8 last_instr_size;
-       u8 trace_chan_id;
-       int cpu;
-+      int el;
-+      pid_t tid;
- };
- #define CS_ETM_PACKET_MAX_BUFFER 1024
-@@ -244,8 +247,9 @@ enum cs_etm_pid_fmt {
- #include <opencsd/ocsd_if_types.h>
- int cs_etm__get_cpu(struct cs_etm_queue *etmq, u8 trace_chan_id, int *cpu);
- enum cs_etm_pid_fmt cs_etm__get_pid_fmt(struct cs_etm_queue *etmq);
--int cs_etm__etmq_set_tid_el(struct cs_etm_queue *etmq, pid_t tid,
--                          u8 trace_chan_id, ocsd_ex_level el);
-+int cs_etm__etmq_update_decode_context(struct cs_etm_queue *etmq,
-+                                     u8 trace_chan_id, ocsd_ex_level el,
-+                                     pid_t tid);
- bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq);
- void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
-                                             u8 trace_chan_id);
diff --git a/queue-6.12/perf-cs-etm-reject-cpu-ids-that-would-overflow-signe.patch b/queue-6.12/perf-cs-etm-reject-cpu-ids-that-would-overflow-signe.patch
deleted file mode 100644 (file)
index 95db5fa..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From 33793177d52cc3face8cd19a594573df93c3b4c1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 22:45:08 -0300
-Subject: perf cs-etm: Reject CPU IDs that would overflow signed comparison
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 542e88a4c6f7b6edd1326ce767d4cb3c2ea9d61d ]
-
-metadata[j][CS_ETM_CPU] is a u64 from perf.data, but the comparison
-with max_cpu casts it to (int).  A crafted value like 0xFFFFFFFF becomes
--1 after the cast, which compares less than max_cpu (0), so the queue
-array is never sized to accommodate it.  When the value is later passed
-to cs_etm__get_queue(), it indexes queue_array with the original large
-value, causing an out-of-bounds access.
-
-Validate that CS_ETM_CPU fits in an int before using it in the signed
-comparison.
-
-Fixes: 57880a7966be510c ("perf: cs-etm: Allocate queues for all CPUs")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: James Clark <james.clark@arm.com>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cs-etm.c |    9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
---- a/tools/perf/util/cs-etm.c
-+++ b/tools/perf/util/cs-etm.c
-@@ -6,6 +6,7 @@
-  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
-  */
-+#include <limits.h>
- #include <linux/bitfield.h>
- #include <linux/bitops.h>
- #include <linux/coresight-pmu.h>
-@@ -3447,7 +3448,13 @@ int cs_etm__process_auxtrace_info_full(u
-                       goto err_free_metadata;
-               }
--              if ((int) metadata[j][CS_ETM_CPU] > max_cpu)
-+              /* CPU id comes from perf.data and must fit max_cpu + 1 without overflow */
-+              if (metadata[j][CS_ETM_CPU] >= INT_MAX) {
-+                      err = -EINVAL;
-+                      goto err_free_metadata;
-+              }
-+
-+              if ((int)metadata[j][CS_ETM_CPU] > max_cpu)
-                       max_cpu = metadata[j][CS_ETM_CPU];
-       }
diff --git a/queue-6.12/perf-cs-etm-require-full-global-header-in-auxtrace_i.patch b/queue-6.12/perf-cs-etm-require-full-global-header-in-auxtrace_i.patch
deleted file mode 100644 (file)
index 75d5514..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-From a2fbadc4fa90d99ec3c46a07dcf6f52e4f08b2ef Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 13 Jun 2026 14:40:36 -0300
-Subject: perf cs-etm: Require full global header in auxtrace_info size check
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 78d8ba680126f3545e8d0fba667e12d79fd4353b ]
-
-cs_etm__process_auxtrace_info() checks that header.size covers
-event_header_size + INFO_HEADER_SIZE (16 bytes total), but then
-accesses ptr[CS_PMU_TYPE_CPUS] at offset 24 from the start of the
-event.  A crafted 16-byte auxtrace_info event passes the size check
-but reads out-of-bounds.
-
-Include CS_ETM_HEADER_SIZE in the minimum size check so that the
-global header entries (version, pmu_type_cpus, snapshot) are
-guaranteed to fit within the event.
-
-Fixes: 55c1de9973d66516 ("perf cs-etm: Print auxtrace info even if OpenCSD isn't linked")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: James Clark <james.clark@arm.com>
-Cc: Leo Yan <leo.yan@linaro.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cs-etm-base.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/cs-etm-base.c b/tools/perf/util/cs-etm-base.c
-index 4abe416e3febd2..aebef71d3a0a1d 100644
---- a/tools/perf/util/cs-etm-base.c
-+++ b/tools/perf/util/cs-etm-base.c
-@@ -170,7 +170,9 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
-       u64 *ptr = NULL;
-       u64 hdr_version;
--      if (auxtrace_info->header.size < (event_header_size + INFO_HEADER_SIZE))
-+      /* Ensure priv[] is large enough for the global header entries */
-+      if (auxtrace_info->header.size < (event_header_size + INFO_HEADER_SIZE +
-+                                        CS_ETM_HEADER_SIZE))
-               return -EINVAL;
-       /* First the global part */
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch b/queue-6.12/perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch
deleted file mode 100644 (file)
index 93c7f56..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 3d3a6d2ca005f15e76c8e9761af300db4358bd27 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 13 Jun 2026 14:16:45 -0300
-Subject: perf cs-etm: Validate num_cpu before metadata allocation
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 312d91329b8fc6989a916a3f9a12d0674167b7e4 ]
-
-cs_etm__process_auxtrace_info_full() reads num_cpu from untrusted
-perf.data and uses it to allocate the metadata pointer array:
-
-  metadata = zalloc(sizeof(*metadata) * num_cpu);
-
-On 32-bit, sizeof(*metadata) is 4, so num_cpu = 0x40000000 overflows
-the multiplication to 0, causing zalloc(0) to return a valid zero-sized
-allocation followed by out-of-bounds writes in the population loop.
-
-Fix by computing priv_size early and using it to bound num_cpu: each
-CPU needs at least one u64 metadata entry, so num_cpu cannot exceed
-the total number of u64 entries in the event's private data area.
-
-Fixes: cd8bfd8c973eaff8 ("perf tools: Add processing of coresight metadata")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: James Clark <james.clark@arm.com>
-Cc: Leo Yan <leo.yan@linaro.org>
-Cc: Tor Jeremiassen <tor@ti.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cs-etm.c |   12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/tools/perf/util/cs-etm.c
-+++ b/tools/perf/util/cs-etm.c
-@@ -3410,6 +3410,18 @@ int cs_etm__process_auxtrace_info_full(u
-       /* First the global part */
-       ptr = (u64 *) auxtrace_info->priv;
-       num_cpu = ptr[CS_PMU_TYPE_CPUS] & 0xffffffff;
-+
-+      /*
-+       * Bound num_cpu by the event size: the global header consumes
-+       * CS_ETM_HEADER_SIZE bytes, and each CPU needs at least one u64
-+       * metadata entry after that.
-+       */
-+      priv_size = total_size - event_header_size - INFO_HEADER_SIZE -
-+                  CS_ETM_HEADER_SIZE;
-+      if (num_cpu <= 0 || priv_size <= 0 ||
-+          num_cpu > priv_size / (int)sizeof(u64))
-+              return -EINVAL;
-+
-       metadata = zalloc(sizeof(*metadata) * num_cpu);
-       if (!metadata)
-               return -ENOMEM;
diff --git a/queue-6.12/perf-debuginfo-fix-libdw-api-contract-violations.patch b/queue-6.12/perf-debuginfo-fix-libdw-api-contract-violations.patch
deleted file mode 100644 (file)
index a9fe9a1..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-From f327b3e36fc33294281f83af5ad7a99038dcf366 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 4 May 2026 01:12:27 -0700
-Subject: perf debuginfo: Fix libdw API contract violations
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit 31088ccf0312b1a547046f1f69890ede07834a30 ]
-
-Check return value of `dwfl_report_end` during offline initialization.
-Validate `dwfl_module_relocation_info` result before passing to `strcmp`
-to avoid potential segmentation faults.
-
-Additionally:
- - Fix a file descriptor leak in `debuginfo__init_offline_dwarf()` when
-   `dwfl_report_offline()` or subsequent setup calls fail.
-
-Fixes: 6f1b6291cf73cb32 ("perf tools: Add util/debuginfo.[ch] files")
-Assisted-by: Gemini-CLI:Google Gemini 3
-Signed-off-by: Ian Rogers <irogers@google.com>
-Acked-by: Namhyung Kim <namhyung@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Masami Hiramatsu <mhiramat@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Zecheng Li <zli94@ncsu.edu>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/debuginfo.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/util/debuginfo.c b/tools/perf/util/debuginfo.c
-index 19acf4775d3587..f5af3b4408b950 100644
---- a/tools/perf/util/debuginfo.c
-+++ b/tools/perf/util/debuginfo.c
-@@ -42,6 +42,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
- {
-       GElf_Addr dummy;
-       int fd;
-+      bool fd_consumed = false;
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
-@@ -55,6 +56,7 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
-       dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
-       if (!dbg->mod)
-               goto error;
-+      fd_consumed = true;
-       dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
-       if (!dbg->dbg)
-@@ -62,13 +64,14 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
-       dwfl_module_build_id(dbg->mod, &dbg->build_id, &dummy);
--      dwfl_report_end(dbg->dwfl, NULL, NULL);
-+      if (dwfl_report_end(dbg->dwfl, NULL, NULL) != 0)
-+              goto error;
-       return 0;
- error:
-       if (dbg->dwfl)
-               dwfl_end(dbg->dwfl);
--      else
-+      if (!fd_consumed)
-               close(fd);
-       memset(dbg, 0, sizeof(*dbg));
-@@ -160,7 +163,7 @@ int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
-       /* Search the relocation related .text section */
-       for (i = 0; i < n; i++) {
-               p = dwfl_module_relocation_info(dbg->mod, i, &shndx);
--              if (strcmp(p, ".text") == 0) {
-+              if (p && strcmp(p, ".text") == 0) {
-                       /* OK, get the section header */
-                       scn = elf_getscn(elf, shndx);
-                       if (!scn)
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-dso-add-support-for-reading-the-e_machine-type-.patch b/queue-6.12/perf-dso-add-support-for-reading-the-e_machine-type-.patch
deleted file mode 100644 (file)
index 779761e..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-From 38090a76f4e23063a774b9efcb9e3e3a36128721 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 18 Mar 2025 22:07:33 -0700
-Subject: perf dso: Add support for reading the e_machine type for a dso
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit afffec6f032926f70fc9f43f5d07cdfa09a0a184 ]
-
-For ELF file dsos read the e_machine from the ELF header. For kernel
-types assume the e_machine matches the perf tool. In other cases
-return EM_NONE.
-
-When reading from the ELF header use DSO__SWAP that may need
-dso->needs_swap initializing. Factor out dso__swap_init to allow this.
-
-Signed-off-by: Ian Rogers <irogers@google.com>
-Reviewed-by: Namhyung Kim <namhyung@kernel.org>
-Acked-by: Arnaldo Carvalho de Melo <acme@kernel.org>
-Link: https://lore.kernel.org/r/20250319050741.269828-7-irogers@google.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 2ea64782a428 ("perf tools: Use snprintf() in dso__read_running_kernel_build_id()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/dso.c        | 89 ++++++++++++++++++++++++++++++++++++
- tools/perf/util/dso.h        |  3 ++
- tools/perf/util/symbol-elf.c | 27 -----------
- 3 files changed, 92 insertions(+), 27 deletions(-)
-
-diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
-index 05a9dc6f41f820..7c12d53656887d 100644
---- a/tools/perf/util/dso.c
-+++ b/tools/perf/util/dso.c
-@@ -1191,6 +1191,68 @@ ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
-       return data_read_write_offset(dso, machine, offset, data, size, true);
- }
-+uint16_t dso__e_machine(struct dso *dso, struct machine *machine)
-+{
-+      uint16_t e_machine = EM_NONE;
-+      int fd;
-+
-+      switch (dso__binary_type(dso)) {
-+      case DSO_BINARY_TYPE__KALLSYMS:
-+      case DSO_BINARY_TYPE__GUEST_KALLSYMS:
-+      case DSO_BINARY_TYPE__VMLINUX:
-+      case DSO_BINARY_TYPE__GUEST_VMLINUX:
-+      case DSO_BINARY_TYPE__GUEST_KMODULE:
-+      case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
-+      case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
-+      case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
-+      case DSO_BINARY_TYPE__KCORE:
-+      case DSO_BINARY_TYPE__GUEST_KCORE:
-+      case DSO_BINARY_TYPE__BPF_PROG_INFO:
-+      case DSO_BINARY_TYPE__BPF_IMAGE:
-+      case DSO_BINARY_TYPE__OOL:
-+      case DSO_BINARY_TYPE__JAVA_JIT:
-+              return EM_HOST;
-+      case DSO_BINARY_TYPE__DEBUGLINK:
-+      case DSO_BINARY_TYPE__BUILD_ID_CACHE:
-+      case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
-+      case DSO_BINARY_TYPE__GNU_DEBUGDATA:
-+      case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
-+      case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
-+      case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
-+      case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
-+      case DSO_BINARY_TYPE__MIXEDUP_UBUNTU_DEBUGINFO:
-+      case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
-+              break;
-+      case DSO_BINARY_TYPE__NOT_FOUND:
-+      default:
-+              return EM_NONE;
-+      }
-+
-+      mutex_lock(dso__data_open_lock());
-+
-+      /*
-+       * dso__data(dso)->fd might be closed if other thread opened another
-+       * file (dso) due to open file limit (RLIMIT_NOFILE).
-+       */
-+      try_to_open_dso(dso, machine);
-+      fd = dso__data(dso)->fd;
-+      if (fd >= 0) {
-+              _Static_assert(offsetof(Elf32_Ehdr, e_machine) == 18, "Unexpected offset");
-+              _Static_assert(offsetof(Elf64_Ehdr, e_machine) == 18, "Unexpected offset");
-+              if (dso__needs_swap(dso) == DSO_SWAP__UNSET) {
-+                      unsigned char eidata;
-+
-+                      if (pread(fd, &eidata, sizeof(eidata), EI_DATA) == sizeof(eidata))
-+                              dso__swap_init(dso, eidata);
-+              }
-+              if (dso__needs_swap(dso) != DSO_SWAP__UNSET &&
-+                  pread(fd, &e_machine, sizeof(e_machine), 18) == sizeof(e_machine))
-+                      e_machine = DSO__SWAP(dso, uint16_t, e_machine);
-+      }
-+      mutex_unlock(dso__data_open_lock());
-+      return e_machine;
-+}
-+
- /**
-  * dso__data_read_addr - Read data from dso address
-  * @dso: dso object
-@@ -1546,6 +1608,33 @@ void dso__put(struct dso *dso)
-               RC_CHK_PUT(dso);
- }
-+int dso__swap_init(struct dso *dso, unsigned char eidata)
-+{
-+      static unsigned int const endian = 1;
-+
-+      dso__set_needs_swap(dso, DSO_SWAP__NO);
-+
-+      switch (eidata) {
-+      case ELFDATA2LSB:
-+              /* We are big endian, DSO is little endian. */
-+              if (*(unsigned char const *)&endian != 1)
-+                      dso__set_needs_swap(dso, DSO_SWAP__YES);
-+              break;
-+
-+      case ELFDATA2MSB:
-+              /* We are little endian, DSO is big endian. */
-+              if (*(unsigned char const *)&endian != 0)
-+                      dso__set_needs_swap(dso, DSO_SWAP__YES);
-+              break;
-+
-+      default:
-+              pr_err("unrecognized DSO data encoding %d\n", eidata);
-+              return -EINVAL;
-+      }
-+
-+      return 0;
-+}
-+
- void dso__set_build_id(struct dso *dso, struct build_id *bid)
- {
-       RC_CHK_ACCESS(dso)->bid = *bid;
-diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
-index 53eac48fd0cd81..4bca8a3c8b48e2 100644
---- a/tools/perf/util/dso.h
-+++ b/tools/perf/util/dso.h
-@@ -677,6 +677,8 @@ bool dso__sorted_by_name(const struct dso *dso);
- void dso__set_sorted_by_name(struct dso *dso);
- void dso__sort_by_name(struct dso *dso);
-+int dso__swap_init(struct dso *dso, unsigned char eidata);
-+
- void dso__set_build_id(struct dso *dso, struct build_id *bid);
- bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
- void dso__read_running_kernel_build_id(struct dso *dso,
-@@ -766,6 +768,7 @@ int dso__data_file_size(struct dso *dso, struct machine *machine);
- off_t dso__data_size(struct dso *dso, struct machine *machine);
- ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
-                             u64 offset, u8 *data, ssize_t size);
-+uint16_t dso__e_machine(struct dso *dso, struct machine *machine);
- ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
-                           struct machine *machine, u64 addr,
-                           u8 *data, ssize_t size);
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index c7fcbb8fb644c3..029a1ef9b287b4 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -1186,33 +1186,6 @@ int filename__read_debuglink(const char *filename, char *debuglink,
- #endif
--static int dso__swap_init(struct dso *dso, unsigned char eidata)
--{
--      static unsigned int const endian = 1;
--
--      dso__set_needs_swap(dso, DSO_SWAP__NO);
--
--      switch (eidata) {
--      case ELFDATA2LSB:
--              /* We are big endian, DSO is little endian. */
--              if (*(unsigned char const *)&endian != 1)
--                      dso__set_needs_swap(dso, DSO_SWAP__YES);
--              break;
--
--      case ELFDATA2MSB:
--              /* We are little endian, DSO is big endian. */
--              if (*(unsigned char const *)&endian != 0)
--                      dso__set_needs_swap(dso, DSO_SWAP__YES);
--              break;
--
--      default:
--              pr_err("unrecognized DSO data encoding %d\n", eidata);
--              return -EINVAL;
--      }
--
--      return 0;
--}
--
- bool symsrc__possibly_runtime(struct symsrc *ss)
- {
-       return ss->dynsym || ss->opdsec;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-dso-move-build_id-to-dso_id.patch b/queue-6.12/perf-dso-move-build_id-to-dso_id.patch
deleted file mode 100644 (file)
index 6a6e04f..0000000
+++ /dev/null
@@ -1,839 +0,0 @@
-From 295ddd9358516166b64d594f5ca07bc35cbb0a62 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 24 Jul 2025 09:32:46 -0700
-Subject: perf dso: Move build_id to dso_id
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit d9f2ecbc5e47fca7bda7c13cff3b3534b1467b32 ]
-
-The dso_id previously contained the major, minor, inode and inode
-generation information from a mmap2 event - the inode generation would
-be zero when reading from /proc/pid/maps. The build_id was in the
-dso. With build ID mmap2 events these fields wouldn't be initialized
-which would largely mean the special empty case where any dso would
-match for equality. This isn't desirable as if a dso is replaced we
-want the comparison to yield a difference.
-
-To support detecting the difference between DSOs based on build_id,
-move the build_id out of the DSO and into the dso_id. The dso_id is
-also stored in the DSO so nothing is lost. Capture in the dso_id what
-parts have been initialized and rename dso_id__inject to
-dso_id__improve_id so that it is clear the dso_id is being improved
-upon with additional information. With the build_id in the dso_id, use
-memcmp to compare for equality.
-
-Signed-off-by: Ian Rogers <irogers@google.com>
-Link: https://lore.kernel.org/r/20250724163302.596743-7-irogers@google.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 2ea64782a428 ("perf tools: Use snprintf() in dso__read_running_kernel_build_id()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-buildid-list.c       |    2 
- tools/perf/builtin-inject.c             |   36 ++++++----
- tools/perf/builtin-report.c             |   11 ++-
- tools/perf/include/perf/perf_dlfilter.h |    2 
- tools/perf/tests/symbols.c              |    4 -
- tools/perf/util/build-id.c              |    4 -
- tools/perf/util/dso.c                   |  109 +++++++++++++++++---------------
- tools/perf/util/dso.h                   |   75 ++++++++++++----------
- tools/perf/util/dsos.c                  |   18 ++---
- tools/perf/util/machine.c               |   28 ++++----
- tools/perf/util/map.c                   |   13 +--
- tools/perf/util/map.h                   |    5 -
- tools/perf/util/sort.c                  |   29 ++++----
- tools/perf/util/synthetic-events.c      |   18 +++--
- 14 files changed, 198 insertions(+), 156 deletions(-)
-
---- a/tools/perf/builtin-buildid-list.c
-+++ b/tools/perf/builtin-buildid-list.c
-@@ -31,7 +31,7 @@ static int buildid__map_cb(struct map *m
-       memset(bid_buf, 0, sizeof(bid_buf));
-       if (dso__has_build_id(dso))
--              build_id__snprintf(dso__bid_const(dso), bid_buf, sizeof(bid_buf));
-+              build_id__snprintf(dso__bid(dso), bid_buf, sizeof(bid_buf));
-       printf("%s %16" PRIx64 " %16" PRIx64, bid_buf, map__start(map), map__end(map));
-       if (dso_long_name != NULL)
-               printf(" %s", dso_long_name);
---- a/tools/perf/builtin-inject.c
-+++ b/tools/perf/builtin-inject.c
-@@ -673,15 +673,17 @@ static int perf_event__repipe_mmap2(cons
-                               struct perf_sample *sample,
-                               struct machine *machine)
- {
--      struct dso_id id;
--      struct dso_id *dso_id = NULL;
-+      struct dso_id id = dso_id_empty;
--      if (!(event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) {
-+      if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
-+              build_id__init(&id.build_id, event->mmap2.build_id, event->mmap2.build_id_size);
-+      } else {
-               id.maj = event->mmap2.maj;
-               id.min = event->mmap2.min;
-               id.ino = event->mmap2.ino;
-               id.ino_generation = event->mmap2.ino_generation;
--              dso_id = &id;
-+              id.mmap2_valid = true;
-+              id.mmap2_ino_generation_valid = true;
-       }
-       return perf_event__repipe_common_mmap(
-@@ -689,7 +691,7 @@ static int perf_event__repipe_mmap2(cons
-               event->mmap2.pid, event->mmap2.tid,
-               event->mmap2.start, event->mmap2.len, event->mmap2.pgoff,
-               event->mmap2.flags, event->mmap2.prot,
--              event->mmap2.filename, dso_id,
-+              event->mmap2.filename, &id,
-               perf_event__process_mmap2);
- }
-@@ -757,19 +759,20 @@ static int perf_event__repipe_tracing_da
- static int dso__read_build_id(struct dso *dso)
- {
-       struct nscookie nsc;
-+      struct build_id bid = { .size = 0, };
-       if (dso__has_build_id(dso))
-               return 0;
-       mutex_lock(dso__lock(dso));
-       nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
--      if (filename__read_build_id(dso__long_name(dso), dso__bid(dso)) > 0)
--              dso__set_has_build_id(dso);
-+      if (filename__read_build_id(dso__long_name(dso), &bid) > 0)
-+              dso__set_build_id(dso, &bid);
-       else if (dso__nsinfo(dso)) {
-               char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso));
--              if (new_name && filename__read_build_id(new_name, dso__bid(dso)) > 0)
--                      dso__set_has_build_id(dso);
-+              if (new_name && filename__read_build_id(new_name, &bid) > 0)
-+                      dso__set_build_id(dso, &bid);
-               free(new_name);
-       }
-       nsinfo__mountns_exit(&nsc);
-@@ -818,23 +821,26 @@ static bool perf_inject__lookup_known_bu
-                                              struct dso *dso)
- {
-       struct str_node *pos;
--      int bid_len;
-       strlist__for_each_entry(pos, inject->known_build_ids) {
-+              struct build_id bid;
-               const char *build_id, *dso_name;
-+              size_t bid_len;
-               build_id = skip_spaces(pos->s);
-               dso_name = strchr(build_id, ' ');
-               bid_len = dso_name - pos->s;
-+              if (bid_len > sizeof(bid.data))
-+                      bid_len = sizeof(bid.data);
-               dso_name = skip_spaces(dso_name);
-               if (strcmp(dso__long_name(dso), dso_name))
-                       continue;
--              for (int ix = 0; 2 * ix + 1 < bid_len; ++ix) {
--                      dso__bid(dso)->data[ix] = (hex(build_id[2 * ix]) << 4 |
--                                                hex(build_id[2 * ix + 1]));
-+              for (size_t ix = 0; 2 * ix + 1 < bid_len; ++ix) {
-+                      bid.data[ix] = (hex(build_id[2 * ix]) << 4 |
-+                                      hex(build_id[2 * ix + 1]));
-               }
--              dso__bid(dso)->size = bid_len / 2;
--              dso__set_has_build_id(dso);
-+              bid.size = bid_len / 2;
-+              dso__set_build_id(dso, &bid);
-               return true;
-       }
-       return false;
---- a/tools/perf/builtin-report.c
-+++ b/tools/perf/builtin-report.c
-@@ -855,17 +855,24 @@ static int maps__fprintf_task_cb(struct
-       struct maps__fprintf_task_args *args = data;
-       const struct dso *dso = map__dso(map);
-       u32 prot = map__prot(map);
-+      const struct dso_id *dso_id = dso__id_const(dso);
-       int ret;
-+      char buf[SBUILD_ID_SIZE];
-+
-+      if (dso_id->mmap2_valid)
-+              snprintf(buf, sizeof(buf), "%" PRIu64, dso_id->ino);
-+      else
-+              build_id__snprintf(&dso_id->build_id, buf, sizeof(buf));
-       ret = fprintf(args->fp,
--              "%*s  %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n",
-+              "%*s  %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %s %s\n",
-               args->indent, "", map__start(map), map__end(map),
-               prot & PROT_READ ? 'r' : '-',
-               prot & PROT_WRITE ? 'w' : '-',
-               prot & PROT_EXEC ? 'x' : '-',
-               map__flags(map) ? 's' : 'p',
-               map__pgoff(map),
--              dso__id_const(dso)->ino, dso__name(dso));
-+              buf, dso__name(dso));
-       if (ret < 0)
-               return ret;
---- a/tools/perf/include/perf/perf_dlfilter.h
-+++ b/tools/perf/include/perf/perf_dlfilter.h
-@@ -87,7 +87,7 @@ struct perf_dlfilter_al {
-       __u8  is_64_bit; /* Only valid if dso is not NULL */
-       __u8  is_kernel_ip; /* True if in kernel space */
-       __u32 buildid_size;
--      __u8 *buildid;
-+      const __u8 *buildid;
-       /* Below members are only populated by resolve_ip() */
-       __u8 filtered; /* True if this sample event will be filtered out */
-       const char *comm;
---- a/tools/perf/tests/symbols.c
-+++ b/tools/perf/tests/symbols.c
-@@ -96,8 +96,8 @@ static int create_map(struct test_info *
-       dso__put(dso);
-       /* Create a dummy map at 0x100000 */
--      *map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, NULL,
--                        PROT_EXEC, 0, NULL, filename, ti->thread);
-+      *map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, &dso_id_empty,
-+                        PROT_EXEC, /*flags=*/0, filename, ti->thread);
-       if (!*map_p) {
-               pr_debug("Failed to create map!");
-               return TEST_FAIL;
---- a/tools/perf/util/build-id.c
-+++ b/tools/perf/util/build-id.c
-@@ -236,7 +236,7 @@ char *__dso__build_id_filename(const str
-       if (!dso__has_build_id(dso))
-               return NULL;
--      build_id__snprintf(dso__bid_const(dso), sbuild_id, sizeof(sbuild_id));
-+      build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id));
-       linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
-       if (!linkname)
-               return NULL;
-@@ -319,7 +319,7 @@ static int machine__write_buildid_table_
-       }
-       in_kernel = dso__kernel(dso) || is_kernel_module(name, PERF_RECORD_MISC_CPUMODE_UNKNOWN);
--      return write_buildid(name, name_len, dso__bid(dso), args->machine->pid,
-+      return write_buildid(name, name_len, &dso__id(dso)->build_id, args->machine->pid,
-                            in_kernel ? args->kmisc : args->umisc, args->fd);
- }
---- a/tools/perf/util/dso.c
-+++ b/tools/perf/util/dso.c
-@@ -215,7 +215,7 @@ int dso__read_binary_type_filename(const
-                       break;
-               }
--              build_id__snprintf(dso__bid_const(dso), build_id_hex, sizeof(build_id_hex));
-+              build_id__snprintf(dso__bid(dso), build_id_hex, sizeof(build_id_hex));
-               len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
-               snprintf(filename + len, size - len, "%.2s/%s.debug",
-                        build_id_hex, build_id_hex + 2);
-@@ -1376,64 +1376,76 @@ static void dso__set_long_name_id(struct
- static int __dso_id__cmp(const struct dso_id *a, const struct dso_id *b)
- {
--      if (a->maj > b->maj) return -1;
--      if (a->maj < b->maj) return 1;
-+      if (a->mmap2_valid && b->mmap2_valid) {
-+              if (a->maj > b->maj) return -1;
-+              if (a->maj < b->maj) return 1;
--      if (a->min > b->min) return -1;
--      if (a->min < b->min) return 1;
-+              if (a->min > b->min) return -1;
-+              if (a->min < b->min) return 1;
--      if (a->ino > b->ino) return -1;
--      if (a->ino < b->ino) return 1;
--
--      /*
--       * Synthesized MMAP events have zero ino_generation, avoid comparing
--       * them with MMAP events with actual ino_generation.
--       *
--       * I found it harmful because the mismatch resulted in a new
--       * dso that did not have a build ID whereas the original dso did have a
--       * build ID. The build ID was essential because the object was not found
--       * otherwise. - Adrian
--       */
--      if (a->ino_generation && b->ino_generation) {
-+              if (a->ino > b->ino) return -1;
-+              if (a->ino < b->ino) return 1;
-+      }
-+      if (a->mmap2_ino_generation_valid && b->mmap2_ino_generation_valid) {
-               if (a->ino_generation > b->ino_generation) return -1;
-               if (a->ino_generation < b->ino_generation) return 1;
-       }
--
-+      if (build_id__is_defined(&a->build_id) && build_id__is_defined(&b->build_id)) {
-+              if (a->build_id.size != b->build_id.size)
-+                      return a->build_id.size < b->build_id.size ? -1 : 1;
-+              return memcmp(a->build_id.data, b->build_id.data, a->build_id.size);
-+      }
-       return 0;
- }
--bool dso_id__empty(const struct dso_id *id)
--{
--      if (!id)
--              return true;
--
--      return !id->maj && !id->min && !id->ino && !id->ino_generation;
--}
-+const struct dso_id dso_id_empty = {
-+      {
-+              .maj = 0,
-+              .min = 0,
-+              .ino = 0,
-+              .ino_generation = 0,
-+      },
-+      .mmap2_valid = false,
-+      .mmap2_ino_generation_valid = false,
-+      {
-+              .size = 0,
-+      }
-+};
--void __dso__inject_id(struct dso *dso, const struct dso_id *id)
-+void __dso__improve_id(struct dso *dso, const struct dso_id *id)
- {
-       struct dsos *dsos = dso__dsos(dso);
-       struct dso_id *dso_id = dso__id(dso);
-+      bool changed = false;
-       /* dsos write lock held by caller. */
--      dso_id->maj = id->maj;
--      dso_id->min = id->min;
--      dso_id->ino = id->ino;
--      dso_id->ino_generation = id->ino_generation;
--
--      if (dsos)
-+      if (id->mmap2_valid && !dso_id->mmap2_valid) {
-+              dso_id->maj = id->maj;
-+              dso_id->min = id->min;
-+              dso_id->ino = id->ino;
-+              dso_id->mmap2_valid = true;
-+              changed = true;
-+      }
-+      if (id->mmap2_ino_generation_valid && !dso_id->mmap2_ino_generation_valid) {
-+              dso_id->ino_generation = id->ino_generation;
-+              dso_id->mmap2_ino_generation_valid = true;
-+              changed = true;
-+      }
-+      if (build_id__is_defined(&id->build_id) && !build_id__is_defined(&dso_id->build_id)) {
-+              dso_id->build_id = id->build_id;
-+              changed = true;
-+      }
-+      if (changed && dsos)
-               dsos->sorted = false;
- }
- int dso_id__cmp(const struct dso_id *a, const struct dso_id *b)
- {
--      /*
--       * The second is always dso->id, so zeroes if not set, assume passing
--       * NULL for a means a zeroed id
--       */
--      if (dso_id__empty(a) || dso_id__empty(b))
-+      if (a == &dso_id_empty || b == &dso_id_empty) {
-+              /* There is no valid data to compare so the comparison always returns identical. */
-               return 0;
-+      }
-       return __dso_id__cmp(a, b);
- }
-@@ -1530,7 +1542,6 @@ struct dso *dso__new_id(const char *name
-               dso->loaded = 0;
-               dso->rel = 0;
-               dso->sorted_by_name = 0;
--              dso->has_build_id = 0;
-               dso->has_srcline = 1;
-               dso->a2l_fails = 1;
-               dso->kernel = DSO_SPACE__USER;
-@@ -1635,15 +1646,14 @@ int dso__swap_init(struct dso *dso, unsi
-       return 0;
- }
--void dso__set_build_id(struct dso *dso, struct build_id *bid)
-+void dso__set_build_id(struct dso *dso, const struct build_id *bid)
- {
--      RC_CHK_ACCESS(dso)->bid = *bid;
--      RC_CHK_ACCESS(dso)->has_build_id = 1;
-+      dso__id(dso)->build_id = *bid;
- }
--bool dso__build_id_equal(const struct dso *dso, struct build_id *bid)
-+bool dso__build_id_equal(const struct dso *dso, const struct build_id *bid)
- {
--      const struct build_id *dso_bid = dso__bid_const(dso);
-+      const struct build_id *dso_bid = dso__bid(dso);
-       if (dso_bid->size > bid->size && dso_bid->size == BUILD_ID_SIZE) {
-               /*
-@@ -1662,18 +1672,20 @@ bool dso__build_id_equal(const struct ds
- void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
- {
-       char path[PATH_MAX];
-+      struct build_id bid = { .size = 0, };
-       if (machine__is_default_guest(machine))
-               return;
-       sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
--      if (sysfs__read_build_id(path, dso__bid(dso)) == 0)
--              dso__set_has_build_id(dso);
-+      sysfs__read_build_id(path, &bid);
-+      dso__set_build_id(dso, &bid);
- }
- int dso__kernel_module_get_build_id(struct dso *dso,
-                                   const char *root_dir)
- {
-       char filename[PATH_MAX];
-+      struct build_id bid = { .size = 0, };
-       /*
-        * kernel module short names are of the form "[module]" and
-        * we need just "module" here.
-@@ -1684,9 +1696,8 @@ int dso__kernel_module_get_build_id(stru
-                "%s/sys/module/%.*s/notes/.note.gnu.build-id",
-                root_dir, (int)strlen(name) - 1, name);
--      if (sysfs__read_build_id(filename, dso__bid(dso)) == 0)
--              dso__set_has_build_id(dso);
--
-+      sysfs__read_build_id(filename, &bid);
-+      dso__set_build_id(dso, &bid);
-       return 0;
- }
---- a/tools/perf/util/dso.h
-+++ b/tools/perf/util/dso.h
-@@ -127,14 +127,33 @@ enum dso_load_errno {
- #define DSO__DATA_CACHE_SIZE 4096
- #define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
--/*
-- * Data about backing storage DSO, comes from PERF_RECORD_MMAP2 meta events
-+/**
-+ * struct dso_id
-+ *
-+ * Data about backing storage DSO, comes from PERF_RECORD_MMAP2 meta events,
-+ * reading from /proc/pid/maps or synthesis of build_ids from DSOs. Possibly
-+ * incomplete at any particular use.
-  */
- struct dso_id {
--      u32     maj;
--      u32     min;
--      u64     ino;
--      u64     ino_generation;
-+      /* Data related to the mmap2 event or read from /proc/pid/maps. */
-+      struct {
-+              u32     maj;
-+              u32     min;
-+              u64     ino;
-+              u64     ino_generation;
-+      };
-+      /** @mmap2_valid: Are the maj, min and ino fields valid? */
-+      bool    mmap2_valid;
-+      /**
-+       * @mmap2_ino_generation_valid: Is the ino_generation valid? Generally
-+       * false for /proc/pid/maps mmap event.
-+       */
-+      bool    mmap2_ino_generation_valid;
-+      /**
-+       * @build_id: A possibly populated build_id. build_id__is_defined checks
-+       * whether it is populated.
-+       */
-+      struct build_id build_id;
- };
- struct dso_cache {
-@@ -183,7 +202,6 @@ DECLARE_RC_STRUCT(dso) {
-               u64             addr;
-               struct symbol   *symbol;
-       } last_find_result;
--      struct build_id  bid;
-       u64              text_offset;
-       u64              text_end;
-       const char       *short_name;
-@@ -216,7 +234,6 @@ DECLARE_RC_STRUCT(dso) {
-       enum dso_swap_type      needs_swap:2;
-       bool                    is_kmod:1;
-       u8               adjust_symbols:1;
--      u8               has_build_id:1;
-       u8               header_build_id:1;
-       u8               has_srcline:1;
-       u8               hit:1;
-@@ -232,6 +249,9 @@ DECLARE_RC_STRUCT(dso) {
- };
- extern struct mutex _dso__data_open_lock;
-+extern const struct dso_id dso_id_empty;
-+
-+int dso_id__cmp(const struct dso_id *a, const struct dso_id *b);
- /* dso__for_each_symbol - iterate over the symbols of given type
-  *
-@@ -302,31 +322,11 @@ static inline void dso__set_auxtrace_cac
-       RC_CHK_ACCESS(dso)->auxtrace_cache = cache;
- }
--static inline struct build_id *dso__bid(struct dso *dso)
--{
--      return &RC_CHK_ACCESS(dso)->bid;
--}
--
--static inline const struct build_id *dso__bid_const(const struct dso *dso)
--{
--      return &RC_CHK_ACCESS(dso)->bid;
--}
--
- static inline struct dso_bpf_prog *dso__bpf_prog(struct dso *dso)
- {
-       return &RC_CHK_ACCESS(dso)->bpf_prog;
- }
--static inline bool dso__has_build_id(const struct dso *dso)
--{
--      return RC_CHK_ACCESS(dso)->has_build_id;
--}
--
--static inline void dso__set_has_build_id(struct dso *dso)
--{
--      RC_CHK_ACCESS(dso)->has_build_id = true;
--}
--
- static inline bool dso__has_srcline(const struct dso *dso)
- {
-       return RC_CHK_ACCESS(dso)->has_srcline;
-@@ -402,6 +402,16 @@ static inline const struct dso_id *dso__
-       return &RC_CHK_ACCESS(dso)->id;
- }
-+static inline const struct build_id *dso__bid(const struct dso *dso)
-+{
-+      return &dso__id_const(dso)->build_id;
-+}
-+
-+static inline bool dso__has_build_id(const struct dso *dso)
-+{
-+      return build_id__is_defined(dso__bid(dso));
-+}
-+
- static inline struct rb_root_cached *dso__inlined_nodes(struct dso *dso)
- {
-       return &RC_CHK_ACCESS(dso)->inlined_nodes;
-@@ -639,9 +649,6 @@ static inline void dso__set_text_offset(
-       RC_CHK_ACCESS(dso)->text_offset = val;
- }
--int dso_id__cmp(const struct dso_id *a, const struct dso_id *b);
--bool dso_id__empty(const struct dso_id *id);
--
- struct dso *dso__new_id(const char *name, const struct dso_id *id);
- struct dso *dso__new(const char *name);
- void dso__delete(struct dso *dso);
-@@ -649,7 +656,7 @@ void dso__delete(struct dso *dso);
- int dso__cmp_id(struct dso *a, struct dso *b);
- void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated);
- void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated);
--void __dso__inject_id(struct dso *dso, const struct dso_id *id);
-+void __dso__improve_id(struct dso *dso, const struct dso_id *id);
- int dso__name_len(const struct dso *dso);
-@@ -679,8 +686,8 @@ void dso__sort_by_name(struct dso *dso);
- int dso__swap_init(struct dso *dso, unsigned char eidata);
--void dso__set_build_id(struct dso *dso, struct build_id *bid);
--bool dso__build_id_equal(const struct dso *dso, struct build_id *bid);
-+void dso__set_build_id(struct dso *dso, const struct build_id *bid);
-+bool dso__build_id_equal(const struct dso *dso, const struct build_id *bid);
- void dso__read_running_kernel_build_id(struct dso *dso,
-                                      struct machine *machine);
- int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
---- a/tools/perf/util/dsos.c
-+++ b/tools/perf/util/dsos.c
-@@ -72,6 +72,7 @@ static int dsos__read_build_ids_cb(struc
- {
-       struct dsos__read_build_ids_cb_args *args = data;
-       struct nscookie nsc;
-+      struct build_id bid = { .size = 0, };
-       if (args->with_hits && !dso__hit(dso) && !dso__is_vdso(dso))
-               return 0;
-@@ -80,15 +81,15 @@ static int dsos__read_build_ids_cb(struc
-               return 0;
-       }
-       nsinfo__mountns_enter(dso__nsinfo(dso), &nsc);
--      if (filename__read_build_id(dso__long_name(dso), dso__bid(dso)) > 0) {
-+      if (filename__read_build_id(dso__long_name(dso), &bid) > 0) {
-+              dso__set_build_id(dso, &bid);
-               args->have_build_id = true;
--              dso__set_has_build_id(dso);
-       } else if (errno == ENOENT && dso__nsinfo(dso)) {
-               char *new_name = dso__filename_with_chroot(dso, dso__long_name(dso));
--              if (new_name && filename__read_build_id(new_name, dso__bid(dso)) > 0) {
-+              if (new_name && filename__read_build_id(new_name, &bid) > 0) {
-+                      dso__set_build_id(dso, &bid);
-                       args->have_build_id = true;
--                      dso__set_has_build_id(dso);
-               }
-               free(new_name);
-       }
-@@ -284,7 +285,7 @@ struct dso *dsos__find(struct dsos *dsos
-       struct dso *res;
-       down_read(&dsos->lock);
--      res = __dsos__find_id(dsos, name, NULL, cmp_short, /*write_locked=*/false);
-+      res = __dsos__find_id(dsos, name, &dso_id_empty, cmp_short, /*write_locked=*/false);
-       up_read(&dsos->lock);
-       return res;
- }
-@@ -341,8 +342,8 @@ static struct dso *__dsos__findnew_id(st
- {
-       struct dso *dso = __dsos__find_id(dsos, name, id, false, /*write_locked=*/true);
--      if (dso && dso_id__empty(dso__id(dso)) && !dso_id__empty(id))
--              __dso__inject_id(dso, id);
-+      if (dso)
-+              __dso__improve_id(dso, id);
-       return dso ? dso : __dsos__addnew_id(dsos, name, id);
- }
-@@ -433,7 +434,8 @@ struct dso *dsos__findnew_module_dso(str
-       down_write(&dsos->lock);
--      dso = __dsos__find_id(dsos, m->name, NULL, /*cmp_short=*/true, /*write_locked=*/true);
-+      dso = __dsos__find_id(dsos, m->name, &dso_id_empty, /*cmp_short=*/true,
-+                            /*write_locked=*/true);
-       if (dso) {
-               up_write(&dsos->lock);
-               return dso;
---- a/tools/perf/util/machine.c
-+++ b/tools/perf/util/machine.c
-@@ -1696,21 +1696,21 @@ int machine__process_mmap2_event(struct
- {
-       struct thread *thread;
-       struct map *map;
--      struct dso_id dso_id = {
--              .maj = event->mmap2.maj,
--              .min = event->mmap2.min,
--              .ino = event->mmap2.ino,
--              .ino_generation = event->mmap2.ino_generation,
--      };
--      struct build_id __bid, *bid = NULL;
-+      struct dso_id dso_id = dso_id_empty;
-       int ret = 0;
-       if (dump_trace)
-               perf_event__fprintf_mmap2(event, stdout);
-       if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
--              bid = &__bid;
--              build_id__init(bid, event->mmap2.build_id, event->mmap2.build_id_size);
-+              build_id__init(&dso_id.build_id, event->mmap2.build_id, event->mmap2.build_id_size);
-+      } else {
-+              dso_id.maj = event->mmap2.maj;
-+              dso_id.min = event->mmap2.min;
-+              dso_id.ino = event->mmap2.ino;
-+              dso_id.ino_generation = event->mmap2.ino_generation;
-+              dso_id.mmap2_valid = true;
-+              dso_id.mmap2_ino_generation_valid = true;
-       }
-       if (sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
-@@ -1722,7 +1722,7 @@ int machine__process_mmap2_event(struct
-               };
-               strlcpy(xm.name, event->mmap2.filename, KMAP_NAME_LEN);
--              ret = machine__process_kernel_mmap_event(machine, &xm, bid);
-+              ret = machine__process_kernel_mmap_event(machine, &xm, &dso_id.build_id);
-               if (ret < 0)
-                       goto out_problem;
-               return 0;
-@@ -1736,7 +1736,7 @@ int machine__process_mmap2_event(struct
-       map = map__new(machine, event->mmap2.start,
-                       event->mmap2.len, event->mmap2.pgoff,
-                       &dso_id, event->mmap2.prot,
--                      event->mmap2.flags, bid,
-+                      event->mmap2.flags,
-                       event->mmap2.filename, thread);
-       if (map == NULL)
-@@ -1794,8 +1794,8 @@ int machine__process_mmap_event(struct m
-               prot = PROT_EXEC;
-       map = map__new(machine, event->mmap.start,
--                      event->mmap.len, event->mmap.pgoff,
--                      NULL, prot, 0, NULL, event->mmap.filename, thread);
-+                     event->mmap.len, event->mmap.pgoff,
-+                     &dso_id_empty, prot, /*flags=*/0, event->mmap.filename, thread);
-       if (map == NULL)
-               goto out_problem_map;
-@@ -3155,7 +3155,7 @@ struct dso *machine__findnew_dso_id(stru
- struct dso *machine__findnew_dso(struct machine *machine, const char *filename)
- {
--      return machine__findnew_dso_id(machine, filename, NULL);
-+      return machine__findnew_dso_id(machine, filename, &dso_id_empty);
- }
- char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
---- a/tools/perf/util/map.c
-+++ b/tools/perf/util/map.c
-@@ -120,8 +120,8 @@ static void map__init(struct map *map, u
- }
- struct map *map__new(struct machine *machine, u64 start, u64 len,
--                   u64 pgoff, struct dso_id *id,
--                   u32 prot, u32 flags, struct build_id *bid,
-+                   u64 pgoff, const struct dso_id *id,
-+                   u32 prot, u32 flags,
-                    char *filename, struct thread *thread)
- {
-       struct map *result;
-@@ -132,7 +132,7 @@ struct map *map__new(struct machine *mac
-       map = zalloc(sizeof(*map));
-       if (ADD_RC_CHK(result, map)) {
-               char newfilename[PATH_MAX];
--              struct dso *dso, *header_bid_dso;
-+              struct dso *dso;
-               int anon, no_dso, vdso, android;
-               android = is_android_lib(filename);
-@@ -189,16 +189,15 @@ struct map *map__new(struct machine *mac
-               dso__set_nsinfo(dso, nsi);
-               mutex_unlock(dso__lock(dso));
--              if (build_id__is_defined(bid)) {
--                      dso__set_build_id(dso, bid);
--              } else {
-+              if (!build_id__is_defined(&id->build_id)) {
-                       /*
-                        * If the mmap event had no build ID, search for an existing dso from the
-                        * build ID header by name. Otherwise only the dso loaded at the time of
-                        * reading the header will have the build ID set and all future mmaps will
-                        * have it missing.
-                        */
--                      header_bid_dso = dsos__find(&machine->dsos, filename, false);
-+                      struct dso *header_bid_dso = dsos__find(&machine->dsos, filename, false);
-+
-                       if (header_bid_dso && dso__header_build_id(header_bid_dso)) {
-                               dso__set_build_id(dso, dso__bid(header_bid_dso));
-                               dso__set_header_build_id(dso, 1);
---- a/tools/perf/util/map.h
-+++ b/tools/perf/util/map.h
-@@ -173,11 +173,10 @@ struct thread;
-       __map__for_each_symbol_by_name(map, sym_name, (pos), idx)
- struct dso_id;
--struct build_id;
- struct map *map__new(struct machine *machine, u64 start, u64 len,
--                   u64 pgoff, struct dso_id *id, u32 prot, u32 flags,
--                   struct build_id *bid, char *filename, struct thread *thread);
-+                   u64 pgoff, const struct dso_id *id, u32 prot, u32 flags,
-+                   char *filename, struct thread *thread);
- struct map *map__new2(u64 start, struct dso *dso);
- void map__delete(struct map *map);
- struct map *map__clone(struct map *map);
---- a/tools/perf/util/sort.c
-+++ b/tools/perf/util/sort.c
-@@ -1579,22 +1579,27 @@ sort__dcacheline_cmp(struct hist_entry *
-       if (rc)
-               return rc;
-       /*
--       * Addresses with no major/minor numbers are assumed to be
-+       * Addresses with no major/minor numbers or build ID are assumed to be
-        * anonymous in userspace.  Sort those on pid then address.
-        *
-        * The kernel and non-zero major/minor mapped areas are
-        * assumed to be unity mapped.  Sort those on address.
-        */
-+      if (left->cpumode != PERF_RECORD_MISC_KERNEL && (map__flags(l_map) & MAP_SHARED) == 0) {
-+              const struct dso_id *dso_id = dso__id_const(l_dso);
--      if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
--          (!(map__flags(l_map) & MAP_SHARED)) && !dso__id(l_dso)->maj && !dso__id(l_dso)->min &&
--           !dso__id(l_dso)->ino && !dso__id(l_dso)->ino_generation) {
--              /* userspace anonymous */
--
--              if (thread__pid(left->thread) > thread__pid(right->thread))
--                      return -1;
--              if (thread__pid(left->thread) < thread__pid(right->thread))
--                      return 1;
-+              if (!dso_id->mmap2_valid)
-+                      dso_id = dso__id_const(r_dso);
-+
-+              if (!build_id__is_defined(&dso_id->build_id) &&
-+                  (!dso_id->mmap2_valid || (dso_id->maj == 0 && dso_id->min == 0))) {
-+                      /* userspace anonymous */
-+
-+                      if (thread__pid(left->thread) > thread__pid(right->thread))
-+                              return -1;
-+                      if (thread__pid(left->thread) < thread__pid(right->thread))
-+                              return 1;
-+              }
-       }
- addr:
-@@ -1619,6 +1624,7 @@ static int hist_entry__dcacheline_snprin
-       if (he->mem_info) {
-               struct map *map = mem_info__daddr(he->mem_info)->ms.map;
-               struct dso *dso = map ? map__dso(map) : NULL;
-+              const struct dso_id *dso_id = dso ? dso__id_const(dso) : &dso_id_empty;
-               addr = cl_address(mem_info__daddr(he->mem_info)->al_addr, chk_double_cl);
-               ms = &mem_info__daddr(he->mem_info)->ms;
-@@ -1627,8 +1633,7 @@ static int hist_entry__dcacheline_snprin
-               if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
-                    map && !(map__prot(map) & PROT_EXEC) &&
-                    (map__flags(map) & MAP_SHARED) &&
--                   (dso__id(dso)->maj || dso__id(dso)->min || dso__id(dso)->ino ||
--                    dso__id(dso)->ino_generation))
-+                   (!dso_id->mmap2_valid || (dso_id->maj == 0 && dso_id->min == 0)))
-                       level = 's';
-               else if (!map)
-                       level = 'X';
---- a/tools/perf/util/synthetic-events.c
-+++ b/tools/perf/util/synthetic-events.c
-@@ -371,7 +371,7 @@ static void perf_record_mmap2__read_buil
-       struct nsinfo *nsi;
-       struct nscookie nc;
-       struct dso *dso = NULL;
--      struct dso_id id;
-+      struct dso_id dso_id = dso_id_empty;
-       int rc;
-       if (is_kernel) {
-@@ -379,12 +379,18 @@ static void perf_record_mmap2__read_buil
-               goto out;
-       }
--      id.maj = event->maj;
--      id.min = event->min;
--      id.ino = event->ino;
--      id.ino_generation = event->ino_generation;
-+      if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
-+              build_id__init(&dso_id.build_id, event->build_id, event->build_id_size);
-+      } else {
-+              dso_id.maj = event->maj;
-+              dso_id.min = event->min;
-+              dso_id.ino = event->ino;
-+              dso_id.ino_generation = event->ino_generation;
-+              dso_id.mmap2_valid = true;
-+              dso_id.mmap2_ino_generation_valid = true;
-+      };
--      dso = dsos__findnew_id(&machine->dsos, event->filename, &id);
-+      dso = dsos__findnew_id(&machine->dsos, event->filename, &dso_id);
-       if (dso && dso__has_build_id(dso)) {
-               bid = *dso__bid(dso);
-               rc = 0;
diff --git a/queue-6.12/perf-dso-use-lock-annotations-to-fix-asan-deadlock.patch b/queue-6.12/perf-dso-use-lock-annotations-to-fix-asan-deadlock.patch
deleted file mode 100644 (file)
index b02128a..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-From a70398930ce7dc7600103884f6fe27e710d871ea Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 17 Mar 2025 21:31:50 -0700
-Subject: perf dso: Use lock annotations to fix asan deadlock
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit 5ac22c35aa8519f1fb5522fb3aff915f28a9365e ]
-
-dso__list_del with address sanitizer and/or reference count checking
-will call dso__put that can call dso__data_close reentrantly trying to
-lock the dso__data_open_lock and deadlocking. Switch from pthread
-mutexes to perf's mutex so that lock checking is performed in debug
-builds. Add lock annotations that diagnosed the problem. Release the
-dso__data_open_lock around the dso__put to avoid the deadlock.
-
-Change the declaration of dso__data_get_fd to return a boolean,
-indicating the fd is valid and the lock is held, to make it compatible
-with the thread safety annotations as a try lock.
-
-Signed-off-by: Ian Rogers <irogers@google.com>
-Link: https://lore.kernel.org/r/20250318043151.137973-3-irogers@google.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: 2ea64782a428 ("perf tools: Use snprintf() in dso__read_running_kernel_build_id()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/tests/dso-data.c              |  4 +-
- tools/perf/util/dso.c                    | 74 +++++++++++++++---------
- tools/perf/util/dso.h                    | 15 +++--
- tools/perf/util/unwind-libunwind-local.c | 16 ++---
- 4 files changed, 66 insertions(+), 43 deletions(-)
-
-diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
-index 5286ae8bd2d70d..06be7c5d849554 100644
---- a/tools/perf/tests/dso-data.c
-+++ b/tools/perf/tests/dso-data.c
-@@ -106,9 +106,9 @@ struct test_data_offset offsets[] = {
- /* move it from util/dso.c for compatibility */
- static int dso__data_fd(struct dso *dso, struct machine *machine)
- {
--      int fd = dso__data_get_fd(dso, machine);
-+      int fd = -1;
--      if (fd >= 0)
-+      if (dso__data_get_fd(dso, machine, &fd))
-               dso__data_put_fd(dso);
-       return fd;
-diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
-index 5c6e85fdae0de1..05a9dc6f41f820 100644
---- a/tools/perf/util/dso.c
-+++ b/tools/perf/util/dso.c
-@@ -490,11 +490,25 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
- /*
-  * Global list of open DSOs and the counter.
-  */
-+struct mutex _dso__data_open_lock;
- static LIST_HEAD(dso__data_open);
--static long dso__data_open_cnt;
--static pthread_mutex_t dso__data_open_lock = PTHREAD_MUTEX_INITIALIZER;
-+static long dso__data_open_cnt GUARDED_BY(_dso__data_open_lock);
--static void dso__list_add(struct dso *dso)
-+static void dso__data_open_lock_init(void)
-+{
-+      mutex_init(&_dso__data_open_lock);
-+}
-+
-+static struct mutex *dso__data_open_lock(void) LOCK_RETURNED(_dso__data_open_lock)
-+{
-+      static pthread_once_t data_open_lock_once = PTHREAD_ONCE_INIT;
-+
-+      pthread_once(&data_open_lock_once, dso__data_open_lock_init);
-+
-+      return &_dso__data_open_lock;
-+}
-+
-+static void dso__list_add(struct dso *dso) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       list_add_tail(&dso__data(dso)->open_entry, &dso__data_open);
- #ifdef REFCNT_CHECKING
-@@ -505,11 +519,13 @@ static void dso__list_add(struct dso *dso)
-       dso__data_open_cnt++;
- }
--static void dso__list_del(struct dso *dso)
-+static void dso__list_del(struct dso *dso) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       list_del_init(&dso__data(dso)->open_entry);
- #ifdef REFCNT_CHECKING
-+      mutex_unlock(dso__data_open_lock());
-       dso__put(dso__data(dso)->dso);
-+      mutex_lock(dso__data_open_lock());
- #endif
-       WARN_ONCE(dso__data_open_cnt <= 0,
-                 "DSO data fd counter out of bounds.");
-@@ -518,7 +534,7 @@ static void dso__list_del(struct dso *dso)
- static void close_first_dso(void);
--static int do_open(char *name)
-+static int do_open(char *name) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       int fd;
-       char sbuf[STRERR_BUFSIZE];
-@@ -545,6 +561,7 @@ char *dso__filename_with_chroot(const struct dso *dso, const char *filename)
- }
- static int __open_dso(struct dso *dso, struct machine *machine)
-+      EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       int fd = -EINVAL;
-       char *root_dir = (char *)"";
-@@ -610,6 +627,7 @@ static void check_data_close(void);
-  * list/count of open DSO objects.
-  */
- static int open_dso(struct dso *dso, struct machine *machine)
-+      EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       int fd;
-       struct nscookie nsc;
-@@ -635,7 +653,7 @@ static int open_dso(struct dso *dso, struct machine *machine)
-       return fd;
- }
--static void close_data_fd(struct dso *dso)
-+static void close_data_fd(struct dso *dso) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       if (dso__data(dso)->fd >= 0) {
-               close(dso__data(dso)->fd);
-@@ -652,12 +670,12 @@ static void close_data_fd(struct dso *dso)
-  * Close @dso's data file descriptor and updates
-  * list/count of open DSO objects.
-  */
--static void close_dso(struct dso *dso)
-+static void close_dso(struct dso *dso) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       close_data_fd(dso);
- }
--static void close_first_dso(void)
-+static void close_first_dso(void) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       struct dso_data *dso_data;
-       struct dso *dso;
-@@ -702,7 +720,7 @@ void reset_fd_limit(void)
-       fd_limit = 0;
- }
--static bool may_cache_fd(void)
-+static bool may_cache_fd(void) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       if (!fd_limit)
-               fd_limit = get_fd_limit();
-@@ -718,7 +736,7 @@ static bool may_cache_fd(void)
-  * for opened dso file descriptors. The limit is half
-  * of the RLIMIT_NOFILE files opened.
- */
--static void check_data_close(void)
-+static void check_data_close(void) EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       bool cache_fd = may_cache_fd();
-@@ -734,12 +752,13 @@ static void check_data_close(void)
-  */
- void dso__data_close(struct dso *dso)
- {
--      pthread_mutex_lock(&dso__data_open_lock);
-+      mutex_lock(dso__data_open_lock());
-       close_dso(dso);
--      pthread_mutex_unlock(&dso__data_open_lock);
-+      mutex_unlock(dso__data_open_lock());
- }
- static void try_to_open_dso(struct dso *dso, struct machine *machine)
-+      EXCLUSIVE_LOCKS_REQUIRED(_dso__data_open_lock)
- {
-       enum dso_binary_type binary_type_data[] = {
-               DSO_BINARY_TYPE__BUILD_ID_CACHE,
-@@ -781,25 +800,27 @@ static void try_to_open_dso(struct dso *dso, struct machine *machine)
-  * returns file descriptor.  It should be paired with
-  * dso__data_put_fd() if it returns non-negative value.
-  */
--int dso__data_get_fd(struct dso *dso, struct machine *machine)
-+bool dso__data_get_fd(struct dso *dso, struct machine *machine, int *fd)
- {
-+      *fd = -1;
-       if (dso__data(dso)->status == DSO_DATA_STATUS_ERROR)
--              return -1;
-+              return false;
--      if (pthread_mutex_lock(&dso__data_open_lock) < 0)
--              return -1;
-+      mutex_lock(dso__data_open_lock());
-       try_to_open_dso(dso, machine);
--      if (dso__data(dso)->fd < 0)
--              pthread_mutex_unlock(&dso__data_open_lock);
-+      *fd = dso__data(dso)->fd;
-+      if (*fd >= 0)
-+              return true;
--      return dso__data(dso)->fd;
-+      mutex_unlock(dso__data_open_lock());
-+      return false;
- }
- void dso__data_put_fd(struct dso *dso __maybe_unused)
- {
--      pthread_mutex_unlock(&dso__data_open_lock);
-+      mutex_unlock(dso__data_open_lock());
- }
- bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
-@@ -951,7 +972,7 @@ static ssize_t file_read(struct dso *dso, struct machine *machine,
- {
-       ssize_t ret;
--      pthread_mutex_lock(&dso__data_open_lock);
-+      mutex_lock(dso__data_open_lock());
-       /*
-        * dso__data(dso)->fd might be closed if other thread opened another
-@@ -967,7 +988,7 @@ static ssize_t file_read(struct dso *dso, struct machine *machine,
-       ret = pread(dso__data(dso)->fd, data, DSO__DATA_CACHE_SIZE, offset);
- out:
--      pthread_mutex_unlock(&dso__data_open_lock);
-+      mutex_unlock(dso__data_open_lock());
-       return ret;
- }
-@@ -1075,7 +1096,7 @@ static int file_size(struct dso *dso, struct machine *machine)
-       struct stat st;
-       char sbuf[STRERR_BUFSIZE];
--      pthread_mutex_lock(&dso__data_open_lock);
-+      mutex_lock(dso__data_open_lock());
-       /*
-        * dso__data(dso)->fd might be closed if other thread opened another
-@@ -1099,7 +1120,7 @@ static int file_size(struct dso *dso, struct machine *machine)
-       dso__data(dso)->file_size = st.st_size;
- out:
--      pthread_mutex_unlock(&dso__data_open_lock);
-+      mutex_unlock(dso__data_open_lock());
-       return ret;
- }
-@@ -1608,11 +1629,10 @@ size_t dso__fprintf(struct dso *dso, FILE *fp)
- enum dso_type dso__type(struct dso *dso, struct machine *machine)
- {
--      int fd;
-+      int fd = -1;
-       enum dso_type type = DSO__TYPE_UNKNOWN;
--      fd = dso__data_get_fd(dso, machine);
--      if (fd >= 0) {
-+      if (dso__data_get_fd(dso, machine, &fd)) {
-               type = dso__type_fd(fd);
-               dso__data_put_fd(dso);
-       }
-diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
-index c0472a41147c3c..53eac48fd0cd81 100644
---- a/tools/perf/util/dso.h
-+++ b/tools/perf/util/dso.h
-@@ -231,6 +231,8 @@ DECLARE_RC_STRUCT(dso) {
-       char             name[];
- };
-+extern struct mutex _dso__data_open_lock;
-+
- /* dso__for_each_symbol - iterate over the symbols of given type
-  *
-  * @dso: the 'struct dso *' in which symbols are iterated
-@@ -652,7 +654,7 @@ void __dso__inject_id(struct dso *dso, const struct dso_id *id);
- int dso__name_len(const struct dso *dso);
- struct dso *dso__get(struct dso *dso);
--void dso__put(struct dso *dso);
-+void dso__put(struct dso *dso) LOCKS_EXCLUDED(_dso__data_open_lock);
- static inline void __dso__zput(struct dso **dso)
- {
-@@ -732,8 +734,8 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
-  * The current usage of the dso__data_* interface is as follows:
-  *
-  * Get DSO's fd:
-- *   int fd = dso__data_get_fd(dso, machine);
-- *   if (fd >= 0) {
-+ *   int fd;
-+ *   if (dso__data_get_fd(dso, machine, &fd)) {
-  *       USE 'fd' SOMEHOW
-  *       dso__data_put_fd(dso);
-  *   }
-@@ -755,9 +757,10 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m,
-  *
-  * TODO
- */
--int dso__data_get_fd(struct dso *dso, struct machine *machine);
--void dso__data_put_fd(struct dso *dso);
--void dso__data_close(struct dso *dso);
-+bool dso__data_get_fd(struct dso *dso, struct machine *machine, int *fd)
-+      EXCLUSIVE_TRYLOCK_FUNCTION(true, _dso__data_open_lock);
-+void dso__data_put_fd(struct dso *dso) UNLOCK_FUNCTION(_dso__data_open_lock);
-+void dso__data_close(struct dso *dso) LOCKS_EXCLUDED(_dso__data_open_lock);
- int dso__data_file_size(struct dso *dso, struct machine *machine);
- off_t dso__data_size(struct dso *dso, struct machine *machine);
-diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
-index 16c2b03831f39a..4c076eba86226c 100644
---- a/tools/perf/util/unwind-libunwind-local.c
-+++ b/tools/perf/util/unwind-libunwind-local.c
-@@ -330,8 +330,7 @@ static int read_unwind_spec_eh_frame(struct dso *dso, struct unwind_info *ui,
-       int ret, fd;
-       if (dso__data(dso)->eh_frame_hdr_offset == 0) {
--              fd = dso__data_get_fd(dso, ui->machine);
--              if (fd < 0)
-+              if (!dso__data_get_fd(dso, ui->machine, &fd))
-                       return -EINVAL;
-               /* Check the .eh_frame section for unwinding info */
-@@ -372,8 +371,7 @@ static int read_unwind_spec_debug_frame(struct dso *dso,
-        *    has to be pointed by symsrc_filename
-        */
-       if (ofs == 0) {
--              fd = dso__data_get_fd(dso, machine);
--              if (fd >= 0) {
-+              if (dso__data_get_fd(dso, machine, &fd) {
-                       ofs = elf_section_offset(fd, ".debug_frame");
-                       dso__data_put_fd(dso);
-               }
-@@ -485,14 +483,16 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
-       /* Check the .debug_frame section for unwinding info */
-       if (ret < 0 &&
-           !read_unwind_spec_debug_frame(dso, ui->machine, &segbase)) {
--              int fd = dso__data_get_fd(dso, ui->machine);
--              int is_exec = elf_is_exec(fd, dso__name(dso));
-+              int fd;
-               u64 start = map__start(map);
--              unw_word_t base = is_exec ? 0 : start;
-+              unw_word_t base = start;
-               const char *symfile;
--              if (fd >= 0)
-+              if (dso__data_get_fd(dso, ui->machine, &fd)) {
-+                      if (elf_is_exec(fd, dso__name(dso)))
-+                              base = 0;
-                       dso__data_put_fd(dso);
-+              }
-               symfile = dso__symsrc_filename(dso) ?: dso__name(dso);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-header-sanity-check-header_event_desc-attr.size.patch b/queue-6.12/perf-header-sanity-check-header_event_desc-attr.size.patch
deleted file mode 100644 (file)
index 69fbef0..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-From 74a5f7a871a93ad8a713e5dc3674dea340ebb385 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 2 May 2026 14:37:39 -0300
-Subject: perf header: Sanity check HEADER_EVENT_DESC attr.size before swap
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 944f65c8b8231d26d4db6be67bcb641142603cb4 ]
-
-read_event_desc() reads nre (event count), sz (attr size), and nr
-(IDs per event) from the file and uses them to control allocations
-and loops without validating them against the section size.
-
-A crafted perf.data could trigger large allocations or many loop
-iterations before __do_read() eventually rejects the reads.
-
-Add bounds checks in read_event_desc():
-- Reject sz smaller than PERF_ATTR_SIZE_VER0.
-- Require at least one event (nre > 0).
-- Check that nre events fit in the remaining section, using the
-  minimum per-event footprint of sz + sizeof(u32).
-- Pre-swap attr->size to native byte order, then reject values
-  below PERF_ATTR_SIZE_VER0 or above sz before calling
-  perf_event__attr_swap() to prevent heap out-of-bounds access.
-- Handle ABI0 (attr.size == 0): substitute PERF_ATTR_SIZE_VER0,
-  and on native-endian files write the value back so
-  free_event_desc() does not treat the zero as its end-of-array
-  sentinel (it iterates while attr.size != 0).  The swap path
-  skips the write-back â€” perf_event__attr_swap() has its own
-  ABI0 fallback that sets VER0 after swapping.
-- Check that nr IDs fit in the remaining section before allocating.
-
-Fixes: b30b61729246 ("perf tools: Fix a problem when opening old perf.data with different byte order")
-Reported-by: sashiko-bot@kernel.org # Running on a local machine
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Wang Nan <wangnan0@huawei.com>
-Assisted-by: Claude:claude-opus-4.6-1m
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/header.c | 54 ++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 54 insertions(+)
-
-diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
-index 7b99f58f7bf269..8c15ce90466997 100644
---- a/tools/perf/util/header.c
-+++ b/tools/perf/util/header.c
-@@ -1940,9 +1940,28 @@ static struct evsel *read_event_desc(struct feat_fd *ff)
-       if (do_read_u32(ff, &nre))
-               goto error;
-+      /* Size of each of the nre attributes. */
-       if (do_read_u32(ff, &sz))
-               goto error;
-+      /*
-+       * Require at least one event with an attr no smaller than the
-+       * first published struct, and reject sz values where
-+       * sz + sizeof(u32) would overflow size_t (possible on 32-bit)
-+       * or nre == UINT32_MAX where nre + 1 wraps to 0 in the calloc.
-+       *
-+       * The minimum section footprint per event is sz bytes for the
-+       * attr plus a u32 for the id count, check that nre events fit.
-+       */
-+      if (!nre || sz < PERF_ATTR_SIZE_VER0 ||
-+          sz > ff->size || (size_t)sz > SIZE_MAX - sizeof(u32) ||
-+          nre == UINT32_MAX ||
-+          nre > (ff->size - ff->offset) / (sz + sizeof(u32))) {
-+              pr_err("Invalid HEADER_EVENT_DESC: nre=%u sz=%u (min %d)\n",
-+                     nre, sz, PERF_ATTR_SIZE_VER0);
-+              goto error;
-+      }
-+
-       /* buffer to hold on file attr struct */
-       buf = malloc(sz);
-       if (!buf)
-@@ -1958,6 +1977,9 @@ static struct evsel *read_event_desc(struct feat_fd *ff)
-               msz = sz;
-       for (i = 0, evsel = events; i < nre; evsel++, i++) {
-+              struct perf_event_attr *attr = buf;
-+              u32 attr_size;
-+
-               evsel->core.idx = i;
-               /*
-@@ -1967,6 +1989,32 @@ static struct evsel *read_event_desc(struct feat_fd *ff)
-               if (__do_read(ff, buf, sz))
-                       goto error;
-+              /* Reject before attr_swap to prevent OOB via bswap_safe() */
-+              attr_size = ff->ph->needs_swap ? bswap_32(attr->size) : attr->size;
-+              /* ABI0: size == 0 means the producer didn't set it */
-+              if (!attr_size) {
-+                      attr_size = PERF_ATTR_SIZE_VER0;
-+                      /*
-+                       * Write back so free_event_desc() doesn't
-+                       * treat this event as the end-of-array sentinel
-+                       * (it iterates while attr.size != 0).
-+                       *
-+                       * Only for native â€” the swap path must NOT
-+                       * write native-endian VER0 here because
-+                       * perf_event__attr_swap() would re-swap it
-+                       * to 0x40000000, defeating bswap_safe() bounds.
-+                       * perf_event__attr_swap() has its own ABI0
-+                       * fallback that sets VER0 after swapping.
-+                       */
-+                      if (!ff->ph->needs_swap)
-+                              attr->size = attr_size;
-+              }
-+              if (attr_size < PERF_ATTR_SIZE_VER0 || attr_size > sz) {
-+                      pr_err("Event %d attr.size (%u) invalid (min: %d, max: %u)\n",
-+                             i, attr_size, PERF_ATTR_SIZE_VER0, sz);
-+                      goto error;
-+              }
-+
-               if (ff->ph->needs_swap)
-                       perf_event__attr_swap(buf);
-@@ -1988,6 +2036,12 @@ static struct evsel *read_event_desc(struct feat_fd *ff)
-               if (!nr)
-                       continue;
-+              /* Prevent oversized allocation from crafted nr */
-+              if (nr > (ff->size - ff->offset) / sizeof(*id)) {
-+                      pr_err("Event %d: id count %u exceeds remaining section\n", i, nr);
-+                      goto error;
-+              }
-+
-               id = calloc(nr, sizeof(*id));
-               if (!id)
-                       goto error;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch b/queue-6.12/perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch
deleted file mode 100644 (file)
index 1b3c059..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 6da2b221ce3fa75964b2932e94385d3057641443 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 14:35:28 -0300
-Subject: perf hists: Fix snprintf() in hists__scnprintf_title() UID filter
- path
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 227a8748742f0263f1fe3131449b44563b77a209 ]
-
-hists__scnprintf_title() accumulates formatted output into a buffer
-using scnprintf() for all filter clauses except the UID filter, which
-uses snprintf().  If the buffer fills up and snprintf() returns more
-than the remaining space, printed exceeds size and the next 'size -
-printed' underflows, causing later scnprintf() calls to write past
-the buffer.
-
-Switch the UID filter clause to scnprintf() to match the rest of the
-function.
-
-Fixes: 25c312dbf88ca402 ("perf hists: Move hists__scnprintf_title() away from the TUI code")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/hist.c | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
-index 694faf405e11cf..299bfca446a698 100644
---- a/tools/perf/util/hist.c
-+++ b/tools/perf/util/hist.c
-@@ -2816,9 +2816,10 @@ int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool sh
-                          ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
--      if (hists->uid_filter_str)
--              printed += snprintf(bf + printed, size - printed,
--                                  ", UID: %s", hists->uid_filter_str);
-+      if (hists->uid_filter_str) {
-+              printed += scnprintf(bf + printed, size - printed,
-+                                   ", UID: %s", hists->uid_filter_str);
-+      }
-       if (thread) {
-               if (hists__has(hists, thread)) {
-                       printed += scnprintf(bf + printed, size - printed,
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-inject-add-convert-callchain-option.patch b/queue-6.12/perf-inject-add-convert-callchain-option.patch
deleted file mode 100644 (file)
index 658a581..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-From b386345dedddd6b741c541fa75444d7e1ad04de8 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 13 Jan 2026 15:29:02 -0800
-Subject: perf inject: Add --convert-callchain option
-
-From: Namhyung Kim <namhyung@kernel.org>
-
-[ Upstream commit 92ea788d2af4e65ad7a144ccfff50667e9a0d227 ]
-
-There are applications not built with frame pointers, so DWARF is needed
-to get the stack traces.
-
-`perf record --call-graph dwarf` saves the stack and register data for
-each sample to get the stacktrace offline.  But sometimes this data may
-have sensitive information and we don't want to keep them in the file.
-
-This new 'perf inject --convert-callchain' option creates the callchains
-and discards the stack and register after that.
-
-This saves storage space and processing time for the new data file.
-
-Of course, users should remove the original data file to not keep
-sensitive data around.  :)
-
-The down side is that it cannot handle inlined callchain entries as they
-all have the same IPs.
-
-Maybe we can add an option to 'perf report' to look up inlined functions
-using DWARF - IIUC it doesn't require stack and register data.
-
-This is an example.
-
-  $ perf record --call-graph dwarf -- perf test -w noploop
-
-  $ perf report --stdio --no-children --percent-limit=0 > output-prev
-
-  $ perf inject -i perf.data --convert-callchain -o perf.data.out
-
-  $ perf report --stdio --no-children --percent-limit=0 -i perf.data.out > output-next
-
-  $ diff -u output-prev output-next
-  ...
-        0.23%  perf          ld-linux-x86-64.so.2  [.] _dl_relocate_object_no_relro
-               |
-  -            ---elf_dynamic_do_Rela (inlined)
-  -               _dl_relocate_object_no_relro
-  +            ---_dl_relocate_object_no_relro
-                  _dl_relocate_object
-                  dl_main
-                  _dl_sysdep_start
-  -               _dl_start_final (inlined)
-                  _dl_start
-                  _start
-
-Reviewed-by: Ian Rogers <irogers@google.com>
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Ingo Molnar <mingo@kernel.org>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Stable-dep-of: 059e9100d82a ("perf event: Fix size of synthesized sample with branch stacks")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/Documentation/perf-inject.txt |   5 +
- tools/perf/builtin-inject.c              | 152 +++++++++++++++++++++++
- 2 files changed, 157 insertions(+)
-
-diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
-index c972032f4ca0d2..95dfdf39666efe 100644
---- a/tools/perf/Documentation/perf-inject.txt
-+++ b/tools/perf/Documentation/perf-inject.txt
-@@ -109,6 +109,11 @@ include::itrace.txt[]
-       should be used, and also --buildid-all and --switch-events may be
-       useful.
-+--convert-callchain::
-+      Parse DWARF callchains and convert them to usual callchains.  This also
-+      discards stack and register data from the samples.  This will lose
-+      inlined callchain entries.
-+
- :GMEXAMPLECMD: inject
- :GMEXAMPLESUBCMD:
- include::guestmount.txt[]
-diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
-index 11e49cafa3af9d..241d7e36914872 100644
---- a/tools/perf/builtin-inject.c
-+++ b/tools/perf/builtin-inject.c
-@@ -122,6 +122,7 @@ struct perf_inject {
-       bool                    in_place_update;
-       bool                    in_place_update_dry_run;
-       bool                    copy_kcore_dir;
-+      bool                    convert_callchain;
-       const char              *input_name;
-       struct perf_data        output;
-       u64                     bytes_written;
-@@ -133,6 +134,7 @@ struct perf_inject {
-       struct guest_session    guest_session;
-       struct strlist          *known_build_ids;
-       const struct evsel      *mmap_evsel;
-+      struct ip_callchain     *raw_callchain;
- };
- struct event_entry {
-@@ -396,6 +398,90 @@ static int perf_event__repipe_sample(const struct perf_tool *tool,
-       return perf_event__repipe_synth(tool, event);
- }
-+static int perf_event__convert_sample_callchain(const struct perf_tool *tool,
-+                                              union perf_event *event,
-+                                              struct perf_sample *sample,
-+                                              struct evsel *evsel,
-+                                              struct machine *machine)
-+{
-+      struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
-+      struct callchain_cursor *cursor = get_tls_callchain_cursor();
-+      union perf_event *event_copy = (void *)inject->event_copy;
-+      struct callchain_cursor_node *node;
-+      struct thread *thread;
-+      u64 sample_type = evsel->core.attr.sample_type;
-+      u32 sample_size = event->header.size;
-+      u64 i, k;
-+      int ret;
-+
-+      if (event_copy == NULL) {
-+              inject->event_copy = malloc(PERF_SAMPLE_MAX_SIZE);
-+              if (!inject->event_copy)
-+                      return -ENOMEM;
-+
-+              event_copy = (void *)inject->event_copy;
-+      }
-+
-+      if (cursor == NULL)
-+              return -ENOMEM;
-+
-+      callchain_cursor_reset(cursor);
-+
-+      thread = machine__find_thread(machine, sample->tid, sample->pid);
-+      if (thread == NULL)
-+              goto out;
-+
-+      /* this will parse DWARF using stack and register data */
-+      ret = thread__resolve_callchain(thread, cursor, evsel, sample,
-+                                      /*parent=*/NULL, /*root_al=*/NULL,
-+                                      PERF_MAX_STACK_DEPTH);
-+      thread__put(thread);
-+      if (ret != 0)
-+              goto out;
-+
-+      /* copy kernel callchain and context entries */
-+      for (i = 0; i < sample->callchain->nr; i++) {
-+              inject->raw_callchain->ips[i] = sample->callchain->ips[i];
-+              if (sample->callchain->ips[i] == PERF_CONTEXT_USER) {
-+                      i++;
-+                      break;
-+              }
-+      }
-+      if (i == 0 || inject->raw_callchain->ips[i - 1] != PERF_CONTEXT_USER)
-+              inject->raw_callchain->ips[i++] = PERF_CONTEXT_USER;
-+
-+      node = cursor->first;
-+      for (k = 0; k < cursor->nr && i < PERF_MAX_STACK_DEPTH; k++) {
-+              if (machine__kernel_ip(machine, node->ip))
-+                      /* kernel IPs were added already */;
-+              else if (node->ms.sym && node->ms.sym->inlined)
-+                      /* we can't handle inlined callchains */;
-+              else
-+                      inject->raw_callchain->ips[i++] = node->ip;
-+
-+              node = node->next;
-+      }
-+
-+      inject->raw_callchain->nr = i;
-+      sample->callchain = inject->raw_callchain;
-+
-+out:
-+      memcpy(event_copy, event, sizeof(event->header));
-+
-+      /* adjust sample size for stack and regs */
-+      sample_size -= sample->user_stack.size;
-+      sample_size -= (hweight64(evsel->core.attr.sample_regs_user) + 1) * sizeof(u64);
-+      sample_size += (sample->callchain->nr + 1) * sizeof(u64);
-+      event_copy->header.size = sample_size;
-+
-+      /* remove sample_type {STACK,REGS}_USER for synthesize */
-+      sample_type &= ~(PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER);
-+
-+      perf_event__synthesize_sample(event_copy, sample_type,
-+                                    evsel->core.attr.read_format, sample);
-+      return perf_event__repipe_synth(tool, event_copy);
-+}
-+
- static struct dso *findnew_dso(int pid, int tid, const char *filename,
-                              const struct dso_id *id, struct machine *machine)
- {
-@@ -2274,6 +2360,15 @@ static int __cmd_inject(struct perf_inject *inject)
-               /* Allow space in the header for guest attributes */
-               output_data_offset += gs->session->header.data_offset;
-               output_data_offset = roundup(output_data_offset, 4096);
-+      } else if (inject->convert_callchain) {
-+              inject->tool.sample     = perf_event__convert_sample_callchain;
-+              inject->tool.fork       = perf_event__repipe_fork;
-+              inject->tool.comm       = perf_event__repipe_comm;
-+              inject->tool.exit       = perf_event__repipe_exit;
-+              inject->tool.mmap       = perf_event__repipe_mmap;
-+              inject->tool.mmap2      = perf_event__repipe_mmap2;
-+              inject->tool.ordered_events = true;
-+              inject->tool.ordering_requires_timestamps = true;
-       }
-       if (!inject->itrace_synth_opts.set)
-@@ -2326,6 +2421,23 @@ static int __cmd_inject(struct perf_inject *inject)
-                               perf_header__set_feat(&session->header,
-                                                     HEADER_BRANCH_STACK);
-               }
-+
-+              /*
-+               * The converted data file won't have stack and registers.
-+               * Update the perf_event_attr to remove them before writing.
-+               */
-+              if (inject->convert_callchain) {
-+                      struct evsel *evsel;
-+
-+                      evlist__for_each_entry(session->evlist, evsel) {
-+                              evsel__reset_sample_bit(evsel, REGS_USER);
-+                              evsel__reset_sample_bit(evsel, STACK_USER);
-+                              evsel->core.attr.sample_regs_user = 0;
-+                              evsel->core.attr.sample_stack_user = 0;
-+                              evsel->core.attr.exclude_callchain_user = 0;
-+                      }
-+              }
-+
-               session->header.data_offset = output_data_offset;
-               session->header.data_size = inject->bytes_written;
-               perf_session__inject_header(session, session->evlist, fd, &inj_fc.fc,
-@@ -2350,6 +2462,18 @@ static int __cmd_inject(struct perf_inject *inject)
-       return ret;
- }
-+static bool evsel__has_dwarf_callchain(struct evsel *evsel)
-+{
-+      struct perf_event_attr *attr = &evsel->core.attr;
-+      const u64 dwarf_callchain_flags =
-+              PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_CALLCHAIN;
-+
-+      if (!attr->exclude_callchain_user)
-+              return false;
-+
-+      return (attr->sample_type & dwarf_callchain_flags) == dwarf_callchain_flags;
-+}
-+
- int cmd_inject(int argc, const char **argv)
- {
-       struct perf_inject inject = {
-@@ -2418,6 +2542,8 @@ int cmd_inject(int argc, const char **argv)
-               OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
-                          "guest mount directory under which every guest os"
-                          " instance has a subdir"),
-+              OPT_BOOLEAN(0, "convert-callchain", &inject.convert_callchain,
-+                          "Generate callchains using DWARF and drop register/stack data"),
-               OPT_END()
-       };
-       const char * const inject_usage[] = {
-@@ -2433,6 +2559,9 @@ int cmd_inject(int argc, const char **argv)
- #ifndef HAVE_JITDUMP
-       set_option_nobuild(options, 'j', "jit", "NO_LIBELF=1", true);
-+#endif
-+#ifndef HAVE_LIBDW_SUPPORT
-+      set_option_nobuild(options, 0, "convert-callchain", "NO_LIBDW=1", true);
- #endif
-       argc = parse_options(argc, argv, options, inject_usage, 0);
-@@ -2589,6 +2718,28 @@ int cmd_inject(int argc, const char **argv)
-               }
-       }
-+      if (inject.convert_callchain) {
-+              struct evsel *evsel;
-+
-+              if (inject.output.is_pipe || inject.session->data->is_pipe) {
-+                      pr_err("--convert-callchain cannot work with pipe\n");
-+                      goto out_delete;
-+              }
-+
-+              evlist__for_each_entry(inject.session->evlist, evsel) {
-+                      if (!evsel__has_dwarf_callchain(evsel)) {
-+                              pr_err("--convert-callchain requires DWARF call graph.\n");
-+                              goto out_delete;
-+                      }
-+              }
-+
-+              inject.raw_callchain = calloc(PERF_MAX_STACK_DEPTH, sizeof(u64));
-+              if (inject.raw_callchain == NULL) {
-+                      pr_err("callchain allocation failed\n");
-+                      goto out_delete;
-+              }
-+      }
-+
- #ifdef HAVE_JITDUMP
-       if (inject.jit_mode) {
-               inject.tool.mmap2          = perf_event__repipe_mmap2;
-@@ -2619,5 +2770,6 @@ int cmd_inject(int argc, const char **argv)
-       free(inject.itrace_synth_opts.vm_tm_corr_args);
-       free(inject.event_copy);
-       free(inject.guest_session.ev.event_buf);
-+      free(inject.raw_callchain);
-       return ret;
- }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-inject-with-convert-callchain-ignore-the-dummy-event-for-dwarf-stacks.patch b/queue-6.12/perf-inject-with-convert-callchain-ignore-the-dummy-event-for-dwarf-stacks.patch
deleted file mode 100644 (file)
index a6216de..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From e786a04b4a5461dd7e2829422314a5a6d5a664d9 Mon Sep 17 00:00:00 2001
-From: Ian Rogers <irogers@google.com>
-Date: Thu, 22 Jan 2026 09:58:46 -0800
-Subject: perf inject: With --convert-callchain ignore the dummy event for dwarf stacks
-
-From: Ian Rogers <irogers@google.com>
-
-commit e786a04b4a5461dd7e2829422314a5a6d5a664d9 upstream.
-
-On hybrid systems there is generally >1 event and a dummy event.
-
-The perf inject --convert-callchain option is failing to convert
-perf.data files on such systems reporting "--convert-callchain requires
-DWARF call graph."
-
-The failing event is the dummy event that doesn't need to be set up for
-samples.
-
-As such ignore this event when checking the evsels.
-
-Fixes: 92ea788d2af4e65a ("perf inject: Add --convert-callchain option")
-Signed-off-by: Ian Rogers <irogers@google.com>
-Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/builtin-inject.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/tools/perf/builtin-inject.c
-+++ b/tools/perf/builtin-inject.c
-@@ -2733,7 +2733,7 @@ int cmd_inject(int argc, const char **ar
-               }
-               evlist__for_each_entry(inject.session->evlist, evsel) {
--                      if (!evsel__has_dwarf_callchain(evsel)) {
-+                      if (!evsel__has_dwarf_callchain(evsel) && !evsel__is_dummy_event(evsel)) {
-                               pr_err("--convert-callchain requires DWARF call graph.\n");
-                               goto out_delete;
-                       }
diff --git a/queue-6.12/perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch b/queue-6.12/perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch
deleted file mode 100644 (file)
index 41417e8..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From 552413aaffba1685e9586d523da9030f028f221b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 21:06:54 -0300
-Subject: perf intel-pt: Fix snprintf size tracking bug in insn decoder
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit b6bb3b005dcdd960b8e0b7f9d6869132b3de08d5 ]
-
-dump_insn() tracks remaining buffer space with a 'left' variable,
-but the loop subtracts the cumulative offset 'n' each iteration
-instead of just the per-iteration delta:
-
-    n += snprintf(x->out + n, left, "%02x ", inbuf[i]);
-    left -= n;  /* BUG: n is cumulative, not the delta */
-
-After two iterations left goes massively negative, wrapping to a
-huge value when passed as size_t to snprintf(), disabling all bounds
-checking for the rest of the loop.
-
-Switch to scnprintf() accumulation using sizeof(x->out) - n as the
-remaining space, which is always correct and eliminates the separate
-'left' variable entirely.
-
-Fixes: 48d02a1d5c137d36 ("perf script: Add 'brstackinsn' for branch stacks")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Andi Kleen <ak@linux.intel.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- .../util/intel-pt-decoder/intel-pt-insn-decoder.c     | 11 +++--------
- 1 file changed, 3 insertions(+), 8 deletions(-)
-
-diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
-index 47cf35799a4dfc..8cd0c31e2b936a 100644
---- a/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
-+++ b/tools/perf/util/intel-pt-decoder/intel-pt-insn-decoder.c
-@@ -223,7 +223,6 @@ const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
- {
-       struct insn insn;
-       int n, i, ret;
--      int left;
-       ret = insn_decode(&insn, inbuf, inlen,
-                         x->is64bit ? INSN_MODE_64 : INSN_MODE_32);
-@@ -232,13 +231,9 @@ const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused,
-               return "<bad>";
-       if (lenp)
-               *lenp = insn.length;
--      left = sizeof(x->out);
--      n = snprintf(x->out, left, "insn: ");
--      left -= n;
--      for (i = 0; i < insn.length; i++) {
--              n += snprintf(x->out + n, left, "%02x ", inbuf[i]);
--              left -= n;
--      }
-+      n = scnprintf(x->out, sizeof(x->out), "insn: ");
-+      for (i = 0; i < insn.length; i++)
-+              n += scnprintf(x->out + n, sizeof(x->out) - n, "%02x ", inbuf[i]);
-       return x->out;
- }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-libunwind-arm64-fix-missing-close-parens-in-an-if-statement.patch b/queue-6.12/perf-libunwind-arm64-fix-missing-close-parens-in-an-if-statement.patch
deleted file mode 100644 (file)
index 796608c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-From 1293dacbbd43ab9848ac4655f6f2ba1dcc5a96ad Mon Sep 17 00:00:00 2001
-From: Arnaldo Carvalho de Melo <acme@kernel.org>
-Date: Wed, 9 Apr 2025 10:35:31 -0300
-Subject: perf libunwind arm64: Fix missing close parens in an if statement
-
-From: Arnaldo Carvalho de Melo <acme@kernel.org>
-
-commit 1293dacbbd43ab9848ac4655f6f2ba1dcc5a96ad upstream.
-
-While testing building with libunwind (using LIBUNWIND=1) in various
-arches I noticed a problem on arm64, on an rpi5 system, a missing close
-parens in a change related to dso__data_get_fd() usage, fix it.
-
-Fixes: 5ac22c35aa8519f1 ("perf dso: Use lock annotations to fix asan deadlock")
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Link: https://lore.kernel.org/r/Z_Z3o8KvB2i5c6ab@x1
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/util/unwind-libunwind-local.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/tools/perf/util/unwind-libunwind-local.c
-+++ b/tools/perf/util/unwind-libunwind-local.c
-@@ -371,7 +371,7 @@ static int read_unwind_spec_debug_frame(
-        *    has to be pointed by symsrc_filename
-        */
-       if (ofs == 0) {
--              if (dso__data_get_fd(dso, machine, &fd) {
-+              if (dso__data_get_fd(dso, machine, &fd)) {
-                       ofs = elf_section_offset(fd, ".debug_frame");
-                       dso__data_put_fd(dso);
-               }
diff --git a/queue-6.12/perf-machine-use-snprintf-for-guestmount-path-constr.patch b/queue-6.12/perf-machine-use-snprintf-for-guestmount-path-constr.patch
deleted file mode 100644 (file)
index 46f760b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 97c215b8b1ecb9d11b3fdf20742eb525b27da551 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 13 Jun 2026 13:59:39 -0300
-Subject: perf machine: Use snprintf() for guestmount path construction
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit fe63d3bca288c5bb983304efd5fc3a5ff3183403 ]
-
-machines__findnew() and machines__create_guest_kernel_maps() use
-sprintf() to build paths by prepending symbol_conf.guestmount.
-Both write into PATH_MAX stack buffers, but guestmount comes from
-user configuration and is not length-checked.  A guestmount path
-at or near PATH_MAX causes a stack buffer overflow.
-
-Switch to snprintf() with sizeof() to prevent overflow.  The
-subsequent access()/fopen() calls will fail on a truncated path.
-
-Fixes: a1645ce12adb6c9c ("perf: 'perf kvm' tool for monitoring guest performance from host")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Zhang, Yanmin <yanmin_zhang@linux.intel.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/machine.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
-index 71d3d034ba095e..b1817634996964 100644
---- a/tools/perf/util/machine.c
-+++ b/tools/perf/util/machine.c
-@@ -289,7 +289,7 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid)
-       if ((pid != HOST_KERNEL_ID) &&
-           (pid != DEFAULT_GUEST_KERNEL_ID) &&
-           (symbol_conf.guestmount)) {
--              sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
-+              snprintf(path, sizeof(path), "%s/%d", symbol_conf.guestmount, pid);
-               if (access(path, R_OK)) {
-                       static struct strlist *seen;
-@@ -1214,9 +1214,9 @@ int machines__create_guest_kernel_maps(struct machines *machines)
-                                        namelist[i]->d_name);
-                               continue;
-                       }
--                      sprintf(path, "%s/%s/proc/kallsyms",
--                              symbol_conf.guestmount,
--                              namelist[i]->d_name);
-+                      snprintf(path, sizeof(path), "%s/%s/proc/kallsyms",
-+                               symbol_conf.guestmount,
-+                               namelist[i]->d_name);
-                       ret = access(path, R_OK);
-                       if (ret) {
-                               pr_debug("Can't access file %s\n", path);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-maps-add-maps__mutate_mapping.patch b/queue-6.12/perf-maps-add-maps__mutate_mapping.patch
deleted file mode 100644 (file)
index 95c0b5d..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-From 2468f12df21a946eec5d1654a289cda9cb90e6b9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 11 Jun 2026 09:41:18 -0700
-Subject: perf maps: Add maps__mutate_mapping
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit 75a4888b7029a1f98613aef91f517b2ee1f03d43 ]
-
-During kernel ELF symbol parsing (dso__process_kernel_symbol), proc
-kallsyms image loading (dso__load_kernel_sym,
-dso__load_guest_kernel_sym), and dynamic kernel memory map alignment
-updates (machine__update_kernel_mmap), the loader directly modifies live
-virtual address boundary keys fields on map objects.
-
-If these boundaries are mutated while the map pointer actively resides
-inside the parent maps cache array list (kmaps) outside of any lock
-closure, an unsafe concurrent window is exposed where parallel worker
-lookup threads (e.g., inside perf top) can mistakenly assume the cache
-remains sorted based on stale parameters, executing binary search
-queries (bsearch) across an unsorted range and triggering lookup
-failures.
-
-Fix this by introducing maps__mutate_mapping() that explicitly acquires
-the parent maps write semaphore lock, executes an incoming mutation
-callback block to perform the field updates under lock protection, and
-invalidates the sorted tracking flags prior to releasing the write lock.
-
-This guarantees synchronization invariants, closing the concurrent
-lookup race window. The adjacent module alignment pass inside
-machine__create_kernel_maps() is safely preserved as a high-performance
-lockless pass, as its invocation lifecycle bounds remain strictly
-single-threaded by contract during session initialization construction.
-
-To safely support this unconditional down_write write lock mutator
-without recursive read-to-write self-deadlock upgrades during lazy
-symbol loading, we introduce a public maps__load_maps() API.
-
-It copies map pointers under a brief read lock and force-loads all
-modules locklessly outside the lock. Callers (such as perf inject) must
-pre-load all kernel symbol maps up front at startup using
-maps__load_maps(), completely bypassing dynamic runtime mutations.
-
-Fixes: 39b12f781271 ("perf tools: Make it possible to read object code from vmlinux")
-
-Assisted-by: Antigravity:gemini-3.1-pro
-Signed-off-by: Ian Rogers <irogers@google.com>
-Tested-by: James Clark <james.clark@linaro.org>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Gabriel Marin <gmx@google.com>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/machine.c    |  32 +++++---
- tools/perf/util/maps.c       | 148 ++++++++++++++++++++++++++++-------
- tools/perf/util/maps.h       |   3 +
- tools/perf/util/symbol-elf.c |  41 ++++++----
- tools/perf/util/symbol.c     |  17 +++-
- 5 files changed, 183 insertions(+), 58 deletions(-)
-
-diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
-index 06a168ce5d9044..557853fcb5479b 100644
---- a/tools/perf/util/machine.c
-+++ b/tools/perf/util/machine.c
-@@ -1489,22 +1489,30 @@ static void machine__set_kernel_mmap(struct machine *machine,
-               map__set_end(machine->vmlinux_map, ~0ULL);
- }
--static int machine__update_kernel_mmap(struct machine *machine,
--                                   u64 start, u64 end)
-+struct kernel_mmap_mutation_ctx {
-+      u64 start;
-+      u64 end;
-+};
-+
-+static int kernel_mmap_mutate_cb(struct map *map, void *data)
- {
--      struct map *orig, *updated;
--      int err;
-+      struct kernel_mmap_mutation_ctx *ctx = data;
--      orig = machine->vmlinux_map;
--      updated = map__get(orig);
-+      map__set_start(map, ctx->start);
-+      map__set_end(map, ctx->end);
-+      if (ctx->start == 0 && ctx->end == 0)
-+              map__set_end(map, ~0ULL);
-+      return 0;
-+}
--      machine->vmlinux_map = updated;
--      maps__remove(machine__kernel_maps(machine), orig);
--      machine__set_kernel_mmap(machine, start, end);
--      err = maps__insert(machine__kernel_maps(machine), updated);
--      map__put(orig);
-+static int machine__update_kernel_mmap(struct machine *machine,
-+                                     u64 start, u64 end)
-+{
-+      struct kernel_mmap_mutation_ctx ctx = { .start = start, .end = end };
--      return err;
-+      return maps__mutate_mapping(machine__kernel_maps(machine),
-+                                   machine->vmlinux_map,
-+                                   kernel_mmap_mutate_cb, &ctx);
- }
- int machine__create_kernel_maps(struct machine *machine)
-diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c
-index 7b8f48677c3185..51726d8de2cfd1 100644
---- a/tools/perf/util/maps.c
-+++ b/tools/perf/util/maps.c
-@@ -539,6 +539,48 @@ void maps__remove(struct maps *maps, struct map *map)
-       up_write(maps__lock(maps));
- }
-+/**
-+ * maps__mutate_mapping - Apply write-protected mutations to a map.
-+ * @maps: The maps collection containing the map.
-+ * @map: The map to mutate.
-+ * @mutate_cb: Callback function that performs the actual mutations.
-+ * @data: Private data passed to the callback.
-+ *
-+ * This acquires the write lock on the maps semaphore to safely protect
-+ * concurrent readers from seeing partially mutated or unsorted map boundaries.
-+ *
-+ * WARNING: Acquiring down_write() here can trigger a recursive self-deadlock if
-+ * the caller already holds the read lock (e.g., during maps__for_each_map() or
-+ * maps__find() iteration paths that trigger lazy symbol loading). To completely
-+ * avoid this deadlock, all kernel/module maps must be pre-loaded up-front (via
-+ * maps__load_maps()) under a clean, single-threaded context before entering
-+ * multi-threaded event processing loops.
-+ */
-+int maps__mutate_mapping(struct maps *maps, struct map *map,
-+                       int (*mutate_cb)(struct map *map, void *data), void *data)
-+{
-+      int err = 0;
-+
-+      if (maps) {
-+              down_write(maps__lock(maps));
-+
-+              err = mutate_cb(map, data);
-+
-+              RC_CHK_ACCESS(maps)->maps_by_address_sorted = false;
-+              RC_CHK_ACCESS(maps)->maps_by_name_sorted = false;
-+
-+              up_write(maps__lock(maps));
-+
-+#ifdef HAVE_LIBDW_SUPPORT
-+              libdw__invalidate_dwfl(maps, maps__libdw_addr_space_dwfl(maps));
-+#endif
-+      } else {
-+              err = mutate_cb(map, data);
-+      }
-+
-+      return err;
-+}
-+
- bool maps__empty(struct maps *maps)
- {
-       bool res;
-@@ -589,6 +631,41 @@ int maps__for_each_map(struct maps *maps, int (*cb)(struct map *map, void *data)
-       return ret;
- }
-+int maps__load_maps(struct maps *maps)
-+{
-+      struct map **maps_copy;
-+      unsigned int nr_maps;
-+      int err = 0;
-+
-+      if (!maps)
-+              return 0;
-+
-+      down_read(maps__lock(maps));
-+      nr_maps = maps__nr_maps(maps);
-+      if (nr_maps == 0) {
-+              up_read(maps__lock(maps));
-+              return 0;
-+      }
-+      maps_copy = calloc(nr_maps, sizeof(*maps_copy));
-+      if (!maps_copy) {
-+              up_read(maps__lock(maps));
-+              return -ENOMEM;
-+      }
-+      for (unsigned int i = 0; i < nr_maps; i++)
-+              maps_copy[i] = map__get(maps__maps_by_address(maps)[i]);
-+      up_read(maps__lock(maps));
-+
-+      for (unsigned int i = 0; i < nr_maps; i++) {
-+              if (map__load(maps_copy[i]) < 0) {
-+                      pr_warning("Failed to load map %s\n", dso__name(map__dso(maps_copy[i])));
-+                      err = -1;
-+              }
-+              map__put(maps_copy[i]);
-+      }
-+      free(maps_copy);
-+      return err;
-+}
-+
- void maps__remove_maps(struct maps *maps, bool (*cb)(struct map *map, void *data), void *data)
- {
-       struct map **maps_by_address;
-@@ -623,40 +700,57 @@ struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp)
-       return result;
- }
--struct maps__find_symbol_by_name_args {
--      struct map **mapp;
--      const char *name;
--      struct symbol *sym;
--};
--
--static int maps__find_symbol_by_name_cb(struct map *map, void *data)
-+struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
- {
--      struct maps__find_symbol_by_name_args *args = data;
-+      struct map **maps_copy;
-+      unsigned int nr_maps;
-+      struct symbol *sym = NULL;
--      args->sym = map__find_symbol_by_name(map, args->name);
--      if (!args->sym)
--              return 0;
-+      if (!maps)
-+              return NULL;
--      if (!map__contains_symbol(map, args->sym)) {
--              args->sym = NULL;
--              return 0;
-+      /*
-+       * First, ensure all maps are loaded. We pre-load them outside of any
-+       * read-to-write locks to avoid deadlocks. Even if some fail, we proceed.
-+       */
-+      maps__load_maps(maps);
-+
-+      /*
-+       * Create a local snapshot of the maps while holding the read lock.
-+       * This prevents deadlocking if iteration triggers further map insertions.
-+       */
-+      down_read(maps__lock(maps));
-+      nr_maps = maps__nr_maps(maps);
-+      maps_copy = calloc(nr_maps, sizeof(*maps_copy));
-+      if (maps_copy) {
-+              for (unsigned int i = 0; i < nr_maps; i++) {
-+                      struct map *map = maps__maps_by_address(maps)[i];
-+
-+                      maps_copy[i] = map__get(map);
-+              }
-       }
-+      up_read(maps__lock(maps));
--      if (args->mapp != NULL)
--              *args->mapp = map__get(map);
--      return 1;
--}
-+      if (!maps_copy)
-+              return NULL;
--struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp)
--{
--      struct maps__find_symbol_by_name_args args = {
--              .mapp = mapp,
--              .name = name,
--              .sym = NULL,
--      };
-+      for (unsigned int i = 0; i < nr_maps; i++) {
-+              struct map *map = maps_copy[i];
-+
-+              sym = map__find_symbol_by_name(map, name);
-+              if (sym && map__contains_symbol(map, sym)) {
-+                      if (mapp)
-+                              *mapp = map__get(map);
-+                      break;
-+              }
-+              sym = NULL;
-+      }
-+
-+      for (unsigned int i = 0; i < nr_maps; i++)
-+              map__put(maps_copy[i]);
--      maps__for_each_map(maps, maps__find_symbol_by_name_cb, &args);
--      return args.sym;
-+      free(maps_copy);
-+      return sym;
- }
- int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams)
-diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h
-index d9aa62ed968ac4..df22f8c1b32bd1 100644
---- a/tools/perf/util/maps.h
-+++ b/tools/perf/util/maps.h
-@@ -55,8 +55,11 @@ void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libun
- size_t maps__fprintf(struct maps *maps, FILE *fp);
-+int maps__load_maps(struct maps *maps);
- int maps__insert(struct maps *maps, struct map *map);
- void maps__remove(struct maps *maps, struct map *map);
-+int maps__mutate_mapping(struct maps *maps, struct map *map,
-+                       int (*mutate_cb)(struct map *map, void *data), void *data);
- struct map *maps__find(struct maps *maps, u64 addr);
- struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp);
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index 90f11a6eb19fea..4ba49975970a9b 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -1418,6 +1418,24 @@ static u64 ref_reloc(struct kmap *kmap)
- void __weak arch__sym_update(struct symbol *s __maybe_unused,
-               GElf_Sym *sym __maybe_unused) { }
-+struct remap_kernel_ctx {
-+      u64 sh_addr;
-+      u64 sh_size;
-+      u64 sh_offset;
-+      struct kmap *kmap;
-+};
-+
-+static int remap_kernel_cb(struct map *map, void *data)
-+{
-+      struct remap_kernel_ctx *ctx = data;
-+
-+      map__set_start(map, ctx->sh_addr + ref_reloc(ctx->kmap));
-+      map__set_end(map, map__start(map) + ctx->sh_size);
-+      map__set_pgoff(map, ctx->sh_offset);
-+      map__set_mapping_type(map, MAPPING_TYPE__DSO);
-+      return 0;
-+}
-+
- static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
-                                     GElf_Sym *sym, GElf_Shdr *shdr,
-                                     struct maps *kmaps, struct kmap *kmap,
-@@ -1448,22 +1466,15 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
-                * map to the kernel dso.
-                */
-               if (*remap_kernel && dso__kernel(dso) && !kmodule) {
-+                      struct remap_kernel_ctx ctx = {
-+                              .sh_addr = shdr->sh_addr,
-+                              .sh_size = shdr->sh_size,
-+                              .sh_offset = shdr->sh_offset,
-+                              .kmap = kmap
-+                      };
-+
-                       *remap_kernel = false;
--                      map__set_start(map, shdr->sh_addr + ref_reloc(kmap));
--                      map__set_end(map, map__start(map) + shdr->sh_size);
--                      map__set_pgoff(map, shdr->sh_offset);
--                      map__set_mapping_type(map, MAPPING_TYPE__DSO);
--                      /* Ensure maps are correctly ordered */
--                      if (kmaps) {
--                              int err;
--                              struct map *tmp = map__get(map);
--
--                              maps__remove(kmaps, map);
--                              err = maps__insert(kmaps, map);
--                              map__put(tmp);
--                              if (err)
--                                      return err;
--                      }
-+                      maps__mutate_mapping(kmaps, map, remap_kernel_cb, &ctx);
-               }
-               /*
-diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
-index b1b4a2d4b7e46c..e792dd22b54983 100644
---- a/tools/perf/util/symbol.c
-+++ b/tools/perf/util/symbol.c
-@@ -42,6 +42,13 @@
- #include <symbol/kallsyms.h>
- #include <sys/utsname.h>
-+static int map_fixup_cb(struct map *map, void *data __maybe_unused)
-+{
-+      map__fixup_start(map);
-+      map__fixup_end(map);
-+      return 0;
-+}
-+
- static int dso__load_kernel_sym(struct dso *dso, struct map *map);
- static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map);
- static bool symbol__is_idle(const char *name);
-@@ -2227,10 +2234,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map)
-       free(kallsyms_allocated_filename);
-       if (err > 0 && !dso__is_kcore(dso)) {
-+              struct maps *kmaps = map__kmaps(map);
-+
-               dso__set_binary_type(dso, DSO_BINARY_TYPE__KALLSYMS);
-               dso__set_long_name(dso, DSO__NAME_KALLSYMS, false);
--              map__fixup_start(map);
--              map__fixup_end(map);
-+              maps__mutate_mapping(kmaps, map, map_fixup_cb, NULL);
-       }
-       return err;
-@@ -2270,10 +2278,11 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
-       if (err > 0)
-               pr_debug("Using %s for symbols\n", kallsyms_filename);
-       if (err > 0 && !dso__is_kcore(dso)) {
-+              struct maps *kmaps = map__kmaps(map);
-+
-               dso__set_binary_type(dso, DSO_BINARY_TYPE__GUEST_KALLSYMS);
-               dso__set_long_name(dso, machine->mmap_name, false);
--              map__fixup_start(map);
--              map__fixup_end(map);
-+              maps__mutate_mapping(kmaps, map, map_fixup_cb, NULL);
-       }
-       return err;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch b/queue-6.12/perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch
deleted file mode 100644 (file)
index a2b626a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-From 2ca4d08f1f172fbd844597d300b5af0cf362dbbd Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 11:03:29 -0300
-Subject: perf mmap: Fix NULL deref in aio cleanup on alloc failure
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 25627346b10e6a564610ea2c49dc6dd54812226d ]
-
-perf_mmap__aio_mmap() sets map->aio.nr_cblocks before allocating the
-data array.  If calloc() for aiocb or cblocks fails before the data
-array is allocated, the return -1 path leads to perf_mmap__aio_munmap()
-which loops nr_cblocks times calling perf_mmap__aio_free().  Both
-versions of perf_mmap__aio_free() (NUMA and non-NUMA) dereference
-map->aio.data[idx] without checking if data is NULL, causing a NULL
-pointer dereference.
-
-Add NULL checks for map->aio.data at the top of both
-perf_mmap__aio_free() variants so the cleanup path is safe when
-allocation fails partway through perf_mmap__aio_mmap().
-
-Fixes: d3d1af6f011a553a ("perf record: Enable asynchronous trace writing")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/mmap.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
-index 5d2685d9ab4ea6..d011968c031c03 100644
---- a/tools/perf/util/mmap.c
-+++ b/tools/perf/util/mmap.c
-@@ -88,10 +88,10 @@ static int perf_mmap__aio_alloc(struct mmap *map, int idx)
- static void perf_mmap__aio_free(struct mmap *map, int idx)
- {
--      if (map->aio.data[idx]) {
--              munmap(map->aio.data[idx], mmap__mmap_len(map));
--              map->aio.data[idx] = NULL;
--      }
-+      if (!map->aio.data || !map->aio.data[idx])
-+              return;
-+      munmap(map->aio.data[idx], mmap__mmap_len(map));
-+      map->aio.data[idx] = NULL;
- }
- static int perf_mmap__aio_bind(struct mmap *map, int idx, struct perf_cpu cpu, int affinity)
-@@ -140,6 +140,8 @@ static int perf_mmap__aio_alloc(struct mmap *map, int idx)
- static void perf_mmap__aio_free(struct mmap *map, int idx)
- {
-+      if (!map->aio.data)
-+              return;
-       zfree(&(map->aio.data[idx]));
- }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch b/queue-6.12/perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch
deleted file mode 100644 (file)
index 5a3d0cc..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 1b91e0c3d517cbedcefdb361c7112c078b33d84a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 10:56:33 -0300
-Subject: perf mmap: Guard cpu__get_node() return in aio_bind()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit f32dc302a090f48893477ef297a888db109ec0bd ]
-
-perf_mmap__aio_bind() passes the cpu__get_node() return value directly
-to an unsigned long variable (node_index).  When cpu__get_node() returns
--1 for an unknown CPU, the implicit int-to-unsigned-long conversion
-sign-extends it to ULONG_MAX.
-
-This causes bitmap_zalloc(ULONG_MAX + 1) which wraps to
-bitmap_zalloc(0), returning a zero-sized allocation.  The subsequent
-__set_bit(ULONG_MAX, node_mask) then writes massively out of bounds.
-
-Check the return value in a signed temporary before assigning to
-node_index, and skip the NUMA binding when the node is unknown.
-
-Fixes: c44a8b44ca9f ("perf record: Bind the AIO user space buffers to nodes")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Alexey Budankov <alexey.budankov@linux.intel.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/mmap.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/mmap.c b/tools/perf/util/mmap.c
-index 43b02293f1d2da..5d2685d9ab4ea6 100644
---- a/tools/perf/util/mmap.c
-+++ b/tools/perf/util/mmap.c
-@@ -103,9 +103,15 @@ static int perf_mmap__aio_bind(struct mmap *map, int idx, struct perf_cpu cpu, i
-       int err = 0;
-       if (affinity != PERF_AFFINITY_SYS && cpu__max_node() > 1) {
-+              int node;
-+
-               data = map->aio.data[idx];
-               mmap_len = mmap__mmap_len(map);
--              node_index = cpu__get_node(cpu);
-+              node = cpu__get_node(cpu);
-+              /* -1 sign-extends to ULONG_MAX, wrapping bitmap_zalloc(0) and OOB __set_bit */
-+              if (node < 0)
-+                      return 0;
-+              node_index = node;
-               node_mask = bitmap_zalloc(node_index + 1);
-               if (!node_mask) {
-                       pr_err("Failed to allocate node mask for mbind: error %m\n");
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch b/queue-6.12/perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch
deleted file mode 100644 (file)
index 1f917e9..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-From 2be632851d4fccb6813c2dd43629a5af9a01aaa4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 21:03:13 -0300
-Subject: perf pmu: Fix perf_pmu__parse_scale/unit() OOB access on empty sysfs
- file
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 33035f7dd4e49f3f117e70c5e36c8c1ae88d37f2 ]
-
-perf_pmu__parse_scale() reads a PMU scale file then accesses
-scale[sret - 1] to strip a trailing newline.  Only sret < 0 is
-guarded, so an empty file (sret == 0) causes scale[-1] â€” a stack
-buffer underflow that reads and potentially writes out of bounds.
-
-perf_pmu__parse_unit() has the same pattern: alias->unit[sret - 1]
-with sret == 0 accesses the byte before the struct member, which
-may corrupt the adjacent pmu_name pointer field.
-
-Change both guards from sret < 0 to sret <= 0 so that empty files
-are treated as read errors.
-
-Fixes: 410136f5dd96b601 ("tools/perf/stat: Add event unit and scale support")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Stephane Eranian <eranian@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/pmu.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
-index bf9793a995316b..3a3a56f06880ad 100644
---- a/tools/perf/util/pmu.c
-+++ b/tools/perf/util/pmu.c
-@@ -314,7 +314,7 @@ static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *al
-               goto error;
-       sret = read(fd, scale, sizeof(scale)-1);
--      if (sret < 0)
-+      if (sret <= 0)
-               goto error;
-       if (scale[sret - 1] == '\n')
-@@ -346,7 +346,7 @@ static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *ali
-               return -1;
-       sret = read(fd, alias->unit, UNIT_MAX_LEN);
--      if (sret < 0)
-+      if (sret <= 0)
-               goto error;
-       close(fd);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch b/queue-6.12/perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch
deleted file mode 100644 (file)
index 671caf2..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-From 68de90895a69326c0013eb8251e2f480a39c6520 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 21:01:43 -0300
-Subject: perf pmu: Fix pmu_id() heap underwrite on empty identifier file
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 836455e6dbd34eb3d12eeab5e2d2b9a7f1512459 ]
-
-pmu_id() calls filename__read_str() then strips the trailing newline
-via str[len - 1] = 0.  If the PMU identifier file is empty,
-filename__read_str() succeeds with len = 0.  len - 1 underflows
-size_t to SIZE_MAX, writing a null byte before the heap allocation.
-
-Add a len == 0 check before the newline stripping.
-
-Fixes: 51d548471510843e ("perf pmu: Add pmu_id()")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: John Garry <john.g.garry@oracle.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/pmu.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
-index 8885998c195308..bf9793a995316b 100644
---- a/tools/perf/util/pmu.c
-+++ b/tools/perf/util/pmu.c
-@@ -796,6 +796,12 @@ static char *pmu_id(const char *name)
-       if (filename__read_str(path, &str, &len) < 0)
-               return NULL;
-+      /* empty identifier file â€” nothing useful */
-+      if (len == 0) {
-+              free(str);
-+              return NULL;
-+      }
-+
-       str[len - 1] = 0; /* remove line feed */
-       return str;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch b/queue-6.12/perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch
deleted file mode 100644 (file)
index bc07c9c..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-From 2e0a291e0c556ad0b6df41ed1eacf4bbc33ea93e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 10 Apr 2026 12:13:44 +0100
-Subject: perf pmu: Skip test on Arm64 when #slots is zero
-
-From: Leo Yan <leo.yan@arm.com>
-
-[ Upstream commit 2e2ba7d1ea554ee6e9e751a53eebf3e9270b0670 ]
-
-Some Arm64 PMUs expose 'caps/slots' as 0 when the slot count is not
-implemented, tool_pmu__read_event() currently returns false for this,
-so metrics that reference #slots are reported as syntax error.
-
-Since the commit 3a61fd866ef9 ("perf expr: Return -EINVAL for syntax
-error in expr__find_ids()"), these syntax errors are populated as
-failures and make the PMU metric test fail:
-
-    9.3: Parsing of PMU event table metrics:
-    --- start ---
-    ...
-
-    Found metric 'backend_bound'
-    metric expr 100 * (stall_slot_backend / (#slots * cpu_cycles)) for backend_bound
-    parsing metric: 100 * (stall_slot_backend / (#slots * cpu_cycles))
-    Failure to read '#slots'
-    literal: #slots = nan
-    syntax error
-    Fail to parse metric or group `backend_bound'
-
-    ...
-    ---- end(-1) ----
-    9.3: Parsing of PMU event table metrics    : FAILED!
-
-This commit introduces a new function is_expected_broken_metric() to
-identify broken metrics, and treats metrics containing "#slots" as
-expected broken when #slots == 0 on Arm64 platforms.
-
-Fixes: 3a61fd866ef9aaa1 ("perf expr: Return -EINVAL for syntax error in expr__find_ids()")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Reviewed-by: James Clark <james.clark@linaro.org>
-Signed-off-by: Leo Yan <leo.yan@arm.com>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Mark Rutland <mark.rutland@arm.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/tests/pmu-events.c | 24 ++++++++++++++++++++++--
- 1 file changed, 22 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c
-index db004d26fcb005..8c73ab189c5fce 100644
---- a/tools/perf/tests/pmu-events.c
-+++ b/tools/perf/tests/pmu-events.c
-@@ -15,6 +15,7 @@
- #include "util/expr.h"
- #include "util/hashmap.h"
- #include "util/parse-events.h"
-+#include "util/tool_pmu.h"
- #include "metricgroup.h"
- #include "stat.h"
-@@ -864,6 +865,26 @@ struct metric {
-       struct metric_ref metric_ref;
- };
-+static bool is_expected_broken_metric(const struct pmu_metric *pm)
-+{
-+      if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") ||
-+          !strcmp(pm->metric_name, "M3"))
-+              return true;
-+
-+#if defined(__aarch64__)
-+      /*
-+       * Arm64 platforms may return "#slots == 0", which is treated as a
-+       * syntax error by the parser. Don't test these metrics when running
-+       * on such platforms.
-+       */
-+      if (strstr(pm->metric_expr, "#slots") &&
-+          !tool_pmu__cpu_slots_per_cycle())
-+              return true;
-+#endif
-+
-+      return false;
-+}
-+
- static int test__parsing_callback(const struct pmu_metric *pm,
-                                 const struct pmu_metrics_table *table,
-                                 void *data)
-@@ -902,8 +923,7 @@ static int test__parsing_callback(const struct pmu_metric *pm,
-       err = metricgroup__parse_groups_test(evlist, table, pm->metric_name, &metric_events);
-       if (err) {
--              if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") ||
--                  !strcmp(pm->metric_name, "M3")) {
-+              if (is_expected_broken_metric(pm)) {
-                       (*failures)--;
-                       pr_debug("Expected broken metric %s skipping\n", pm->metric_name);
-                       err = 0;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-remove-redundant-kernel.h-include.patch b/queue-6.12/perf-remove-redundant-kernel.h-include.patch
deleted file mode 100644 (file)
index 5023066..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-From 942efef4b7b7d031c09e6719131040dfda8d3aac Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 23 Jan 2026 13:32:04 +0000
-Subject: perf: Remove redundant kernel.h include
-
-From: Leo Yan <leo.yan@arm.com>
-
-[ Upstream commit 7a0ba3891104da77cfd1a16d41699e0fdf45603a ]
-
-Now that the bitfield dependency is resolved, the explicit inclusion of
-kernel.h is no longer needed.
-
-Remove the redundant include.
-
-Signed-off-by: Leo Yan <leo.yan@arm.com>
-Cc: Ian Rogers <irogers@google.com>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Stable-dep-of: 542e88a4c6f7 ("perf cs-etm: Reject CPU IDs that would overflow signed comparison")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/arch/arm64/util/header.c | 1 -
- tools/perf/util/cs-etm.c            | 1 -
- 2 files changed, 2 deletions(-)
-
-diff --git a/tools/perf/arch/arm64/util/header.c b/tools/perf/arch/arm64/util/header.c
-index 741df3614a09ac..d0ccc727593ca2 100644
---- a/tools/perf/arch/arm64/util/header.c
-+++ b/tools/perf/arch/arm64/util/header.c
-@@ -1,4 +1,3 @@
--#include <linux/kernel.h>
- #include <linux/bits.h>
- #include <linux/bitfield.h>
- #include <stdio.h>
-diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
-index 3fd669817eb9bf..776bef4e00156e 100644
---- a/tools/perf/util/cs-etm.c
-+++ b/tools/perf/util/cs-etm.c
-@@ -6,7 +6,6 @@
-  * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
-  */
--#include <linux/kernel.h>
- #include <linux/bitfield.h>
- #include <linux/bitops.h>
- #include <linux/coresight-pmu.h>
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-add-missing-mmap2-handler-in-timehist.patch b/queue-6.12/perf-sched-add-missing-mmap2-handler-in-timehist.patch
deleted file mode 100644 (file)
index fc0583d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From 198e08ffc86f5ecfb3818a30c56a395ebafc799b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 5 May 2026 17:45:42 -0700
-Subject: perf sched: Add missing mmap2 handler in timehist
-
-From: Ian Rogers <irogers@google.com>
-
-[ Upstream commit 91182741369b261c441e63e6678893032a6d7e4c ]
-
-perf_sched__timehist() registers event handlers for options using the
-sched->tool struct. It registers handlers for MMAP, COMM, EXIT, FORK, etc.
-but completely omits registering a handler for MMAP2 events.
-
-Failing to register both MMAP and MMAP2 handlers causes modern systems
-(which primarily output MMAP2 records) to silently drop VMA map mappings.
-This results in uninitialized machine/thread mapping structures, making it
-impossible to resolve shared library instruction pointers (IPs) to dynamic
-symbols/DSOs during timehist callchain analysis.
-
-Fix this by correctly registering perf_event__process_mmap2 in
-sched->tool inside perf_sched__timehist().
-
-Fixes: 49394a2a24c78ce0 ("perf sched timehist: Introduce timehist command")
-Assisted-by: Gemini-CLI:Google Gemini 3
-Signed-off-by: Ian Rogers <irogers@google.com>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: David Ahern <dsahern@gmail.com>
-Cc: Gabriel Marin <gmx@google.com>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 64bf3ac237f2ef..fa5f00d47e6277 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -3261,6 +3261,7 @@ static int perf_sched__timehist(struct perf_sched *sched)
-        */
-       sched->tool.sample       = perf_timehist__process_sample;
-       sched->tool.mmap         = perf_event__process_mmap;
-+      sched->tool.mmap2        = perf_event__process_mmap2;
-       sched->tool.comm         = perf_event__process_comm;
-       sched->tool.exit         = perf_event__process_exit;
-       sched->tool.fork         = perf_event__process_fork;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-bounds-check-prio-before-test_bit-in-time.patch b/queue-6.12/perf-sched-bounds-check-prio-before-test_bit-in-time.patch
deleted file mode 100644 (file)
index 5dab2b5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 6007424409b0a570f8132a408e0f317dd33c8830 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 21:48:13 -0300
-Subject: perf sched: Bounds-check prio before test_bit() in timehist
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 4477dc01fcfc7f404772a67e0c1e056541ceb61d ]
-
-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>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index d599ad421df108..7cf56e271a993a 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -2646,7 +2646,9 @@ static bool timehist_skip_sample(struct perf_sched *sched,
-               else if (evsel__name_is(evsel, "sched:sched_switch"))
-                       prio = evsel__intval(evsel, 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++;
-               }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-clean-up-idle_threads-entry-on-init-failu.patch b/queue-6.12/perf-sched-clean-up-idle_threads-entry-on-init-failu.patch
deleted file mode 100644 (file)
index e9eab6a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-From f68c59a0bd704d8491bc39474d5f73d19e496808 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 11:12:08 -0300
-Subject: perf sched: Clean up idle_threads entry on init failure
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit cda5a94ad9181cd60cbf04be11d524201bf489a2 ]
-
-get_idle_thread() allocates a thread via thread__new() and stores it in
-idle_threads[cpu], then calls init_idle_thread() to set up the private
-data.  If init_idle_thread() fails (e.g. OOM for the idle_thread_runtime
-struct), the function returns NULL but leaves the partially initialized
-thread in idle_threads[cpu].
-
-On subsequent calls for the same CPU, get_idle_thread() finds a non-NULL
-idle_threads[cpu], skips allocation, and returns thread__get() on a
-thread that has no priv data.  Callers then get a thread whose
-thread__priv() returns NULL, leading to unexpected behavior.
-
-Release the thread and reset the slot to NULL on init failure so the
-entry doesn't persist in a corrupted state.
-
-Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: David Ahern <dsahern@gmail.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 4596037b5763c0..fd93ab11bd37ed 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -2496,8 +2496,11 @@ static struct thread *get_idle_thread(int cpu)
-               idle_threads[cpu] = thread__new(0, 0);
-               if (idle_threads[cpu]) {
--                      if (init_idle_thread(idle_threads[cpu]) < 0)
-+                      if (init_idle_thread(idle_threads[cpu]) < 0) {
-+                              /* clean up so next call doesn't find a half-initialized thread */
-+                              thread__zput(idle_threads[cpu]);
-                               return NULL;
-+                      }
-               }
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-fix-idle-hist-callchain-display-using-wro.patch b/queue-6.12/perf-sched-fix-idle-hist-callchain-display-using-wro.patch
deleted file mode 100644 (file)
index 8a83f8a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From 8ca288d57427734595a82345590be1fa3a9ad6c1 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 21:49:16 -0300
-Subject: perf sched: Fix idle-hist callchain display using wrong rb_first
- variant
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit d9b99dc8148e0c1f5da3942131b47e0d21187a32 ]
-
-timehist_print_idlehist_callchain() calls rb_first_cached() on
-sorted_root, but the sort function (callchain_param.sort) populates it
-via rb_insert_color() on the plain rb_root member â€” not the cached
-variant.  This means rb_leftmost is never set, so rb_first_cached()
-always returns NULL and the entire callchain summary is silently
-dropped from --idle-hist output.
-
-The original code in ba957ebb54893aca ("perf sched timehist: Show
-callchains for idle stat") was correct â€” it used struct rb_root and
-rb_first().  The bug was introduced when sorted_root was converted to
-rb_root_cached without converting the sort insertion path to use
-rb_insert_color_cached().
-
-Use rb_first(&root->rb_root) to match how the tree was populated.
-
-Fixes: cb4c13a5137766c3 ("perf sched: Use cached rbtrees")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Davidlohr Bueso <dave@stgolabs.net>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Acked-by: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 7cf56e271a993a..0741d926590468 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -3126,7 +3126,8 @@ static size_t timehist_print_idlehist_callchain(struct rb_root_cached *root)
-       size_t ret = 0;
-       FILE *fp = stdout;
-       struct callchain_node *chain;
--      struct rb_node *rb_node = rb_first_cached(root);
-+      /* sort() uses rb_insert_color() on rb_root, not rb_root_cached */
-+      struct rb_node *rb_node = rb_first(&root->rb_root);
-       printf("  %16s  %8s  %s\n", "Idle time (msec)", "Count", "Callchains");
-       printf("  %.16s  %.8s  %.50s\n", graph_dotted_line, graph_dotted_line,
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-fix-null-dereference-in-latency_runtime_e.patch b/queue-6.12/perf-sched-fix-null-dereference-in-latency_runtime_e.patch
deleted file mode 100644 (file)
index a3c7c63..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-From 15f991f106f73950850b3029d6e163b7d32ad579 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 4 Jun 2026 12:56:02 -0300
-Subject: perf sched: Fix NULL dereference in latency_runtime_event
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 8cbca8a480e15f6326ce94287570993f27a4b2d5 ]
-
-latency_runtime_event() passes the return value of
-machine__findnew_thread() directly to thread_atoms_search() at line
-1216, before checking for NULL at line 1220.  thread_atoms_search()
-calls pid_cmp() which dereferences the thread pointer via
-thread__tid(), causing a NULL pointer dereference if the allocation
-fails.
-
-All other callers of thread_atoms_search() in this file
-(latency_switch_event, latency_wakeup_event,
-latency_migrate_task_event) correctly check for NULL first.
-
-Move the atoms assignment after the NULL check to match the pattern
-used by the other callers.
-
-Fixes: b91fc39f4ad7 ("perf machine: Protect the machine->threads with a rwlock")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 00d50c356e43c1..12db6fe6e05a6a 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -1214,13 +1214,15 @@ static int latency_runtime_event(struct perf_sched *sched,
-       const u32 pid      = evsel__intval(evsel, sample, "pid");
-       const u64 runtime  = evsel__intval(evsel, sample, "runtime");
-       struct thread *thread = machine__findnew_thread(machine, -1, pid);
--      struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
-+      struct work_atoms *atoms;
-       u64 timestamp = sample->time;
-       int cpu = sample->cpu, err = -1;
-       if (thread == NULL)
-               return -1;
-+      atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
-+
-       /* perf.data is untrusted input â€” CPU may be absent or corrupted */
-       if (cpu >= MAX_CPUS || cpu < 0) {
-               pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n",
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-fix-register_pid-overflow-strcpy-and-bug_.patch b/queue-6.12/perf-sched-fix-register_pid-overflow-strcpy-and-bug_.patch
deleted file mode 100644 (file)
index 4ec5ed6..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-From 0d2616e375487df9410dd818229be85ded869f7e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 4 Jun 2026 18:25:57 -0300
-Subject: perf sched: Fix register_pid() overflow, strcpy, and BUG_ON
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 5949d339f5ec98752d56dcd4e36f619a59d513a5 ]
-
-register_pid() has several issues when processing untrusted perf.data:
-
-1. Integer overflow: (pid + 1) * sizeof(struct task_desc *) can wrap
-   to a small value on 32-bit systems when pid is large (e.g.
-   0x40000000), causing realloc to return a tiny buffer followed by
-   out-of-bounds writes in the initialization loop.
-
-2. Heap buffer overflow: strcpy(task->comm, comm) copies the
-   untrusted comm string into a fixed 20-byte COMM_LEN buffer with
-   no length check.
-
-3. BUG_ON on allocation failure: perf.data is untrusted input, so
-   allocation failures should be handled gracefully rather than
-   killing the process.
-
-4. Realloc of sched->tasks assigned directly back, leaking the old
-   pointer on failure; nr_tasks incremented before the realloc,
-   leaving corrupted state on failure.
-
-Cap pid at PID_MAX_LIMIT (4194304, matching the kernel's maximum
-on 64-bit), replace strcpy with strlcpy, guard against NULL comm,
-replace BUG_ON with NULL returns using safe realloc patterns, and
-add NULL checks in callers that dereference the result.
-
-Fixes: ec156764d424 ("perf sched: Import schedbench.c")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Ingo Molnar <mingo@elte.hu>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 40 ++++++++++++++++++++++++++++----------
- 1 file changed, 30 insertions(+), 10 deletions(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 12db6fe6e05a6a..4596037b5763c0 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -51,6 +51,7 @@
- #define COMM_LEN              20
- #define SYM_LEN                       129
- #define MAX_PID                       1024000
-+#define PID_MAX_LIMIT         4194304 /* kernel limit on 64-bit */
- #define MAX_PRIO              140
- static const char *cpu_list;
-@@ -440,17 +441,28 @@ static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *ta
- static struct task_desc *register_pid(struct perf_sched *sched,
-                                     unsigned long pid, const char *comm)
- {
--      struct task_desc *task;
-+      struct task_desc *task, **tasks_p;
-       static int pid_max;
-+      /* perf.data is untrusted â€” cap pid to prevent overflow in size calculations */
-+      if (pid >= PID_MAX_LIMIT) {
-+              pr_err("pid %lu exceeds limit %d, skipping\n", pid, PID_MAX_LIMIT);
-+              return NULL;
-+      }
-+
-       if (sched->pid_to_task == NULL) {
-               if (sysctl__read_int("kernel/pid_max", &pid_max) < 0)
-                       pid_max = MAX_PID;
--              BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL);
-+              sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *));
-+              if (sched->pid_to_task == NULL)
-+                      return NULL;
-       }
-       if (pid >= (unsigned long)pid_max) {
--              BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) *
--                      sizeof(struct task_desc *))) == NULL);
-+              void *p = realloc(sched->pid_to_task, (pid + 1) * sizeof(struct task_desc *));
-+
-+              if (p == NULL)
-+                      return NULL;
-+              sched->pid_to_task = p;
-               while (pid >= (unsigned long)pid_max)
-                       sched->pid_to_task[pid_max++] = NULL;
-       }
-@@ -461,9 +473,11 @@ static struct task_desc *register_pid(struct perf_sched *sched,
-               return task;
-       task = zalloc(sizeof(*task));
-+      if (task == NULL)
-+              return NULL;
-       task->pid = pid;
--      task->nr = sched->nr_tasks;
--      strcpy(task->comm, comm);
-+      if (comm)
-+              strlcpy(task->comm, comm, sizeof(task->comm));
-       /*
-        * every task starts in sleeping state - this gets ignored
-        * if there's no wakeup pointing to this sleep state:
-@@ -471,10 +485,12 @@ static struct task_desc *register_pid(struct perf_sched *sched,
-       add_sched_event_sleep(sched, task, 0, 0);
-       sched->pid_to_task[pid] = task;
--      sched->nr_tasks++;
--      sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *));
--      BUG_ON(!sched->tasks);
--      sched->tasks[task->nr] = task;
-+      tasks_p = realloc(sched->tasks, (sched->nr_tasks + 1) * sizeof(struct task_desc *));
-+      if (!tasks_p)
-+              return NULL;
-+      sched->tasks = tasks_p;
-+      sched->tasks[sched->nr_tasks] = task;
-+      task->nr = sched->nr_tasks++;
-       if (verbose > 0)
-               printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm);
-@@ -838,6 +854,8 @@ replay_wakeup_event(struct perf_sched *sched,
-       waker = register_pid(sched, sample->tid, "<unknown>");
-       wakee = register_pid(sched, pid, comm);
-+      if (waker == NULL || wakee == NULL)
-+              return -1;
-       add_sched_event_wakeup(sched, waker, sample->time, wakee);
-       return 0;
-@@ -880,6 +898,8 @@ static int replay_switch_event(struct perf_sched *sched,
-       prev = register_pid(sched, prev_pid, prev_comm);
-       next = register_pid(sched, next_pid, next_comm);
-+      if (prev == NULL || next == NULL)
-+              return -1;
-       sched->cpu_last_switched[cpu] = timestamp;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-fix-thread-leaks-in-perf-sched-timehist.patch b/queue-6.12/perf-sched-fix-thread-leaks-in-perf-sched-timehist.patch
deleted file mode 100644 (file)
index 5390d2a..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-From 7e45435541778380e6b352e5d1d5363b05b61536 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 2 Jul 2025 18:49:38 -0700
-Subject: perf sched: Fix thread leaks in 'perf sched timehist'
-
-From: Namhyung Kim <namhyung@kernel.org>
-
-[ Upstream commit e2eb59260c4f6bac403491d0112891766b8650d1 ]
-
-Add missing thread__put() after machine__findnew_thread() or
-timehist_get_thread().  Also idle threads' last_thread should be
-refcounted properly.
-
-Fixes: 699b5b920db04a6f ("perf sched timehist: Save callchain when entering idle")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Tested-by: Ian Rogers <irogers@google.com>
-Link: https://lore.kernel.org/r/20250703014942.1369397-5-namhyung@kernel.org
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: a99d6394cd48 ("perf sched: Use thread__put() in free_idle_threads()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 48 +++++++++++++++++++++++++++++---------
- 1 file changed, 37 insertions(+), 11 deletions(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 1203425d2b8a55..f3a03be9471aa0 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -2386,8 +2386,10 @@ static void save_task_callchain(struct perf_sched *sched,
-               return;
-       }
--      if (!sched->show_callchain || sample->callchain == NULL)
-+      if (!sched->show_callchain || sample->callchain == NULL) {
-+              thread__put(thread);
-               return;
-+      }
-       cursor = get_tls_callchain_cursor();
-@@ -2396,10 +2398,12 @@ static void save_task_callchain(struct perf_sched *sched,
-               if (verbose > 0)
-                       pr_err("Failed to resolve callchain. Skipping\n");
-+              thread__put(thread);
-               return;
-       }
-       callchain_cursor_commit(cursor);
-+      thread__put(thread);
-       while (true) {
-               struct callchain_cursor_node *node;
-@@ -2476,8 +2480,17 @@ static void free_idle_threads(void)
-               return;
-       for (i = 0; i < idle_max_cpu; ++i) {
--              if ((idle_threads[i]))
--                      thread__delete(idle_threads[i]);
-+              struct thread *idle = idle_threads[i];
-+
-+              if (idle) {
-+                      struct idle_thread_runtime *itr;
-+
-+                      itr = thread__priv(idle);
-+                      if (itr)
-+                              thread__put(itr->last_thread);
-+
-+                      thread__delete(idle);
-+              }
-       }
-       free(idle_threads);
-@@ -2517,7 +2530,7 @@ static struct thread *get_idle_thread(int cpu)
-               }
-       }
--      return idle_threads[cpu];
-+      return thread__get(idle_threads[cpu]);
- }
- static void save_idle_callchain(struct perf_sched *sched,
-@@ -2572,7 +2585,8 @@ static struct thread *timehist_get_thread(struct perf_sched *sched,
-                       if (itr == NULL)
-                               return NULL;
--                      itr->last_thread = thread;
-+                      thread__put(itr->last_thread);
-+                      itr->last_thread = thread__get(thread);
-                       /* copy task callchain when entering to idle */
-                       if (evsel__intval(evsel, sample, "next_pid") == 0)
-@@ -2643,6 +2657,7 @@ static void timehist_print_wakeup_event(struct perf_sched *sched,
-       /* show wakeup unless both awakee and awaker are filtered */
-       if (timehist_skip_sample(sched, thread, evsel, sample) &&
-           timehist_skip_sample(sched, awakened, evsel, sample)) {
-+              thread__put(thread);
-               return;
-       }
-@@ -2659,6 +2674,8 @@ static void timehist_print_wakeup_event(struct perf_sched *sched,
-       printf("awakened: %s", timehist_get_commstr(awakened));
-       printf("\n");
-+
-+      thread__put(thread);
- }
- static int timehist_sched_wakeup_ignore(const struct perf_tool *tool __maybe_unused,
-@@ -2687,8 +2704,10 @@ static int timehist_sched_wakeup_event(const struct perf_tool *tool,
-               return -1;
-       tr = thread__get_runtime(thread);
--      if (tr == NULL)
-+      if (tr == NULL) {
-+              thread__put(thread);
-               return -1;
-+      }
-       if (tr->ready_to_run == 0)
-               tr->ready_to_run = sample->time;
-@@ -2698,6 +2717,7 @@ static int timehist_sched_wakeup_event(const struct perf_tool *tool,
-           !perf_time__skip_sample(&sched->ptime, sample->time))
-               timehist_print_wakeup_event(sched, evsel, sample, machine, thread);
-+      thread__put(thread);
-       return 0;
- }
-@@ -2725,6 +2745,7 @@ static void timehist_print_migration_event(struct perf_sched *sched,
-       if (timehist_skip_sample(sched, thread, evsel, sample) &&
-           timehist_skip_sample(sched, migrated, evsel, sample)) {
-+              thread__put(thread);
-               return;
-       }
-@@ -2752,6 +2773,7 @@ static void timehist_print_migration_event(struct perf_sched *sched,
-       printf(" cpu %d => %d", ocpu, dcpu);
-       printf("\n");
-+      thread__put(thread);
- }
- static int timehist_migrate_task_event(const struct perf_tool *tool,
-@@ -2771,8 +2793,10 @@ static int timehist_migrate_task_event(const struct perf_tool *tool,
-               return -1;
-       tr = thread__get_runtime(thread);
--      if (tr == NULL)
-+      if (tr == NULL) {
-+              thread__put(thread);
-               return -1;
-+      }
-       tr->migrations++;
-       tr->migrated = sample->time;
-@@ -2782,6 +2806,7 @@ static int timehist_migrate_task_event(const struct perf_tool *tool,
-               timehist_print_migration_event(sched, evsel, sample,
-                                                       machine, thread);
-       }
-+      thread__put(thread);
-       return 0;
- }
-@@ -2804,10 +2829,10 @@ static void timehist_update_task_prio(struct evsel *evsel,
-               return;
-       tr = thread__get_runtime(thread);
--      if (tr == NULL)
--              return;
-+      if (tr != NULL)
-+              tr->prio = next_prio;
--      tr->prio = next_prio;
-+      thread__put(thread);
- }
- static int timehist_sched_change_event(const struct perf_tool *tool,
-@@ -2819,7 +2844,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool,
-       struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
-       struct perf_time_interval *ptime = &sched->ptime;
-       struct addr_location al;
--      struct thread *thread;
-+      struct thread *thread = NULL;
-       struct thread_runtime *tr = NULL;
-       u64 tprev, t = sample->time;
-       int rc = 0;
-@@ -2944,6 +2969,7 @@ static int timehist_sched_change_event(const struct perf_tool *tool,
-       evsel__save_time(evsel, sample->time, sample->cpu);
-+      thread__put(thread);
-       addr_location__exit(&al);
-       return rc;
- }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-fix-thread-reference-leak-in-latency_swit.patch b/queue-6.12/perf-sched-fix-thread-reference-leak-in-latency_swit.patch
deleted file mode 100644 (file)
index 0a97c8f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From aeff520e1eb2a89c4f61def4ae298cd13e1e340a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 4 Jun 2026 12:55:29 -0300
-Subject: perf sched: Fix thread reference leak in latency_switch_event
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 66ea9de60396a4dea5276bc87025884691876c36 ]
-
-In latency_switch_event(), after acquiring thread references for
-sched_out and sched_in via machine__findnew_thread(), the first
-add_sched_out_event() failure path does 'return -1', bypassing the
-out_put label that calls thread__put() on both references.
-
-The second and third add_sched_out_event() failures correctly use
-'goto out_put'.  Fix the first one to match.
-
-Fixes: b91fc39f4ad7 ("perf machine: Protect the machine->threads with a rwlock")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 6d7106fb1c0cbc..c0fd6a8595d0f2 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -1175,7 +1175,7 @@ static int latency_switch_event(struct perf_sched *sched,
-               }
-       }
-       if (add_sched_out_event(out_events, prev_state, timestamp))
--              return -1;
-+              goto out_put;
-       in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
-       if (!in_events) {
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch b/queue-6.12/perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch
deleted file mode 100644 (file)
index ab4a9af..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-From d14d51afef5376933d3142196548558a11e7f96e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 11:26:28 -0300
-Subject: perf sched: Replace BUG_ON and add NULL checks in replay event
- helpers
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 75eafe4a3a93a0143a20c0cc286bfb9008ac1478 ]
-
-get_new_event() has three issues:
-
-1. The zalloc() result is dereferenced without a NULL check, crashing
-   on allocation failure.
-
-2. BUG_ON(!task->atoms) kills the process when realloc() fails.
-   Since perf.data is untrusted input, this should be a graceful error.
-
-3. The realloc pattern assigns directly to task->atoms, losing the old
-   pointer on failure.  task->nr_events is also incremented before the
-   realloc, leaving corrupted state on failure.
-
-Fix get_new_event() to:
-  - Check the zalloc() result before dereferencing
-  - Use a temporary for realloc() to avoid losing the old pointer
-  - Increment nr_events only after successful realloc
-  - Return NULL instead of calling BUG_ON on failure
-
-Also fix add_sched_event_wakeup() where zalloc() for wait_sem is
-passed to sem_init() without a NULL check.
-
-Update all callers (add_sched_event_run, add_sched_event_wakeup,
-add_sched_event_sleep) to handle NULL returns by returning early.
-The replay may produce incomplete output on OOM but will not crash.
-
-Fixes: ec156764d424 ("perf sched: Import schedbench.c")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Ingo Molnar <mingo@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 28 +++++++++++++++++++++++++---
- 1 file changed, 25 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index 8eb5c880a5b605..d599ad421df108 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -360,14 +360,25 @@ get_new_event(struct task_desc *task, u64 timestamp)
-       struct sched_atom *event = zalloc(sizeof(*event));
-       unsigned long idx = task->nr_events;
-       size_t size;
-+      struct sched_atom **atoms_p;
-+
-+      if (event == NULL) {
-+              pr_err("ERROR: sched: failed to allocate event\n");
-+              return NULL;
-+      }
-       event->timestamp = timestamp;
-       event->nr = idx;
-+      size = sizeof(struct sched_atom *) * (task->nr_events + 1);
-+      atoms_p = realloc(task->atoms, size);
-+      if (!atoms_p) {
-+              pr_err("ERROR: sched: failed to grow atoms array\n");
-+              free(event);
-+              return NULL;
-+      }
-+      task->atoms = atoms_p;
-       task->nr_events++;
--      size = sizeof(struct sched_atom *) * task->nr_events;
--      task->atoms = realloc(task->atoms, size);
--      BUG_ON(!task->atoms);
-       task->atoms[idx] = event;
-@@ -398,6 +409,8 @@ static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task
-       }
-       event = get_new_event(task, timestamp);
-+      if (event == NULL)
-+              return;
-       event->type = SCHED_EVENT_RUN;
-       event->duration = duration;
-@@ -411,6 +424,8 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t
-       struct sched_atom *event, *wakee_event;
-       event = get_new_event(task, timestamp);
-+      if (event == NULL)
-+              return;
-       event->type = SCHED_EVENT_WAKEUP;
-       event->wakee = wakee;
-@@ -425,6 +440,10 @@ static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *t
-       }
-       wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem));
-+      if (!wakee_event->wait_sem) {
-+              pr_err("ERROR: sched: failed to allocate semaphore\n");
-+              return;
-+      }
-       sem_init(wakee_event->wait_sem, 0, 0);
-       wakee_event->specific_wait = 1;
-       event->wait_sem = wakee_event->wait_sem;
-@@ -437,6 +456,9 @@ static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *ta
- {
-       struct sched_atom *event = get_new_event(task, timestamp);
-+      if (event == NULL)
-+              return;
-+
-       event->type = SCHED_EVENT_SLEEP;
-       sched->nr_sleep_events++;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch b/queue-6.12/perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch
deleted file mode 100644 (file)
index 2d84490..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-From a12dc855834bb7be2affdb52098a836fc82064e7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 1 Jun 2026 19:53:41 -0300
-Subject: perf sched: Replace BUG_ON on invalid CPU with graceful skip
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 1e2c83f732deb329ebce23e26cbc482f4c4bf194 ]
-
-latency_switch_event(), latency_runtime_event(), and map_switch_event()
-use BUG_ON(cpu >= MAX_CPUS || cpu < 0) to validate the sample CPU.
-When PERF_SAMPLE_CPU is absent from the sample type,
-evsel__parse_sample() initializes sample->cpu to (u32)-1.  Casting
-this to int yields -1, which triggers the BUG_ON and aborts perf sched.
-
-The central CPU validation in perf_session__deliver_event() intentionally
-preserves the (u32)-1 sentinel for downstream tools like perf script
-and perf inject, so leaf callbacks must handle it themselves.
-
-Replace the three BUG_ON calls with graceful skips using pr_warning(),
-matching the existing pattern in process_sched_switch_event() and
-process_sched_runtime_event() earlier in the same file.  Include the
-file offset for cross-referencing with perf report -D.
-
-Reported-by: sashiko-bot@kernel.org # Running on a local machine
-Reviewed-by: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Stable-dep-of: 8cbca8a480e1 ("perf sched: Fix NULL dereference in latency_runtime_event")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 22 +++++++++++++++++++---
- 1 file changed, 19 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index c0fd6a8595d0f2..00d50c356e43c1 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -1145,7 +1145,12 @@ static int latency_switch_event(struct perf_sched *sched,
-       int cpu = sample->cpu, err = -1;
-       s64 delta;
--      BUG_ON(cpu >= MAX_CPUS || cpu < 0);
-+      /* perf.data is untrusted input â€” CPU may be absent or corrupted */
-+      if (cpu >= MAX_CPUS || cpu < 0) {
-+              pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n",
-+                         sample->file_offset, cpu);
-+              return 0;
-+      }
-       timestamp0 = sched->cpu_last_switched[cpu];
-       sched->cpu_last_switched[cpu] = timestamp;
-@@ -1216,7 +1221,13 @@ static int latency_runtime_event(struct perf_sched *sched,
-       if (thread == NULL)
-               return -1;
--      BUG_ON(cpu >= MAX_CPUS || cpu < 0);
-+      /* perf.data is untrusted input â€” CPU may be absent or corrupted */
-+      if (cpu >= MAX_CPUS || cpu < 0) {
-+              pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n",
-+                         sample->file_offset, cpu);
-+              err = 0;
-+              goto out_put;
-+      }
-       if (!atoms) {
-               if (thread_atoms_insert(sched, thread))
-                       goto out_put;
-@@ -1656,7 +1667,12 @@ static int map_switch_event(struct perf_sched *sched, struct evsel *evsel,
-       const char *str;
-       int ret = -1;
--      BUG_ON(this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0);
-+      /* perf.data is untrusted input â€” CPU may be absent or corrupted */
-+      if (this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0) {
-+              pr_warning("WARNING: at offset %#" PRIx64 ": out-of-bound sample CPU %d, skipping sample\n",
-+                         sample->file_offset, this_cpu.cpu);
-+              return 0;
-+      }
-       if (this_cpu.cpu > sched->max_cpu.cpu)
-               sched->max_cpu = this_cpu;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-timehist-add-pre-migration-wait-time-opti.patch b/queue-6.12/perf-sched-timehist-add-pre-migration-wait-time-opti.patch
deleted file mode 100644 (file)
index a9f90fc..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-From 638a0bcd5724e3f1c6beecc3c1cf2c34ad5236e4 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 4 Oct 2024 22:37:56 +0530
-Subject: perf sched timehist: Add pre-migration wait time option
-
-From: Madadi Vineeth Reddy <vineethr@linux.ibm.com>
-
-[ Upstream commit cd912ab3b65445df7b95bbdd06ac29f823d4df98 ]
-
-pre-migration wait time is the time that a task unnecessarily spends
-on the runqueue of a CPU but doesn't get switched-in there. In terms
-of tracepoints, it is the time between sched:sched_wakeup and
-sched:sched_migrate_task.
-
-Let's say a task woke up on CPU2, then it got migrated to CPU4 and
-then it's switched-in to CPU4. So, here pre-migration wait time is
-time that it was waiting on runqueue of CPU2 after it is woken up.
-
-The general pattern for pre-migration to occur is:
-sched:sched_wakeup
-sched:sched_migrate_task
-sched:sched_switch
-
-The sched:sched_waking event is used to capture the wakeup time,
-as it aligns with the existing code and only introduces a negligible
-time difference.
-
-pre-migrations are generally not useful and it increases migrations.
-This metric would be helpful in testing patches mainly related to wakeup
-and load-balancer code paths as better wakeup logic would choose an
-optimal CPU where task would be switched-in and thereby reducing pre-
-migrations.
-
-The sample output(s) when -P or --pre-migrations is used:
-=================
-           time    cpu  task name                       wait time  sch delay   run time  pre-mig time
-                        [tid/pid]                          (msec)     (msec)     (msec)     (msec)
---------------- ------  ------------------------------  ---------  ---------  ---------  ---------
-   38456.720806 [0001]  schbench[28634/28574]               4.917      4.768      1.004      0.000
-   38456.720810 [0001]  rcu_preempt[18]                     3.919      0.003      0.004      0.000
-   38456.721800 [0006]  schbench[28779/28574]              23.465     23.465      1.999      0.000
-   38456.722800 [0002]  schbench[28773/28574]              60.371     60.237      3.955     60.197
-   38456.722806 [0001]  schbench[28634/28574]               0.004      0.004      1.996      0.000
-   38456.722811 [0001]  rcu_preempt[18]                     1.996      0.005      0.005      0.000
-   38456.723800 [0000]  schbench[28833/28574]               4.000      4.000      3.999      0.000
-   38456.723800 [0004]  schbench[28762/28574]              42.951     42.839      3.999     39.867
-   38456.723802 [0007]  schbench[28812/28574]              43.947     43.817      3.999     40.866
-   38456.723804 [0001]  schbench[28587/28574]               7.935      7.822      0.993      0.000
-
-Signed-off-by: Madadi Vineeth Reddy <vineethr@linux.ibm.com>
-Reviewed-by: Tim Chen <tim.c.chen@linux.intel.com>
-Link: https://lore.kernel.org/r/20241004170756.18064-1-vineethr@linux.ibm.com
-Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-Stable-dep-of: a99d6394cd48 ("perf sched: Use thread__put() in free_idle_threads()")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/Documentation/perf-sched.txt |  8 ++
- tools/perf/builtin-sched.c              | 98 +++++++++++++++----------
- 2 files changed, 67 insertions(+), 39 deletions(-)
-
-diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
-index 3db64954a267a3..6dbbddb6464d01 100644
---- a/tools/perf/Documentation/perf-sched.txt
-+++ b/tools/perf/Documentation/perf-sched.txt
-@@ -221,6 +221,14 @@ OPTIONS for 'perf sched timehist'
-       priorities are specified with -: 120-129. A combination of both can also be
-       provided: 0,120-129.
-+-P::
-+--pre-migrations::
-+      Show pre-migration wait time. pre-migration wait time is the time spent
-+      by a task waiting on a runqueue but not getting the chance to run there
-+      and is migrated to a different runqueue where it is finally run. This
-+      time between sched_wakeup and migrate_task is the pre-migration wait
-+      time.
-+
- OPTIONS for 'perf sched replay'
- ------------------------------
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index fd93ab11bd37ed..1203425d2b8a55 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -229,6 +229,7 @@ struct perf_sched {
-       bool            show_wakeups;
-       bool            show_next;
-       bool            show_migrations;
-+      bool            pre_migrations;
-       bool            show_state;
-       bool            show_prio;
-       u64             skipped_samples;
-@@ -248,7 +249,9 @@ struct thread_runtime {
-       u64 dt_iowait;      /* time between CPU access by iowait (off cpu) */
-       u64 dt_preempt;     /* time between CPU access by preempt (off cpu) */
-       u64 dt_delay;       /* time between wakeup and sched-in */
-+      u64 dt_pre_mig;     /* time between migration and wakeup */
-       u64 ready_to_run;   /* time of wakeup */
-+      u64 migrated;       /* time when a thread is migrated */
-       struct stats run_stats;
-       u64 total_run_time;
-@@ -256,6 +259,7 @@ struct thread_runtime {
-       u64 total_iowait_time;
-       u64 total_preempt_time;
-       u64 total_delay_time;
-+      u64 total_pre_mig_time;
-       char last_state;
-@@ -2148,14 +2152,15 @@ static void timehist_header(struct perf_sched *sched)
-               printf(" ");
-       }
--      if (sched->show_prio) {
--              printf(" %-*s  %-*s  %9s  %9s  %9s",
--                     comm_width, "task name", MAX_PRIO_STR_LEN, "prio",
--                     "wait time", "sch delay", "run time");
--      } else {
--              printf(" %-*s  %9s  %9s  %9s", comm_width,
--                     "task name", "wait time", "sch delay", "run time");
--      }
-+      printf(" %-*s", comm_width, "task name");
-+
-+      if (sched->show_prio)
-+              printf("  %-*s", MAX_PRIO_STR_LEN, "prio");
-+
-+      printf("  %9s  %9s  %9s", "wait time", "sch delay", "run time");
-+
-+      if (sched->pre_migrations)
-+              printf("  %9s", "pre-mig time");
-       if (sched->show_state)
-               printf("  %s", "state");
-@@ -2170,17 +2175,15 @@ static void timehist_header(struct perf_sched *sched)
-       if (sched->show_cpu_visual)
-               printf(" %*s ", ncpus, "");
--      if (sched->show_prio) {
--              printf(" %-*s  %-*s  %9s  %9s  %9s",
--                     comm_width, "[tid/pid]", MAX_PRIO_STR_LEN, "",
--                     "(msec)", "(msec)", "(msec)");
--      } else {
--              printf(" %-*s  %9s  %9s  %9s", comm_width,
--                     "[tid/pid]", "(msec)", "(msec)", "(msec)");
--      }
-+      printf(" %-*s", comm_width, "[tid/pid]");
--      if (sched->show_state)
--              printf("  %5s", "");
-+      if (sched->show_prio)
-+              printf("  %-*s", MAX_PRIO_STR_LEN, "");
-+
-+      printf("  %9s  %9s  %9s", "(msec)", "(msec)", "(msec)");
-+
-+      if (sched->pre_migrations)
-+              printf("  %9s", "(msec)");
-       printf("\n");
-@@ -2192,15 +2195,15 @@ static void timehist_header(struct perf_sched *sched)
-       if (sched->show_cpu_visual)
-               printf(" %.*s ", ncpus, graph_dotted_line);
--      if (sched->show_prio) {
--              printf(" %.*s  %.*s  %.9s  %.9s  %.9s",
--                     comm_width, graph_dotted_line, MAX_PRIO_STR_LEN, graph_dotted_line,
--                     graph_dotted_line, graph_dotted_line, graph_dotted_line);
--      } else {
--              printf(" %.*s  %.9s  %.9s  %.9s", comm_width,
--                     graph_dotted_line, graph_dotted_line, graph_dotted_line,
--                     graph_dotted_line);
--      }
-+      printf(" %.*s", comm_width, graph_dotted_line);
-+
-+      if (sched->show_prio)
-+              printf("  %.*s", MAX_PRIO_STR_LEN, graph_dotted_line);
-+
-+      printf("  %.9s  %.9s  %.9s", graph_dotted_line, graph_dotted_line, graph_dotted_line);
-+
-+      if (sched->pre_migrations)
-+              printf("  %.9s", graph_dotted_line);
-       if (sched->show_state)
-               printf("  %.5s", graph_dotted_line);
-@@ -2256,6 +2259,8 @@ static void timehist_print_sample(struct perf_sched *sched,
-       print_sched_time(tr->dt_delay, 6);
-       print_sched_time(tr->dt_run, 6);
-+      if (sched->pre_migrations)
-+              print_sched_time(tr->dt_pre_mig, 6);
-       if (sched->show_state)
-               printf(" %5c ", thread__tid(thread) == 0 ? 'I' : state);
-@@ -2293,18 +2298,21 @@ static void timehist_print_sample(struct perf_sched *sched,
-  *    last_time = time of last sched change event for current task
-  *                (i.e, time process was last scheduled out)
-  * ready_to_run = time of wakeup for current task
-+ *     migrated = time of task migration to another CPU
-  *
-- * -----|------------|------------|------------|------
-- *    last         ready        tprev          t
-+ * -----|-------------|-------------|-------------|-------------|-----
-+ *    last         ready         migrated       tprev           t
-  *    time         to run
-  *
-- *      |-------- dt_wait --------|
-- *                   |- dt_delay -|-- dt_run --|
-+ *      |---------------- dt_wait ----------------|
-+ *                   |--------- dt_delay ---------|-- dt_run --|
-+ *                   |- dt_pre_mig -|
-  *
-- *   dt_run = run time of current task
-- *  dt_wait = time between last schedule out event for task and tprev
-- *            represents time spent off the cpu
-- * dt_delay = time between wakeup and schedule-in of task
-+ *     dt_run = run time of current task
-+ *    dt_wait = time between last schedule out event for task and tprev
-+ *              represents time spent off the cpu
-+ *   dt_delay = time between wakeup and schedule-in of task
-+ * dt_pre_mig = time between wakeup and migration to another CPU
-  */
- static void timehist_update_runtime_stats(struct thread_runtime *r,
-@@ -2315,6 +2323,7 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
-       r->dt_iowait  = 0;
-       r->dt_preempt = 0;
-       r->dt_run     = 0;
-+      r->dt_pre_mig = 0;
-       if (tprev) {
-               r->dt_run = t - tprev;
-@@ -2323,6 +2332,9 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
-                               pr_debug("time travel: wakeup time for task > previous sched_switch event\n");
-                       else
-                               r->dt_delay = tprev - r->ready_to_run;
-+
-+                      if ((r->migrated > r->ready_to_run) && (r->migrated < tprev))
-+                              r->dt_pre_mig = r->migrated - r->ready_to_run;
-               }
-               if (r->last_time > tprev)
-@@ -2346,6 +2358,7 @@ static void timehist_update_runtime_stats(struct thread_runtime *r,
-       r->total_sleep_time   += r->dt_sleep;
-       r->total_iowait_time  += r->dt_iowait;
-       r->total_preempt_time += r->dt_preempt;
-+      r->total_pre_mig_time += r->dt_pre_mig;
- }
- static bool is_idle_sample(struct perf_sample *sample,
-@@ -2762,9 +2775,13 @@ static int timehist_migrate_task_event(const struct perf_tool *tool,
-               return -1;
-       tr->migrations++;
-+      tr->migrated = sample->time;
-       /* show migrations if requested */
--      timehist_print_migration_event(sched, evsel, sample, machine, thread);
-+      if (sched->show_migrations) {
-+              timehist_print_migration_event(sched, evsel, sample,
-+                                                      machine, thread);
-+      }
-       return 0;
- }
-@@ -2916,11 +2933,13 @@ static int timehist_sched_change_event(const struct perf_tool *tool,
-               /* last state is used to determine where to account wait time */
-               tr->last_state = state;
--              /* sched out event for task so reset ready to run time */
-+              /* sched out event for task so reset ready to run time and migrated time */
-               if (state == 'R')
-                       tr->ready_to_run = t;
-               else
-                       tr->ready_to_run = 0;
-+
-+              tr->migrated = 0;
-       }
-       evsel__save_time(evsel, sample->time, sample->cpu);
-@@ -3363,8 +3382,8 @@ static int perf_sched__timehist(struct perf_sched *sched)
-               goto out;
-       }
--      if (sched->show_migrations &&
--          perf_session__set_tracepoints_handlers(session, migrate_handlers))
-+      if ((sched->show_migrations || sched->pre_migrations) &&
-+              perf_session__set_tracepoints_handlers(session, migrate_handlers))
-               goto out;
-       /* pre-allocate struct for per-CPU idle stats */
-@@ -3919,6 +3938,7 @@ int cmd_sched(int argc, const char **argv)
-       OPT_BOOLEAN(0, "show-prio", &sched.show_prio, "Show task priority"),
-       OPT_STRING(0, "prio", &sched.prio_str, "prio",
-                  "analyze events only for given task priority(ies)"),
-+      OPT_BOOLEAN('P', "pre-migrations", &sched.pre_migrations, "Show pre-migration wait time"),
-       OPT_PARENT(sched_options)
-       };
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-sched-use-thread__put-in-free_idle_threads.patch b/queue-6.12/perf-sched-use-thread__put-in-free_idle_threads.patch
deleted file mode 100644 (file)
index ae14c52..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From 4a601c1324dcd54899d2639c80a9be567ac4ed77 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 11:17:03 -0300
-Subject: perf sched: Use thread__put() in free_idle_threads()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit a99d6394cd48fed75b1d24733d5afe6837a61a3f ]
-
-free_idle_threads() calls thread__delete() directly instead of
-thread__put(), bypassing the reference counting lifecycle.  Under
-REFCNT_CHECKING builds, this leaks the pointer handle since
-thread__delete() frees the object without going through the refcount
-wrapper.
-
-The idle threads are created via thread__new() (refcount=1) in
-get_idle_thread().  Callers get additional references via thread__get()
-which they release with thread__put().  free_idle_threads() drops the
-base reference â€” thread__put() is the correct call, matching the
-thread__new() acquisition.
-
-Fixes: 49394a2a24c7 ("perf sched timehist: Introduce timehist command")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: David Ahern <dsahern@gmail.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-sched.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index f3a03be9471aa0..8eb5c880a5b605 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -2489,7 +2489,7 @@ static void free_idle_threads(void)
-                       if (itr)
-                               thread__put(itr->last_thread);
--                      thread__delete(idle);
-+                      thread__put(idle);
-               }
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-stat-bounds-check-cpu-index-in-topology-aggrega.patch b/queue-6.12/perf-stat-bounds-check-cpu-index-in-topology-aggrega.patch
deleted file mode 100644 (file)
index b63f68f..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-From 5709b7f407201e5c57ad5b40736ae821ac5ab396 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 5 Jun 2026 10:59:11 -0300
-Subject: perf stat: Bounds-check CPU index in topology aggregation callbacks
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 52e69b1c5b606b513d403dd4addc784c27a0c8e2 ]
-
-Six perf_env__get_*_aggr_by_cpu() functions access env->cpu[cpu.cpu]
-after only checking cpu.cpu != -1.  env->cpu[] is allocated with
-env->nr_cpus_avail entries, so a CPU index from an untrusted perf.data
-file that exceeds that count causes an out-of-bounds heap read.
-
-Replace the != -1 guard with >= 0 && < env->nr_cpus_avail in all six
-functions.  The >= 0 check also catches -1 and any other negative values
-that could bypass the old check.
-
-Affected functions:
-  - perf_env__get_socket_aggr_by_cpu()
-  - perf_env__get_die_aggr_by_cpu()
-  - perf_env__get_cache_aggr_by_cpu()
-  - perf_env__get_cluster_aggr_by_cpu()
-  - perf_env__get_core_aggr_by_cpu()
-  - perf_env__get_cpu_aggr_by_cpu()
-
-Fixes: 68d702f7a120 ("perf stat report: Add support to initialize aggr_map from file")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Ian Rogers <irogers@google.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-stat.c | 13 +++++++------
- 1 file changed, 7 insertions(+), 6 deletions(-)
-
-diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
-index e476598de80836..4331820b199601 100644
---- a/tools/perf/builtin-stat.c
-+++ b/tools/perf/builtin-stat.c
-@@ -1561,7 +1561,8 @@ static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu,
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
--      if (cpu.cpu != -1)
-+      /* env->cpu[] has env->nr_cpus_avail entries; reject untrusted indices */
-+      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail)
-               id.socket = env->cpu[cpu.cpu].socket_id;
-       return id;
-@@ -1572,7 +1573,7 @@ static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, voi
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
--      if (cpu.cpu != -1) {
-+      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-               /*
-                * die_id is relative to socket, so start
-                * with the socket ID and then add die to
-@@ -1628,7 +1629,7 @@ static struct aggr_cpu_id perf_env__get_cache_aggr_by_cpu(struct perf_cpu cpu,
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
--      if (cpu.cpu != -1) {
-+      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-               u32 cache_level = (perf_stat.aggr_level) ?: stat_config.aggr_level;
-               id.socket = env->cpu[cpu.cpu].socket_id;
-@@ -1645,7 +1646,7 @@ static struct aggr_cpu_id perf_env__get_cluster_aggr_by_cpu(struct perf_cpu cpu,
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
--      if (cpu.cpu != -1) {
-+      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-               id.socket = env->cpu[cpu.cpu].socket_id;
-               id.die = env->cpu[cpu.cpu].die_id;
-               id.cluster = env->cpu[cpu.cpu].cluster_id;
-@@ -1659,7 +1660,7 @@ static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, vo
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
--      if (cpu.cpu != -1) {
-+      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-               /*
-                * core_id is relative to socket, die and cluster, we need a
-                * global id. So we set socket, die id, cluster id and core id.
-@@ -1678,7 +1679,7 @@ static struct aggr_cpu_id perf_env__get_cpu_aggr_by_cpu(struct perf_cpu cpu, voi
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
--      if (cpu.cpu != -1) {
-+      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-               /*
-                * core_id is relative to socket and die,
-                * we need a global id. So we set
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-stat-introduce-perf_env__get_cpu_topology-to-gu.patch b/queue-6.12/perf-stat-introduce-perf_env__get_cpu_topology-to-gu.patch
deleted file mode 100644 (file)
index 7e4ecd8..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-From dcdee7052257bab063c42acf931aa4e905732e31 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 11:17:45 -0300
-Subject: perf stat: Introduce perf_env__get_cpu_topology() to guard NULL
- env->cpu
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit afa4363a91a19dff65dceb7fbce7bba689bbc854 ]
-
-process_cpu_topology() in header.c frees env->cpu on old-format
-perf.data files that predate topology information, but leaves
-nr_cpus_avail set.  The six perf_env__get_*_aggr_by_cpu() functions
-in builtin-stat.c pass the bounds check but dereference a NULL
-env->cpu pointer, crashing on old recordings.
-
-Introduce perf_env__get_cpu_topology() as a safe accessor that
-validates env->cpu, cpu.cpu >= 0, and cpu.cpu < nr_cpus_avail in
-one place, returning a struct cpu_topology_map pointer or NULL.
-Convert all six topology aggregation callbacks to use it.
-
-Fixes: 88031a0de7d68d13 ("perf stat: Switch to cpu version of cpu_map__get()")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-stat.c | 51 +++++++++++++++++++++------------------
- tools/perf/util/env.h     | 14 +++++++++++
- 2 files changed, 42 insertions(+), 23 deletions(-)
-
-diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
-index 4331820b199601..2b8b3354e0cf7b 100644
---- a/tools/perf/builtin-stat.c
-+++ b/tools/perf/builtin-stat.c
-@@ -1560,10 +1560,10 @@ static struct aggr_cpu_id perf_env__get_socket_aggr_by_cpu(struct perf_cpu cpu,
- {
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
-+      struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
--      /* env->cpu[] has env->nr_cpus_avail entries; reject untrusted indices */
--      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail)
--              id.socket = env->cpu[cpu.cpu].socket_id;
-+      if (topo)
-+              id.socket = topo->socket_id;
-       return id;
- }
-@@ -1572,15 +1572,16 @@ static struct aggr_cpu_id perf_env__get_die_aggr_by_cpu(struct perf_cpu cpu, voi
- {
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
-+      struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
--      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-+      if (topo) {
-               /*
-                * die_id is relative to socket, so start
-                * with the socket ID and then add die to
-                * make a unique ID.
-                */
--              id.socket = env->cpu[cpu.cpu].socket_id;
--              id.die = env->cpu[cpu.cpu].die_id;
-+              id.socket = topo->socket_id;
-+              id.die = topo->die_id;
-       }
-       return id;
-@@ -1628,12 +1629,13 @@ static struct aggr_cpu_id perf_env__get_cache_aggr_by_cpu(struct perf_cpu cpu,
- {
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
-+      struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
--      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-+      if (topo) {
-               u32 cache_level = (perf_stat.aggr_level) ?: stat_config.aggr_level;
--              id.socket = env->cpu[cpu.cpu].socket_id;
--              id.die = env->cpu[cpu.cpu].die_id;
-+              id.socket = topo->socket_id;
-+              id.die = topo->die_id;
-               perf_env__get_cache_id_for_cpu(cpu, env, cache_level, &id);
-       }
-@@ -1645,11 +1647,12 @@ static struct aggr_cpu_id perf_env__get_cluster_aggr_by_cpu(struct perf_cpu cpu,
- {
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
-+      struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
--      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
--              id.socket = env->cpu[cpu.cpu].socket_id;
--              id.die = env->cpu[cpu.cpu].die_id;
--              id.cluster = env->cpu[cpu.cpu].cluster_id;
-+      if (topo) {
-+              id.socket = topo->socket_id;
-+              id.die = topo->die_id;
-+              id.cluster = topo->cluster_id;
-       }
-       return id;
-@@ -1659,16 +1662,17 @@ static struct aggr_cpu_id perf_env__get_core_aggr_by_cpu(struct perf_cpu cpu, vo
- {
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
-+      struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
--      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-+      if (topo) {
-               /*
-                * core_id is relative to socket, die and cluster, we need a
-                * global id. So we set socket, die id, cluster id and core id.
-                */
--              id.socket = env->cpu[cpu.cpu].socket_id;
--              id.die = env->cpu[cpu.cpu].die_id;
--              id.cluster = env->cpu[cpu.cpu].cluster_id;
--              id.core = env->cpu[cpu.cpu].core_id;
-+              id.socket = topo->socket_id;
-+              id.die = topo->die_id;
-+              id.cluster = topo->cluster_id;
-+              id.core = topo->core_id;
-       }
-       return id;
-@@ -1678,18 +1682,19 @@ static struct aggr_cpu_id perf_env__get_cpu_aggr_by_cpu(struct perf_cpu cpu, voi
- {
-       struct perf_env *env = data;
-       struct aggr_cpu_id id = aggr_cpu_id__empty();
-+      struct cpu_topology_map *topo = perf_env__get_cpu_topology(env, cpu);
--      if (cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail) {
-+      if (topo) {
-               /*
-                * core_id is relative to socket and die,
-                * we need a global id. So we set
-                * socket, die id and core id
-                */
--              id.socket = env->cpu[cpu.cpu].socket_id;
--              id.die = env->cpu[cpu.cpu].die_id;
--              id.core = env->cpu[cpu.cpu].core_id;
--              id.cpu = cpu;
-+              id.socket = topo->socket_id;
-+              id.die = topo->die_id;
-+              id.core = topo->core_id;
-       }
-+      id.cpu = cpu;
-       return id;
- }
-diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
-index 38de0af2a68081..0ba95396ecf04d 100644
---- a/tools/perf/util/env.h
-+++ b/tools/perf/util/env.h
-@@ -167,6 +167,20 @@ const char *perf_env__pmu_mappings(struct perf_env *env);
- int perf_env__read_cpu_topology_map(struct perf_env *env);
-+/*
-+ * Safe accessor for env->cpu[] topology array.  env->cpu can be NULL when
-+ * reading old-format perf.data that predates topology information â€”
-+ * process_cpu_topology() in header.c frees it while nr_cpus_avail remains
-+ * set, so callers must not index env->cpu[] without this check.
-+ */
-+static inline struct cpu_topology_map *
-+perf_env__get_cpu_topology(struct perf_env *env, struct perf_cpu cpu)
-+{
-+      if (env->cpu && cpu.cpu >= 0 && cpu.cpu < env->nr_cpus_avail)
-+              return &env->cpu[cpu.cpu];
-+      return NULL;
-+}
-+
- void cpu_cache_level__free(struct cpu_cache_level *cache);
- const char *perf_env__arch(struct perf_env *env);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch b/queue-6.12/perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch
deleted file mode 100644 (file)
index e375d3e..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-From fdedca7203c4d5eb76d80a8d22d49483a19177be Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 8 Jun 2026 08:12:34 -0300
-Subject: perf symbols: Add bounds checks to elf_read_build_id() note iteration
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit acc56d3941fc2997a5a21ea9233a8ac3d87c4f2f ]
-
-elf_read_build_id() iterates ELF notes using pointer arithmetic
-driven by n_namesz and n_descsz from the note headers.  Neither
-the note header read nor the subsequent name/desc advances are
-checked against the section boundary.  A malformed ELF file with
-oversized note sizes causes out-of-bounds reads past the section
-data buffer.
-
-Add two bounds checks: verify the note header fits within the
-remaining section data, and verify that namesz + descsz (after
-alignment) fits before advancing the pointer.
-
-Fixes: fd7a346ea292074e ("perf symbols: Filename__read_build_id should look at .notes section too")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-elf.c | 18 ++++++++++++++++--
- 1 file changed, 16 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index 029a1ef9b287b4..90f11a6eb19fea 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -909,10 +909,24 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
-       ptr = data->d_buf;
-       while (ptr < (data->d_buf + data->d_size)) {
-               GElf_Nhdr *nhdr = ptr;
--              size_t namesz = NOTE_ALIGN(nhdr->n_namesz),
--                     descsz = NOTE_ALIGN(nhdr->n_descsz);
-+              size_t namesz, descsz, remaining;
-               const char *name;
-+              /* ensure the note header fits within the section */
-+              if (ptr + sizeof(*nhdr) > data->d_buf + data->d_size)
-+                      break;
-+
-+              namesz = NOTE_ALIGN(nhdr->n_namesz);
-+              descsz = NOTE_ALIGN(nhdr->n_descsz);
-+
-+              /* validate individually to avoid size_t overflow on 32-bit */
-+              remaining = data->d_buf + data->d_size - ptr - sizeof(*nhdr);
-+              if (namesz > remaining || descsz > remaining - namesz) {
-+                      pr_warning("%s: oversized note: n_namesz=%u, n_descsz=%u\n",
-+                                 __func__, nhdr->n_namesz, nhdr->n_descsz);
-+                      break;
-+              }
-+
-               ptr += sizeof(*nhdr);
-               name = ptr;
-               ptr += namesz;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-add-bounds-checks-to-read_build_id-note.patch b/queue-6.12/perf-symbols-add-bounds-checks-to-read_build_id-note.patch
deleted file mode 100644 (file)
index aed9fce..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-From 387e0c7eed13e14603281c3399a3cc768a2ebf81 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 16:09:45 -0300
-Subject: perf symbols: Add bounds checks to read_build_id() note iteration in
- minimal build
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 52e582e316c48c53bb3082c29f7862ebc554087e ]
-
-symbol-minimal.c's read_build_id() iterates ELF notes with the same
-pattern as symbol-elf.c's elf_read_build_id(): pointer arithmetic
-driven by n_namesz and n_descsz from 32-bit note header fields,
-without validating that the name and desc fit within the note section
-data.  A malformed ELF file with oversized note sizes causes
-out-of-bounds reads past the section data buffer.
-
-Add the same bounds check as the libelf path: validate namesz and
-descsz individually against remaining data before advancing the
-pointer, avoiding size_t overflow on 32-bit.
-
-Fixes: b691f64360ecec49 ("perf symbols: Implement poor man's ELF parser")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-minimal.c | 11 ++++++++++-
- 1 file changed, 10 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
-index f114f75ebeb989..12ef02bbf2eea8 100644
---- a/tools/perf/util/symbol-minimal.c
-+++ b/tools/perf/util/symbol-minimal.c
-@@ -1,3 +1,4 @@
-+#include "debug.h"
- #include "dso.h"
- #include "symbol.h"
- #include "symsrc.h"
-@@ -44,7 +45,7 @@ static int read_build_id(void *note_data, size_t note_len, struct build_id *bid,
-       ptr = note_data;
-       while (ptr < (note_data + note_len)) {
-               const char *name;
--              size_t namesz, descsz;
-+              size_t namesz, descsz, remaining;
-               nhdr = ptr;
-               if (need_swap) {
-@@ -56,6 +57,14 @@ static int read_build_id(void *note_data, size_t note_len, struct build_id *bid,
-               namesz = NOTE_ALIGN(nhdr->n_namesz);
-               descsz = NOTE_ALIGN(nhdr->n_descsz);
-+              /* validate individually to avoid size_t overflow on 32-bit */
-+              remaining = note_data + note_len - ptr - sizeof(*nhdr);
-+              if (namesz > remaining || descsz > remaining - namesz) {
-+                      pr_warning("%s: oversized note: n_namesz=%u, n_descsz=%u\n",
-+                                 __func__, nhdr->n_namesz, nhdr->n_descsz);
-+                      break;
-+              }
-+
-               ptr += sizeof(*nhdr);
-               name = ptr;
-               ptr += namesz;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch b/queue-6.12/perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch
deleted file mode 100644 (file)
index be137f2..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From d89e7b0b17c6423161131b145e615a92dedeaa1b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 21:05:15 -0300
-Subject: perf symbols: Bounds-check .gnu_debuglink section data
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 9c74f0aab398cb32ab250401f323c0fdc9a3a496 ]
-
-filename__read_debuglink() copies .gnu_debuglink section data into a
-caller-provided buffer via:
-
-    strncpy(debuglink, data->d_buf, size);
-
-where size is PATH_MAX.  If the ELF section is smaller than size and
-lacks a null terminator, strncpy reads past data->d_buf into adjacent
-memory.  A malformed ELF file can trigger this, potentially causing a
-segfault or leaking heap data.
-
-Additionally, strncpy does not guarantee null termination when the
-source fills the buffer.
-
-Replace with an explicit memcpy bounded by both the output buffer
-size and the actual section data size (data->d_size), followed by
-explicit null termination.
-
-Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-elf.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index 3968645e1dfa08..923e7d1d8aad8a 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -1160,7 +1160,14 @@ int filename__read_debuglink(const char *filename, char *debuglink,
-               goto out_elf_end;
-       /* the start of this section is a zero-terminated string */
--      strncpy(debuglink, data->d_buf, size);
-+      if (data->d_size > 0) {
-+              size_t len = min(size - 1, data->d_size);
-+
-+              memcpy(debuglink, data->d_buf, len);
-+              debuglink[len] = '\0';
-+      } else {
-+              debuglink[0] = '\0';
-+      }
-       err = 0;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch b/queue-6.12/perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch
deleted file mode 100644 (file)
index e8906b3..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-From f9a65684f7758d8381ec0b0f974618a7020a293b Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 22:40:20 -0300
-Subject: perf symbols: Bounds-check descsz in sysfs__read_build_id() GNU
- fallback
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 1b4e9fbdeabc549965e70ac0cd8095d57ff6df06 ]
-
-When sysfs__read_build_id() matches NT_GNU_BUILD_ID with the right
-namesz but the name content is not "GNU", it falls back to reading
-descsz bytes into the stack buffer bf[BUFSIZ]:
-
-    } else if (read(fd, bf, descsz) != (ssize_t)descsz)
-
-Unlike the else branch which validates namesz + descsz against
-sizeof(bf), this path passes descsz directly to read() without any
-bounds check.  A crafted sysfs file with a large n_descsz overflows
-the 8192-byte stack buffer.
-
-Add a descsz > sizeof(bf) check before the read, breaking out of
-the loop on oversized values.
-
-Fixes: e5a1845fc0aeca85 ("perf symbols: Split out util/symbol-elf.c")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-elf.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index 923e7d1d8aad8a..c7fcbb8fb644c3 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -1060,8 +1060,13 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid)
-                                       err = 0;
-                                       break;
-                               }
--                      } else if (read(fd, bf, descsz) != (ssize_t)descsz)
--                              break;
-+                      } else {
-+                              /* descsz from untrusted file â€” clamp to buffer */
-+                              if (descsz > sizeof(bf))
-+                                      break;
-+                              if (read(fd, bf, descsz) != (ssize_t)descsz)
-+                                      break;
-+                      }
-               } else {
-                       size_t n;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-break-infinite-loop-on-zero-filled-note.patch b/queue-6.12/perf-symbols-break-infinite-loop-on-zero-filled-note.patch
deleted file mode 100644 (file)
index 8f3e254..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 45ed275d8a4e761c4f0a446da25672469f952d5a Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 19:32:22 -0300
-Subject: perf symbols: Break infinite loop on zero-filled notes in
- sysfs__read_build_id()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 063c647b24f640657d6d9e2e90d620ea3ee19ae6 ]
-
-sysfs__read_build_id() iterates ELF note headers from sysfs files in a
-while(1) loop.  If the file contains a zero-filled note header (both
-n_namesz and n_descsz are 0), the code computes n = namesz + descsz = 0
-and calls read(fd, bf, 0).  read() with count 0 returns 0, which
-matches the expected (ssize_t)n value, so the error check passes and
-the loop repeats â€” reading the same zero bytes and spinning forever.
-
-This can happen with corrupted or zero-padded sysfs pseudo-files.
-
-Add a check for n == 0 before the read, since no valid ELF note has
-both name and description of zero length.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-elf.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index 4ba49975970a9b..bb3c1b68fe3706 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -1092,6 +1092,9 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid)
-                       } else {
-                               n = namesz + descsz;
-                       }
-+                      /* no valid note has both namesz and descsz zero */
-+                      if (n == 0)
-+                              break;
-                       if (read(fd, bf, n) != (ssize_t)n)
-                               break;
-               }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-fix-bswap-copy-paste-error-for-32-bit-e.patch b/queue-6.12/perf-symbols-fix-bswap-copy-paste-error-for-32-bit-e.patch
deleted file mode 100644 (file)
index bba07d4..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-From e1c9337037614d1a0761570fec1b31035874a2c9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 19:28:43 -0300
-Subject: perf symbols: Fix bswap copy-paste error for 32-bit ELF p_filesz
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 081b387c7397498c583b1ba7c2fdaf4c6da6b538 ]
-
-filename__read_build_id() byte-swaps 32-bit ELF program headers on
-cross-endian files, but line 178 passes p_offset to bswap_32() instead
-of p_filesz:
-
-  hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_offset);
-
-This clobbers p_filesz with the already-swapped p_offset value.  The
-64-bit path on line 182 is correct and swaps p_filesz from p_filesz.
-
-The consequence is that the PT_NOTE segment read uses the wrong size,
-which can cause either a short read (missing the build-id) or an
-oversized read (reading past the segment into adjacent data).
-
-Fix by swapping the correct field.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: fef8f648bb47726d ("perf symbol: Fix use-after-free in filename__read_build_id")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-minimal.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
-index 12ef02bbf2eea8..68f5a2622bd8bc 100644
---- a/tools/perf/util/symbol-minimal.c
-+++ b/tools/perf/util/symbol-minimal.c
-@@ -168,7 +168,7 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
-                       if (elf32) {
-                               hdrs.phdr32[i].p_type = bswap_32(hdrs.phdr32[i].p_type);
-                               hdrs.phdr32[i].p_offset = bswap_32(hdrs.phdr32[i].p_offset);
--                              hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_offset);
-+                              hdrs.phdr32[i].p_filesz = bswap_32(hdrs.phdr32[i].p_filesz);
-                       } else {
-                               hdrs.phdr64[i].p_type = bswap_32(hdrs.phdr64[i].p_type);
-                               hdrs.phdr64[i].p_offset = bswap_64(hdrs.phdr64[i].p_offset);
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch b/queue-6.12/perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch
deleted file mode 100644 (file)
index c1b2c63..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-From 2a6cdac63f01f3a6bce30d35b78eb1e730353523 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 21:04:50 -0300
-Subject: perf symbols: Fix signed overflow in sysfs__read_build_id() size
- check
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 6eaa8ee3e2abe5112e80e94c27196bb175689469 ]
-
-sysfs__read_build_id() reads ELF note headers from sysfs files.  The
-note's namesz and descsz fields are used to compute the skip size:
-
-    int n = namesz + descsz;
-    if (n > (int)sizeof(bf))
-
-Both namesz and descsz are size_t from NOTE_ALIGN() of 32-bit note
-header fields.  Their sum can exceed INT_MAX, overflowing the signed
-int n to a negative value.  The check n > sizeof(bf) then evaluates
-false (negative < positive in signed comparison), and read(fd, bf, n)
-reinterprets the negative n as a huge size_t count â€” the kernel writes
-up to MAX_RW_COUNT bytes into the 8192-byte stack buffer.
-
-In practice the overflow is bounded by the sysfs file's actual size,
-so a real sysfs notes file won't trigger it organically.  But crafted
-input (e.g. via a mounted debugfs/sysfs image) could.
-
-Fix by validating namesz and descsz individually against the buffer
-size before summing, and change n to size_t to avoid the signed
-overflow entirely.
-
-Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-elf.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
-index 61f931997f2ecf..3968645e1dfa08 100644
---- a/tools/perf/util/symbol-elf.c
-+++ b/tools/perf/util/symbol-elf.c
-@@ -1063,14 +1063,17 @@ int sysfs__read_build_id(const char *filename, struct build_id *bid)
-                       } else if (read(fd, bf, descsz) != (ssize_t)descsz)
-                               break;
-               } else {
--                      int n = namesz + descsz;
-+                      size_t n;
--                      if (n > (int)sizeof(bf)) {
-+                      /* int sum of namesz+descsz can overflow negative, bypassing size check */
-+                      if (namesz > sizeof(bf) || descsz > sizeof(bf) - namesz) {
-                               n = sizeof(bf);
-                               pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n",
-                                        __func__, filename, nhdr.n_namesz, nhdr.n_descsz);
-+                      } else {
-+                              n = namesz + descsz;
-                       }
--                      if (read(fd, bf, n) != n)
-+                      if (read(fd, bf, n) != (ssize_t)n)
-                               break;
-               }
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-symbols-validate-p_filesz-before-use-in-filenam.patch b/queue-6.12/perf-symbols-validate-p_filesz-before-use-in-filenam.patch
deleted file mode 100644 (file)
index 5ef4e50..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-From 43fa6a64625d86439ef972c35b5f664d9082158e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 19:29:34 -0300
-Subject: perf symbols: Validate p_filesz before use in
- filename__read_build_id()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 2a3716544359d4312c81b0fa909a13301186da17 ]
-
-filename__read_build_id() stores ELF p_filesz in a ssize_t variable.
-A crafted 32-bit ELF with p_filesz = 0xFFFFFFFF produces ssize_t value
--1.  The comparison `p_filesz > buf_size` evaluates false because signed
--1 is less than any non-negative buf_size, so the realloc is skipped and
-buf remains NULL.
-
-The subsequent read(fd, NULL, -1) returns -1, which equals p_filesz,
-passing the error check.  read_build_id() then dereferences the NULL
-buffer.
-
-Add an explicit check for p_filesz <= 0 before using the value,
-catching both zero-length and sign-wrapped negative sizes from crafted
-ELF files.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: ba0b7081f7a521d7 ("perf symbol-minimal: Fix ehdr reading in filename__read_build_id")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/symbol-minimal.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
-index 68f5a2622bd8bc..f6bef8fcc75f97 100644
---- a/tools/perf/util/symbol-minimal.c
-+++ b/tools/perf/util/symbol-minimal.c
-@@ -179,6 +179,9 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
-                       continue;
-               p_filesz = elf32 ? hdrs.phdr32[i].p_filesz : hdrs.phdr64[i].p_filesz;
-+              /* ssize_t can go negative with crafted ELF p_filesz values */
-+              if (p_filesz <= 0)
-+                      continue;
-               if (p_filesz > buf_size) {
-                       void *tmp;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-synthetic-events-fix-stale-build-id-in-module-mmap2-records.patch b/queue-6.12/perf-synthetic-events-fix-stale-build-id-in-module-mmap2-records.patch
deleted file mode 100644 (file)
index ba4a63f..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-From 35b16a7a2c4fc458304447128b86514ce9f70f3c Mon Sep 17 00:00:00 2001
-From: Chuck Lever <chuck.lever@oracle.com>
-Date: Tue, 10 Mar 2026 13:59:51 -0400
-Subject: perf synthetic-events: Fix stale build ID in module MMAP2 records
-
-From: Chuck Lever <chuck.lever@oracle.com>
-
-commit 35b16a7a2c4fc458304447128b86514ce9f70f3c upstream.
-
-perf_event__synthesize_modules() allocates a single union perf_event and
-reuses it across every kernel module callback.
-
-After the first module is processed, perf_record_mmap2__read_build_id()
-sets PERF_RECORD_MISC_MMAP_BUILD_ID in header.misc and writes that
-module's build ID into the event.
-
-On subsequent iterations the callback overwrites start, len, pid, and
-filename for the next module but never clears the stale build ID fields
-or the MMAP_BUILD_ID flag.
-
-When perf_record_mmap2__read_build_id() runs for the second module it
-sees the flag, reads the stale build ID into a dso_id, and
-__dso__improve_id() permanently poisons the DSO with the wrong build ID.
-
-Every module after the first therefore receives the first module's build
-ID in its MMAP2 record.
-
-On a system with the sunrpc and nfsd modules loaded, this causes perf
-script and perf report to show [unknown] for all module symbols.
-
-The latent bug has existed since commit d9f2ecbc5e47fca7 ("perf dso:
-Move build_id to dso_id") introduced the PERF_RECORD_MISC_MMAP_BUILD_ID
-check in perf_record_mmap2__read_build_id().
-
-Commit 53b00ff358dc75b1 ("perf record: Make --buildid-mmap the default")
-then exposed it to all users by making the MMAP2-with-build-ID path the
-default.  Both commits were merged in the same series.
-
-Clear the MMAP_BUILD_ID flag and zero the build_id union before each
-call to perf_record_mmap2__read_build_id() so that every module starts
-with a clean slate.
-
-Fixes: d9f2ecbc5e47fca7 ("perf dso: Move build_id to dso_id")
-Reviewed-by: Ian Rogers <irogers@google.com>
-Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
-Cc: Adrian Hunter <adrian.hunter@intel.com>
-Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
-Cc: Ian Rogers <irogers@google.com>
-Cc: Ingo Molnar <mingo@redhat.com>
-Cc: James Clark <james.clark@linaro.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Mark Rutland <mark.rutland@arm.com>
-Cc: Namhyung Kim <namhyung@kernel.org>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- tools/perf/util/synthetic-events.c |    5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/tools/perf/util/synthetic-events.c
-+++ b/tools/perf/util/synthetic-events.c
-@@ -702,6 +702,11 @@ static int perf_event__synthesize_module
-               memcpy(event->mmap2.filename, dso__long_name(dso), dso__long_name_len(dso) + 1);
-+              /* Clear stale build ID from previous module iteration */
-+              event->mmap2.header.misc &= ~PERF_RECORD_MISC_MMAP_BUILD_ID;
-+              memset(event->mmap2.build_id, 0, sizeof(event->mmap2.build_id));
-+              event->mmap2.build_id_size = 0;
-+
-               perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false);
-       } else {
-               size = PERF_ALIGN(dso__long_name_len(dso) + 1, sizeof(u64));
diff --git a/queue-6.12/perf-timechart-fix-cpu2y-oob-read-on-untrusted-cpu-i.patch b/queue-6.12/perf-timechart-fix-cpu2y-oob-read-on-untrusted-cpu-i.patch
deleted file mode 100644 (file)
index 39e0ffd..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-From e04782c639cb25bbc4a3a833c7d1b70f8d5d728e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 11:21:32 -0300
-Subject: perf timechart: Fix cpu2y() OOB read on untrusted CPU index
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit e2496db45bfd8dfb6154ec415798fee330f1cc0a ]
-
-cpu2y() indexes topology_map[cpu] without bounds checking.  The array
-is allocated with nr_cpus entries (from env->nr_cpus_online), but
-callers pass sample CPU values from perf.data which can exceed that
-size with cross-machine recordings.
-
-Track the topology_map allocation size and bounds-check the CPU
-argument in cpu2y() before indexing.  Out-of-bounds CPUs fall back
-to the identity mapping (cpu2slot(cpu)), which is the same behavior
-as when no topology is available.
-
-Fixes: c507999790438cde ("perf timechart: Add support for topology")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Stanislav Fomichev <stfomichev@yandex-team.ru>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/svghelper.c | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
-index 2b04f47f4db0f0..d553a40f2c6add 100644
---- a/tools/perf/util/svghelper.c
-+++ b/tools/perf/util/svghelper.c
-@@ -46,13 +46,13 @@ static double cpu2slot(int cpu)
- }
- static int *topology_map;
-+static int topology_map_size;
- static double cpu2y(int cpu)
- {
--      if (topology_map)
-+      if (topology_map && cpu >= 0 && cpu < topology_map_size)
-               return cpu2slot(topology_map[cpu]) * SLOT_MULT;
--      else
--              return cpu2slot(cpu) * SLOT_MULT;
-+      return cpu2slot(cpu) * SLOT_MULT;
- }
- static double time2pixels(u64 __time)
-@@ -734,7 +734,8 @@ static int str_to_bitmap(char *s, cpumask_t *b, int nr_cpus)
-               return -1;
-       perf_cpu_map__for_each_cpu(cpu, idx, map) {
--              if (cpu.cpu >= nr_cpus) {
-+              /* perf_cpu_map__new("") returns cpu.cpu == -1 */
-+              if (cpu.cpu < 0 || cpu.cpu >= nr_cpus) {
-                       ret = -1;
-                       break;
-               }
-@@ -792,6 +793,7 @@ int svg_build_topology_map(struct perf_env *env)
-               fprintf(stderr, "topology: no memory\n");
-               goto exit;
-       }
-+      topology_map_size = nr_cpus;
-       for (i = 0; i < nr_cpus; i++)
-               topology_map[i] = -1;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-add-bounds-check-to-cpu__get_node.patch b/queue-6.12/perf-tools-add-bounds-check-to-cpu__get_node.patch
deleted file mode 100644 (file)
index 56aa3e4..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-From ee957ddaa2bc90819907eb28fef12305728eff63 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 4 Jun 2026 18:14:23 -0300
-Subject: perf tools: Add bounds check to cpu__get_node()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 1e7921d7227de5da0dfc167943092c823ec7e49b ]
-
-cpu__get_node() accesses cpunode_map[cpu.cpu] without checking against
-max_cpu_num, the allocation size of cpunode_map.  Callers such as
-builtin-kmem.c:evsel__process_alloc_event() pass sample->cpu from
-perf.data events, which may exceed the host's CPU count when analyzing
-cross-machine recordings.
-
-Add a bounds check against max_cpu_num before indexing, returning -1
-for out-of-range values.  This is a central fix that protects all
-callers.
-
-Fixes: 86895b480a2f ("perf stat: Add --per-node agregation support")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cpumap.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
-index 27094211edd8a8..7cafa6672d4fb4 100644
---- a/tools/perf/util/cpumap.c
-+++ b/tools/perf/util/cpumap.c
-@@ -522,6 +522,10 @@ int cpu__get_node(struct perf_cpu cpu)
-               return -1;
-       }
-+      /* cpunode_map allocated for max_cpu_num entries; input may be untrusted */
-+      if (cpu.cpu < 0 || cpu.cpu >= max_cpu_num.cpu)
-+              return -1;
-+
-       return cpunode_map[cpu.cpu];
- }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch b/queue-6.12/perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch
deleted file mode 100644 (file)
index 098c96e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-From 866c203d6775ec390b55d33780deaadb0efd0c36 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 20:37:52 -0300
-Subject: perf tools: Fix get_max_num() size_t underflow on empty sysfs file
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 0a012113bb3a44482c163f16f4db03ccaa37a339 ]
-
-get_max_num() reads a sysfs file (cpu/possible, cpu/present, or
-node/possible) and scans backward from the end to find the last
-number.  If the file is empty, filename__read_str() returns num == 0.
-The loop `while (--num)` decrements the size_t from 0 to SIZE_MAX,
-reading backward across the heap until a comma or hyphen is found
-or unmapped memory is hit.
-
-Add an early return for empty files before the backward scan.
-
-Fixes: 7780c25bae59fd04 ("perf tools: Allow ability to map cpus to nodes easily")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Don Zickus <dzickus@redhat.com>
-Cc: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cpumap.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
-index 7cafa6672d4fb4..388755a4eda2f2 100644
---- a/tools/perf/util/cpumap.c
-+++ b/tools/perf/util/cpumap.c
-@@ -402,6 +402,12 @@ static int get_max_num(char *path, int *max)
-       buf[num] = '\0';
-+      /* empty file â€” nothing to parse */
-+      if (num == 0) {
-+              err = -1;
-+              goto out;
-+      }
-+
-       /* start on the right, to find highest node num */
-       while (--num) {
-               if ((buf[num] == ',') || (buf[num] == '-')) {
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch b/queue-6.12/perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch
deleted file mode 100644 (file)
index 6d1e2ae..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-From d023b81607362e43e1b5a79f05cad140a08029f7 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sun, 7 Jun 2026 22:37:55 -0300
-Subject: perf tools: Fix thread__set_comm_from_proc() on empty comm file
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 31d596054550f793508abe7dd593853ece47d428 ]
-
-thread__set_comm_from_proc() calls procfs__read_str() then strips
-the trailing newline via comm[sz - 1] = '\0'.  procfs__read_str()
-allocates the buffer before reading, so on an empty /proc/pid/comm
-(reachable during late exit teardown) it returns success with sz = 0
-and an unterminated heap buffer.
-
-The sz - 1 underflow was the original sashiko finding: it writes a
-null byte before the allocation.  But even with a sz > 0 guard on
-the newline strip, the unterminated buffer would still be passed to
-thread__set_comm() which calls strlen() â€” an unbounded heap read.
-
-Fix by treating sz == 0 as failure: free the buffer and return -1.
-This is consistent with pmu.c's perf_pmu__parse_scale/unit which
-already treat len == 0 from filename__read_str as an error.
-
-Fixes: 2f3027ac28bf6bc3 ("perf thread: Introduce method to set comm from /proc/pid/self")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/thread.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
-index 309d573eac9a94..64f29370d59962 100644
---- a/tools/perf/util/thread.c
-+++ b/tools/perf/util/thread.c
-@@ -273,6 +273,11 @@ int thread__set_comm_from_proc(struct thread *thread)
-       if (!(snprintf(path, sizeof(path), "%d/task/%d/comm",
-                      thread__pid(thread), thread__tid(thread)) >= (int)sizeof(path)) &&
-           procfs__read_str(path, &comm, &sz) == 0) {
-+              /* sz==0: read got nothing, e.g. race during exit teardown */
-+              if (sz == 0) {
-+                      free(comm);
-+                      return -1;
-+              }
-               comm[sz - 1] = '\0';
-               err = thread__set_comm(thread, comm, 0);
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch b/queue-6.12/perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch
deleted file mode 100644 (file)
index fb999cb..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From af74646eb6980580abfe8fcabf8f83c6102d4225 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 4 Jun 2026 12:55:06 -0300
-Subject: perf tools: Guard test_bit from out-of-bounds sample CPU
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit a5498ccf8079fc91c938f122ff9697b0c526b2fd ]
-
-When PERF_SAMPLE_CPU is absent from a perf.data file, sample->cpu is
-initialized to (u32)-1 by evsel__parse_sample().  Five call sites pass
-this value directly to test_bit(sample->cpu, cpu_bitmap), reading
-massively out of bounds past the DECLARE_BITMAP(..., MAX_NR_CPUS)
-allocation of 4096 bits.
-
-Add a sample->cpu >= MAX_NR_CPUS guard before each test_bit() call,
-matching the existing safe pattern in builtin-kwork.c.  This catches
-both the (u32)-1 sentinel and any corrupted CPU value exceeding the
-bitmap size.
-
-Fixes: 5d67be97f890 ("perf report/annotate/script: Add option to specify a CPU range")
-Cc: Anton Blanchard <anton@samba.org>
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/builtin-annotate.c | 3 ++-
- tools/perf/builtin-diff.c     | 3 ++-
- tools/perf/builtin-report.c   | 3 ++-
- tools/perf/builtin-sched.c    | 6 ++++--
- 4 files changed, 10 insertions(+), 5 deletions(-)
-
-diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
-index 3dc6197ef3fa6d..3882f400065c7c 100644
---- a/tools/perf/builtin-annotate.c
-+++ b/tools/perf/builtin-annotate.c
-@@ -298,7 +298,8 @@ static int process_sample_event(const struct perf_tool *tool,
-               goto out_put;
-       }
--      if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
-+      if (ann->cpu_list && (sample->cpu >= MAX_NR_CPUS ||
-+                           !test_bit(sample->cpu, ann->cpu_bitmap)))
-               goto out_put;
-       if (!al.filtered &&
-diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
-index 82fb7773e03e62..bf5611e1f5e006 100644
---- a/tools/perf/builtin-diff.c
-+++ b/tools/perf/builtin-diff.c
-@@ -417,7 +417,8 @@ static int diff__process_sample_event(const struct perf_tool *tool,
-               goto out;
-       }
--      if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) {
-+      if (cpu_list && (sample->cpu >= MAX_NR_CPUS ||
-+                      !test_bit(sample->cpu, cpu_bitmap))) {
-               ret = 0;
-               goto out;
-       }
-diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
-index 8700c39680662a..86cbca6285a51a 100644
---- a/tools/perf/builtin-report.c
-+++ b/tools/perf/builtin-report.c
-@@ -301,7 +301,8 @@ static int process_sample_event(const struct perf_tool *tool,
-       if (symbol_conf.hide_unresolved && al.sym == NULL)
-               goto out_put;
--      if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
-+      if (rep->cpu_list && (sample->cpu >= MAX_NR_CPUS ||
-+                           !test_bit(sample->cpu, rep->cpu_bitmap)))
-               goto out_put;
-       if (sort__mode == SORT_MODE__BRANCH) {
-diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
-index fa5f00d47e6277..6d7106fb1c0cbc 100644
---- a/tools/perf/builtin-sched.c
-+++ b/tools/perf/builtin-sched.c
-@@ -2185,7 +2185,8 @@ static void timehist_print_sample(struct perf_sched *sched,
-       char nstr[30];
-       u64 wait_time;
--      if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
-+      if (cpu_list && (sample->cpu >= MAX_NR_CPUS ||
-+                      !test_bit(sample->cpu, cpu_bitmap)))
-               return;
-       timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
-@@ -2823,7 +2824,8 @@ static int timehist_sched_change_event(const struct perf_tool *tool,
-       }
-       if (!sched->idle_hist || thread__tid(thread) == 0) {
--              if (!cpu_list || test_bit(sample->cpu, cpu_bitmap))
-+              if (!cpu_list || (sample->cpu < MAX_NR_CPUS &&
-+                               test_bit(sample->cpu, cpu_bitmap)))
-                       timehist_update_runtime_stats(tr, t, tprev);
-               if (sched->idle_hist) {
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-use-perf_env__get_cpu_topology-in-machine.patch b/queue-6.12/perf-tools-use-perf_env__get_cpu_topology-in-machine.patch
deleted file mode 100644 (file)
index 7a76ab1..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-From 6bb248d226457f4db505e74b659d8af2022b8d69 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 20:57:49 -0300
-Subject: perf tools: Use perf_env__get_cpu_topology() in machine__resolve()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 5484b43a0ec8231c36fba6ead654cb72dbba8b8f ]
-
-machine__resolve() accesses env->cpu[al->cpu].socket_id after checking
-al->cpu >= 0 and env->cpu != NULL, but without validating al->cpu
-against env->nr_cpus_avail.  Since al->cpu comes from the untrusted
-perf.data sample, a crafted file with a large CPU index causes an
-out-of-bounds heap read.
-
-Use perf_env__get_cpu_topology() which validates both NULL and bounds.
-Also bounds-check al->cpu before the cast to struct perf_cpu (int16_t):
-without this, values like 65536 silently truncate to 0, bypassing the
-accessor's internal check and returning CPU 0's topology.
-
-Fixes: 0c4c4debb0adda4c ("perf tools: Add processor socket info to hist_entry and addr_location")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Kan Liang <kan.liang@intel.com>
-Cc: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/event.c | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
-index aac96d5d191700..1e5085817e8250 100644
---- a/tools/perf/util/event.c
-+++ b/tools/perf/util/event.c
-@@ -12,6 +12,7 @@
- #include <linux/zalloc.h>
- #include "cpumap.h"
- #include "dso.h"
-+#include "env.h"
- #include "event.h"
- #include "debug.h"
- #include "hist.h"
-@@ -763,8 +764,18 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
-       if (al->cpu >= 0) {
-               struct perf_env *env = machine->env;
--              if (env && env->cpu)
--                      al->socket = env->cpu[al->cpu].socket_id;
-+              /*
-+               * Bounds-check al->cpu (s32) before casting to struct perf_cpu
-+               * (int16_t): without this, e.g. 65536 truncates to 0 and silently
-+               * returns CPU 0's topology.  Can go once perf_cpu.cpu is widened.
-+               */
-+              if (env && al->cpu < env->nr_cpus_avail) {
-+                      struct cpu_topology_map *topo;
-+
-+                      topo = perf_env__get_cpu_topology(env, (struct perf_cpu){ al->cpu });
-+                      if (topo)
-+                              al->socket = topo->socket_id;
-+              }
-       }
-       if (al->map) {
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch b/queue-6.12/perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch
deleted file mode 100644 (file)
index 13fc5d1..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-From 6860af79c10d3ed1e8095d743f4ff35e60cfb829 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Sat, 6 Jun 2026 20:43:52 -0300
-Subject: perf tools: Use scnprintf() in cpu_map__snprint() to prevent overflow
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 7953a3a9b8e02e98c6e6958f291d0ae22393e46a ]
-
-cpu_map__snprint() accumulates snprintf() return values in ret.
-snprintf() returns the number of characters that *would have been
-written* on truncation, not the actual count.  When a fragmented CPU
-list exceeds the buffer, ret grows past size, causing `size - ret` to
-underflow (both are size_t), and subsequent snprintf() calls write
-past the end of the caller's stack buffer.
-
-Switch to scnprintf() which returns the actual number of characters
-written, making ret accumulation safe by construction.
-
-Fixes: a24020e6b7cf6eb8 ("perf tools: Change cpu_map__fprintf output")
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Reviewed-by: Ian Rogers <irogers@google.com>
-Cc: Jiri Olsa <jolsa@kernel.org>
-Cc: Ian Rogers <irogers@google.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/cpumap.c | 18 +++++++++---------
- 1 file changed, 9 insertions(+), 9 deletions(-)
-
-diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
-index 388755a4eda2f2..f6a5daffeeb10e 100644
---- a/tools/perf/util/cpumap.c
-+++ b/tools/perf/util/cpumap.c
-@@ -625,21 +625,21 @@ size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size)
-               if (start == -1) {
-                       start = i;
-                       if (last) {
--                              ret += snprintf(buf + ret, size - ret,
--                                              "%s%d", COMMA,
--                                              perf_cpu_map__cpu(map, i).cpu);
-+                              ret += scnprintf(buf + ret, size - ret,
-+                                               "%s%d", COMMA,
-+                                               perf_cpu_map__cpu(map, i).cpu);
-                       }
-               } else if (((i - start) != (cpu.cpu - perf_cpu_map__cpu(map, start).cpu)) || last) {
-                       int end = i - 1;
-                       if (start == end) {
--                              ret += snprintf(buf + ret, size - ret,
--                                              "%s%d", COMMA,
--                                              perf_cpu_map__cpu(map, start).cpu);
-+                              ret += scnprintf(buf + ret, size - ret,
-+                                               "%s%d", COMMA,
-+                                               perf_cpu_map__cpu(map, start).cpu);
-                       } else {
--                              ret += snprintf(buf + ret, size - ret,
--                                              "%s%d-%d", COMMA,
--                                              perf_cpu_map__cpu(map, start).cpu, perf_cpu_map__cpu(map, end).cpu);
-+                              ret += scnprintf(buf + ret, size - ret,
-+                                               "%s%d-%d", COMMA,
-+                                               perf_cpu_map__cpu(map, start).cpu, perf_cpu_map__cpu(map, end).cpu);
-                       }
-                       first = false;
-                       start = i;
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-use-snprintf-for-root_dir-path-constructi.patch b/queue-6.12/perf-tools-use-snprintf-for-root_dir-path-constructi.patch
deleted file mode 100644 (file)
index 6186ebb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-From 5de6778c41c7e0c4eb12f4f80835a6458786ec1e Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Wed, 10 Jun 2026 20:34:38 -0300
-Subject: perf tools: Use snprintf() for root_dir path construction
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 7b0df6f4d498b1608afccfd6dffb264e6da91693 ]
-
-get_kernel_version() in machine.c and dso__load_guest_kernel_sym() in
-symbol.c use sprintf() to construct paths by prepending root_dir to
-"/proc/version" and "/proc/kallsyms" respectively.  Both write into
-PATH_MAX stack buffers, but root_dir comes from --guestmount or KVM
-configuration and is not length-checked.  A root_dir at or near
-PATH_MAX causes a stack buffer overflow.
-
-Switch to snprintf() with sizeof(path) to prevent overflow.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: a1645ce12adb6c9c ("perf: 'perf kvm' tool for monitoring guest performance from host")
-Cc: Zhang Yanmin <yanmin_zhang@linux.intel.com>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/machine.c | 2 +-
- tools/perf/util/symbol.c  | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
-index 557853fcb5479b..71d3d034ba095e 100644
---- a/tools/perf/util/machine.c
-+++ b/tools/perf/util/machine.c
-@@ -1294,7 +1294,7 @@ static char *get_kernel_version(const char *root_dir)
-       char *name, *tmp;
-       const char *prefix = "Linux version ";
--      sprintf(version, "%s/proc/version", root_dir);
-+      snprintf(version, sizeof(version), "%s/proc/version", root_dir);
-       file = fopen(version, "r");
-       if (!file)
-               return NULL;
-diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
-index e792dd22b54983..92b31c1a73a839 100644
---- a/tools/perf/util/symbol.c
-+++ b/tools/perf/util/symbol.c
-@@ -2270,7 +2270,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
-               if (!kallsyms_filename)
-                       return -1;
-       } else {
--              sprintf(path, "%s/proc/kallsyms", machine->root_dir);
-+              snprintf(path, sizeof(path), "%s/proc/kallsyms", machine->root_dir);
-               kallsyms_filename = path;
-       }
--- 
-2.53.0
-
diff --git a/queue-6.12/perf-tools-use-snprintf-in-dso__read_running_kernel_.patch b/queue-6.12/perf-tools-use-snprintf-in-dso__read_running_kernel_.patch
deleted file mode 100644 (file)
index 7a4f360..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 40724299dc87fbe1e19146b0004764408ebc6c6c Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Mon, 8 Jun 2026 07:04:25 -0300
-Subject: perf tools: Use snprintf() in dso__read_running_kernel_build_id()
-
-From: Arnaldo Carvalho de Melo <acme@redhat.com>
-
-[ Upstream commit 2ea64782a428bed74f595961e651ceb8c4c5bf22 ]
-
-dso__read_running_kernel_build_id() uses sprintf() to format a sysfs
-path from machine->root_dir into a PATH_MAX buffer.  If root_dir is
-close to PATH_MAX in length, appending "/sys/kernel/notes" (18 bytes)
-overflows the stack buffer.
-
-Switch to snprintf() with sizeof(path) to prevent the overflow.
-
-Reported-by: sashiko-bot <sashiko-bot@kernel.org>
-Fixes: cdd059d731eeb466 ("perf tools: Move dso_* related functions into dso object")
-Cc: Jiri Olsa <jolsa@kernel.org>
-Assisted-by: Claude:claude-opus-4.6
-Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- tools/perf/util/dso.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
-index 9792c8d38a314b..0c8492ea530fc1 100644
---- a/tools/perf/util/dso.c
-+++ b/tools/perf/util/dso.c
-@@ -1676,7 +1676,7 @@ void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
-       if (machine__is_default_guest(machine))
-               return;
--      sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
-+      snprintf(path, sizeof(path), "%s/sys/kernel/notes", machine->root_dir);
-       sysfs__read_build_id(path, &bid);
-       dso__set_build_id(dso, &bid);
- }
--- 
-2.53.0
-
index 00259a3c74eb7b2bc757feaed1e68f59abd977cd..a9b951b34c50f6cd5169958fbc4db7176f7a149a 100644 (file)
@@ -411,7 +411,6 @@ eventpoll-rename-epi-next-and-txlist-for-clarity.patch
 eventpoll-fix-epoll_wait-report-false-negative.patch
 gpiolib-acpi-only-trigger-activeboth-interrupts-on-b.patch
 staging-nvec-fix-use-after-free-in-nvec_rx_completed.patch
-perf-debuginfo-fix-libdw-api-contract-violations.patch
 coresight-cti-fix-dt-filter-signals-silently-ignored.patch
 coresight-etm4x-correct-trcvmidcctlr1-save-and-resto.patch
 pci-aspm-don-t-reconfigure-aspm-entering-low-power-s.patch
@@ -419,27 +418,19 @@ pci-introduce-named-defines-for-pci-rom.patch
 pci-check-rom-header-and-data-structure-addr-before-.patch
 x86-platform-olpc-xo15-drop-wakeup-source-on-driver-.patch
 platform-x86-xo15-ebook-fix-wakeup-source-and-gpe-ha.patch
-perf-sched-add-missing-mmap2-handler-in-timehist.patch
 pci-loongson-do-not-ignore-downstream-devices-on-ext.patch
 rust-alloc-fix-assert-in-vec-reserve-doc-test.patch
 bus-mhi-ep-fix-potential-deadlock-in-mhi_ep_reset_wo.patch
 pci-qcom-set-max-opp-before-dbi-access-during-resume.patch
 phy-phy-can-transceiver-check-driver-match-and-drive.patch
-perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch
 clk-at91-sam9x7-fix-gmac_gclk-clock-definition.patch
 coresight-fix-source-not-disabled-on-idr_alloc_u32-f.patch
 mailbox-mtk-adsp-fix-uaf-during-device-teardown.patch
-perf-arm-spe-use-metadata-to-decide-the-data-source-.patch
-perf-arm-spe-use-arm_spe_op_branch_eret-when-synthes.patch
-perf-arm-spe-correctly-set-sample-flags.patch
-perf-arm-spe-add-branch-stack.patch
-perf-inject-add-convert-callchain-option.patch
 staging-most-video-avoid-double-free-on-video-regist.patch
 usb-host-max3421-fix-shift-out-of-bounds-in-max3421_.patch
 usb-host-max3421-reject-hub-port-requests-for-non-ex.patch
 char-tlclk-fix-use-after-free-in-tlclk_cleanup.patch
 pci-qcom-disable-aspm-l0s-for-sa8775p.patch
-perf-header-sanity-check-header_event_desc-attr.size.patch
 iio-light-si1133-reset-counter-to-prevent-race-condi.patch
 iio-light-si1133-prevent-race-condition-on-timeout.patch
 iio-magnetometer-ak8975-fix-potential-kernel-stack-m.patch
@@ -454,25 +445,6 @@ drm-amd-display-add-missing-kdoc-for-allm-parameters.patch
 thunderbolt-debugfs-fix-margining-error-counter-buff.patch
 dmaengine-imx-sdma-refine-spba-bus-searching-in-prob.patch
 perf-fix-off-by-one-stack-buffer-overflow-in-kallsym.patch
-perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch
-perf-sched-fix-thread-reference-leak-in-latency_swit.patch
-perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch
-perf-sched-fix-null-dereference-in-latency_runtime_e.patch
-perf-tools-add-bounds-check-to-cpu__get_node.patch
-perf-sched-fix-register_pid-overflow-strcpy-and-bug_.patch
-perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch
-perf-stat-bounds-check-cpu-index-in-topology-aggrega.patch
-perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch
-perf-c2c-bounds-check-cpu-ids-in-setup_nodes-topolog.patch
-perf-sched-clean-up-idle_threads-entry-on-init-failu.patch
-perf-sched-timehist-add-pre-migration-wait-time-opti.patch
-perf-sched-fix-thread-leaks-in-perf-sched-timehist.patch
-perf-sched-use-thread__put-in-free_idle_threads.patch
-perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch
-perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch
-perf-stat-introduce-perf_env__get_cpu_topology-to-gu.patch
-perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch
-perf-timechart-fix-cpu2y-oob-read-on-untrusted-cpu-i.patch
 dmaengine-qcom-gpi-set-dma_private-capability.patch
 dmaengine-fix-possible-use-after-free.patch
 dmaengine-dma-axi-dmac-properly-free-struct-axi_dmac.patch
@@ -493,14 +465,7 @@ pci-mediatek-fix-operator-precedence-in-pcie_fts_num.patch
 pci-meson-propagate-devm_add_action_or_reset-failure.patch
 pci-meson-add-missing-remove-callback.patch
 fs-ntfs3-resize-log-one_page_buf-when-adopting-on-di.patch
-perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch
-perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch
-perf-tools-use-perf_env__get_cpu_topology-in-machine.patch
 pci-rcar-host-remove-unused-list_head-res.patch
-perf-sched-bounds-check-prio-before-test_bit-in-time.patch
-perf-sched-fix-idle-hist-callchain-display-using-wro.patch
-perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch
-perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch
 xprtrdma-fix-ep-kref-imbalance-on-addr_change.patch
 xprtrdma-initialize-re_id-before-removal-registratio.patch
 xprtrdma-check-frwr_wp_create-during-connect.patch
@@ -510,25 +475,9 @@ xprtrdma-fix-bcall-rep-leak-and-unbounded-peek.patch
 xprtrdma-sanitize-the-reply-credit-grant-after-parsi.patch
 xprtrdma-repost-receive-buffers-for-malformed-replie.patch
 xprtrdma-return-sendctx-slot-after-send-preparation-.patch
-perf-cs-etm-queue-context-packets-for-frontend.patch
-perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch
-perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch
 tools-lib-api-fix-missing-null-termination-in-filena.patch
-perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch
-perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch
-perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch
-perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch
-perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch
-perf-dso-use-lock-annotations-to-fix-asan-deadlock.patch
-perf-dso-add-support-for-reading-the-e_machine-type-.patch
-perf-build-id-change-sprintf-functions-to-snprintf.patch
-perf-dso-move-build_id-to-dso_id.patch
-perf-tools-use-snprintf-in-dso__read_running_kernel_.patch
 tools-lib-api-fix-filename__write_int-writing-uninit.patch
 tools-lib-api-fix-mount_overload-snprintf-truncation.patch
-perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch
-perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch
-perf-symbols-add-bounds-checks-to-read_build_id-note.patch
 pci-mediatek-fix-possible-truncation-in-mtk_pcie_par.patch
 pci-mediatek-use-actual-physical-address-instead-of-.patch
 revert-pci-msi-unmap-msi-x-region-on-error.patch
@@ -547,25 +496,12 @@ i3c-master-make-hot-join-workqueue-freezable-to-bloc.patch
 i3c-master-prevent-reuse-of-dynamic-address-on-devic.patch
 apparmor-fix-label-can-not-be-immediately-before-a-d.patch
 sparc-led-avoid-trimming-a-newline-from-empty-writes.patch
-perf-maps-add-maps__mutate_mapping.patch
-perf-symbols-fix-bswap-copy-paste-error-for-32-bit-e.patch
-perf-symbols-validate-p_filesz-before-use-in-filenam.patch
-perf-symbols-break-infinite-loop-on-zero-filled-note.patch
-perf-tools-use-snprintf-for-root_dir-path-constructi.patch
-perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch
-perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch
-perf-remove-redundant-kernel.h-include.patch
-perf-cs-etm-reject-cpu-ids-that-would-overflow-signe.patch
 gpio-mlxbf3-fail-probe-if-gpiochip-registration-fail.patch
 drm-i915-clear-crtc-color-blob-pointers-after-droppi.patch
 spi-dw-fix-wrong-baudr-setting-after-resume.patch
 xfrm-fix-xfrm-state-cache-insertion-race.patch
 xfrm-annotate-data-races-around-xfrm_policy_count-an.patch
 xfrm-validate-selector-family-and-prefixlen-during-m.patch
-perf-machine-use-snprintf-for-guestmount-path-constr.patch
-perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch
-perf-cs-etm-require-full-global-header-in-auxtrace_i.patch
-perf-cs-etm-bounds-check-cpu-in-cs_etm__get_queue.patch
 asoc-tlv320aic3x-restrict-clkdiv-bypass-q-values-in-.patch
 drm-amdkfd-avoid-double-unpin-of-doorbell-mmio-bos-o.patch
 drm-amdkfd-fix-list_del-corruption-in-kfd_criu_resum.patch
@@ -1245,17 +1181,13 @@ kvm-arm64-fix-propagation-of-tlbi-level-in-kvm_pgtable_stage2_relax_perms.patch
 bpf-reject-bpf_map_type_inode_storage-creation-if-bpf-lsm-is-uninitialized.patch
 perf-x86-amd-brs-fix-kernel-address-leakage.patch
 dibs-loopback-validate-offset-and-size-in-move_data.patch
-perf-inject-with-convert-callchain-ignore-the-dummy-event-for-dwarf-stacks.patch
 seqlock-fix-scoped_seqlock_read-kernel-doc.patch
-perf-callchain-handle-multiple-address-spaces.patch
 ksmbd-fix-durable-reconnect-double-bind-race-in-ksmbd_reopen_durable_fd.patch
 rtnetlink-make-per-netns-rtnl-dereference-helpers-to-macro.patch
-perf-arm-spe-use-old-behavior-when-opening-old-spe-files.patch
 net-airoha-fix-channel-configuration-for-ets-qdisc.patch
 jiffies-cast-to-unsigned-long-in-secs_to_jiffies-conversion.patch
 afs-fix-afs_atcell_get_link-to-check-if-ws_cell-is-unset-first.patch
 afs-fix-afs_dynroot_readdir-to-not-use-the-rcu-read-lock.patch
-perf-libunwind-arm64-fix-missing-close-parens-in-an-if-statement.patch
 crypto-ccp-fix-__sev_snp_shutdown_locked.patch
 crypto-ccp-fix-dereferencing-uninitialized-error-pointer.patch
 crypto-ccp-fix-snp-panic-notifier-unregistration.patch
@@ -1263,13 +1195,10 @@ udp_tunnel-fix-deadlock-in-udp_tunnel_nic_set_port_priv.patch
 bluetooth-hci_core-remove-check-of-bdaddr_any-in-hci_conn_hash_lookup_big_state.patch
 bluetooth-hci_sync-fix-attempting-to-send-hci_disconnect-to-bis-handle.patch
 crypto-ccp-always-pass-in-an-error-pointer-to-__sev_platform_shutdown_locked.patch
-perf-build-id-ensure-snprintf-string-is-empty-when-size-is-0.patch
 i40e-drop-udp_tunnel_get_rx_info-call-from-i40e_open.patch
 ice-drop-udp_tunnel_get_rx_info-call-from-ndo_open.patch
 crypto-ccp-fix-leaking-the-same-page-twice.patch
-perf-synthetic-events-fix-stale-build-id-in-module-mmap2-records.patch
 bluetooth-l2cap-fix-regressions-caused-by-reusing-ident.patch
 bluetooth-6lowpan-fix-using-chan-conn-as-indication-to-no-remote-netdev.patch
 bluetooth-l2cap-fix-tx-ident-leak-for-commands-without-a-response.patch
 dpll-fix-null-pointer-dereference-in-dpll_msg_add_pin_ref_sync.patch
-perf-build-id-fix-off-by-one-bug-when-printing-kernel-module-build-id.patch