From: Greg Kroah-Hartman Date: Wed, 22 Jul 2026 13:12:41 +0000 (+0200) Subject: drop perf 6.6.y patches X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=28dcfd23389661a6b073313d556470895b57a6ae;p=thirdparty%2Fkernel%2Fstable-queue.git drop perf 6.6.y patches --- diff --git a/queue-6.6/perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch b/queue-6.6/perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch deleted file mode 100644 index 02797def3f..0000000000 --- a/queue-6.6/perf-bpf-add-null-check-for-btf__type_by_id-in-synth.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 7d6caf1ff6937044097543083be38383753541b8 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Fixes: fc462ac75b36daaa ("perf bpf: Extract logic to create program names from perf_event__synthesize_one_bpf_prog()") -Cc: Song Liu -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 2a9b90aa181fc7..dfebec3a6e71f5 100644 ---- a/tools/perf/util/bpf-event.c -+++ b/tools/perf/util/bpf-event.c -@@ -137,7 +137,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.6/perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch b/queue-6.6/perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch deleted file mode 100644 index b5614c6ba1..0000000000 --- a/queue-6.6/perf-bpf-bounds-check-array-offsets-in-bpil_offs_to_.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 605b77e2620e491be8423925ea582bd495a8a62b Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Fixes: 6ac22d036f86c4e2 ("perf bpf: Pull in bpf_program__get_prog_info_linear()") -Cc: Dave Marchevsky -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 80b1d2b3729ba4..a20ed281bcaf80 100644 ---- a/tools/perf/util/bpf-utils.c -+++ b/tools/perf/util/bpf-utils.c -@@ -246,6 +246,7 @@ void bpil_offs_to_addr(struct perf_bpil *info_linear) - for (i = PERF_BPIL_FIRST_ARRAY; i < PERF_BPIL_LAST_ARRAY; ++i) { - struct bpil_array_desc *desc; - __u64 addr, offs; -+ __u32 count, size; - - if ((info_linear->arrays & (1UL << i)) == 0) - continue; -@@ -253,6 +254,21 @@ void bpil_offs_to_addr(struct perf_bpil *info_linear) - desc = bpil_array_desc + i; - 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.6/perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch b/queue-6.6/perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch deleted file mode 100644 index f5e208ddd8..0000000000 --- a/queue-6.6/perf-bpf-use-scnprintf-in-snprintf_hex-and-synthesiz.patch +++ /dev/null @@ -1,68 +0,0 @@ -From e7baf646051162917349fadfcb36fa6d21f5d1d1 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Reviewed-by: Ian Rogers -Cc: Song Liu -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 1573d6b6478d28..2a9b90aa181fc7 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; - } - -@@ -131,7 +131,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) { -@@ -144,9 +144,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.6/perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch b/queue-6.6/perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch deleted file mode 100644 index d00eec9e8a..0000000000 --- a/queue-6.6/perf-bpf-validate-func_info_rec_size-and-sub_id-in-s.patch +++ /dev/null @@ -1,53 +0,0 @@ -From c065155cbbc4380b6f28c5eb82fec453c7a6d674 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Fixes: 7b612e291a5affb1 ("perf tools: Synthesize PERF_RECORD_* for loaded BPF programs") -Cc: Song Liu -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 dfebec3a6e71f5..fb4eb16c7b5bae 100644 ---- a/tools/perf/util/bpf-event.c -+++ b/tools/perf/util/bpf-event.c -@@ -134,7 +134,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.6/perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch b/queue-6.6/perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch deleted file mode 100644 index 592a862858..0000000000 --- a/queue-6.6/perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 622825444cd491f971326c84ac8bbf00a4c62d90 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Jiri Olsa -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 a4cf9de7a7b5a9..207b9c863aeea5 100644 ---- a/tools/perf/builtin-c2c.c -+++ b/tools/perf/builtin-c2c.c -@@ -229,6 +229,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); - } - -@@ -246,6 +250,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) { -@@ -345,7 +353,12 @@ static int process_sample_event(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; - -@@ -362,7 +375,9 @@ static int process_sample_event(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.6/perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch b/queue-6.6/perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch deleted file mode 100644 index 08d5131a9b..0000000000 --- a/queue-6.6/perf-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch +++ /dev/null @@ -1,43 +0,0 @@ -From baadde6e6db8689ad107050bbc1372f89c3a3398 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Jiri Olsa -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 207b9c863aeea5..96ca35c4f3062c 100644 ---- a/tools/perf/builtin-c2c.c -+++ b/tools/perf/builtin-c2c.c -@@ -215,6 +215,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.6/perf-cs-etm-create-decoders-after-both-aux-and-hw_id.patch b/queue-6.6/perf-cs-etm-create-decoders-after-both-aux-and-hw_id.patch deleted file mode 100644 index 25fa099c61..0000000000 --- a/queue-6.6/perf-cs-etm-create-decoders-after-both-aux-and-hw_id.patch +++ /dev/null @@ -1,370 +0,0 @@ -From a4bb4c43b7536bcb0c71edd33966b85e47453fac Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Mon, 22 Jul 2024 11:11:43 +0100 -Subject: perf cs-etm: Create decoders after both AUX and HW_ID search passes - -From: James Clark - -[ Upstream commit b6aa0de9a53a231eb068ce1e62b5e7ec9e30e627 ] - -Both of these passes gather information about how to create the -decoders. AUX records determine formatted/unformatted, and the HW_IDs -determine the traceID/metadata mappings. - -Therefore it makes sense to cache the information and wait until both -passes are over until creating the decoders, rather than creating them -at the first HW_ID found. - -This will allow a simplification of the creation process where -cs_etm_queue->traceid_list will exclusively used to create the decoders, -rather than the current two methods depending on whether the trace is -formatted or not. - -Previously the sample CPU from the AUX record was used to initialize -the decoder CPU, but actually sample CPU == AUX queue index in per-CPU -mode, so saving the sample CPU isn't required. - -Similarly formatted/unformatted was used upfront to create the decoders, -but now it's cached until later. - -Reviewed-by: Anshuman Khandual -Reviewed-by: Mike Leach -Signed-off-by: James Clark -Signed-off-by: James Clark -Tested-by: Ganapatrao Kulkarni -Tested-by: Leo Yan -Acked-by: Suzuki Poulouse -Cc: Adrian Hunter -Cc: Alexander Shishkin -Cc: Alexandre Torgue -Cc: Ian Rogers -Cc: Ingo Molnar -Cc: Jiri Olsa -Cc: John Garry -Cc: Kan Liang -Cc: Leo Yan -Cc: Mark Rutland -Cc: Maxime Coquelin -Cc: Namhyung Kim -Cc: Peter Zijlstra -Cc: Will Deacon -Link: https://lore.kernel.org/r/20240722101202.26915-2-james.clark@linaro.org -Signed-off-by: Arnaldo Carvalho de Melo -Stable-dep-of: 68ca50bc0fa6 ("perf cs-etm: Queue context packets for frontend") -Signed-off-by: Sasha Levin ---- - tools/perf/util/cs-etm.c | 182 ++++++++++++++++++++++++--------------- - 1 file changed, 113 insertions(+), 69 deletions(-) - -diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c -index 1fb104357eebb8..9077072994b23b 100644 ---- a/tools/perf/util/cs-etm.c -+++ b/tools/perf/util/cs-etm.c -@@ -97,12 +97,19 @@ struct cs_etm_traceid_queue { - struct cs_etm_packet_queue packet_queue; - }; - -+enum cs_etm_format { -+ UNSET, -+ FORMATTED, -+ UNFORMATTED -+}; -+ - struct cs_etm_queue { - struct cs_etm_auxtrace *etm; - struct cs_etm_decoder *decoder; - struct auxtrace_buffer *buffer; - unsigned int queue_nr; - u8 pending_timestamp_chan_id; -+ enum cs_etm_format format; - u64 offset; - const unsigned char *buf; - size_t buf_len, buf_used; -@@ -693,7 +700,7 @@ static void cs_etm__set_trace_param_ete(struct cs_etm_trace_params *t_params, - - static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, -- bool formatted, -+ enum cs_etm_format format, - int sample_cpu, - int decoders) - { -@@ -702,7 +709,7 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, - u64 architecture; - - for (t_idx = 0; t_idx < decoders; t_idx++) { -- if (formatted) -+ if (format == FORMATTED) - m_idx = t_idx; - else { - m_idx = get_cpu_data_idx(etm, sample_cpu); -@@ -735,8 +742,7 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, - - static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params, - struct cs_etm_queue *etmq, -- enum cs_etm_decoder_operation mode, -- bool formatted) -+ enum cs_etm_decoder_operation mode) - { - int ret = -EINVAL; - -@@ -746,7 +752,7 @@ static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params, - d_params->packet_printer = cs_etm__packet_dump; - d_params->operation = mode; - d_params->data = etmq; -- d_params->formatted = formatted; -+ d_params->formatted = etmq->format == FORMATTED; - d_params->fsyncs = false; - d_params->hsyncs = false; - d_params->frame_aligned = true; -@@ -1038,81 +1044,34 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, - return ret; - } - --static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, -- bool formatted, int sample_cpu) -+static struct cs_etm_queue *cs_etm__alloc_queue(void) - { -- struct cs_etm_decoder_params d_params; -- struct cs_etm_trace_params *t_params = NULL; -- struct cs_etm_queue *etmq; -- /* -- * Each queue can only contain data from one CPU when unformatted, so only one decoder is -- * needed. -- */ -- int decoders = formatted ? etm->num_cpu : 1; -- -- etmq = zalloc(sizeof(*etmq)); -+ struct cs_etm_queue *etmq = zalloc(sizeof(*etmq)); - if (!etmq) - return NULL; - - etmq->traceid_queues_list = intlist__new(NULL); - if (!etmq->traceid_queues_list) -- goto out_free; -- -- /* Use metadata to fill in trace parameters for trace decoder */ -- t_params = zalloc(sizeof(*t_params) * decoders); -- -- if (!t_params) -- goto out_free; -- -- if (cs_etm__init_trace_params(t_params, etm, formatted, sample_cpu, decoders)) -- goto out_free; -- -- /* Set decoder parameters to decode trace packets */ -- if (cs_etm__init_decoder_params(&d_params, etmq, -- dump_trace ? CS_ETM_OPERATION_PRINT : -- CS_ETM_OPERATION_DECODE, -- formatted)) -- goto out_free; -- -- etmq->decoder = cs_etm_decoder__new(decoders, &d_params, -- t_params); -- -- if (!etmq->decoder) -- goto out_free; -- -- /* -- * Register a function to handle all memory accesses required by -- * the trace decoder library. -- */ -- if (cs_etm_decoder__add_mem_access_cb(etmq->decoder, -- 0x0L, ((u64) -1L), -- cs_etm__mem_access)) -- goto out_free_decoder; -+ free(etmq); - -- zfree(&t_params); - return etmq; -- --out_free_decoder: -- cs_etm_decoder__free(etmq->decoder); --out_free: -- intlist__delete(etmq->traceid_queues_list); -- free(etmq); -- -- return NULL; - } - - static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, - struct auxtrace_queue *queue, -- unsigned int queue_nr, -- bool formatted, -- int sample_cpu) -+ unsigned int queue_nr, enum cs_etm_format format) - { - struct cs_etm_queue *etmq = queue->priv; - -+ if (etmq && format != etmq->format) { -+ pr_err("CS_ETM: mixed formatted and unformatted trace not supported\n"); -+ return -EINVAL; -+ } -+ - if (list_empty(&queue->head) || etmq) - return 0; - -- etmq = cs_etm__alloc_queue(etm, formatted, sample_cpu); -+ etmq = cs_etm__alloc_queue(); - - if (!etmq) - return -ENOMEM; -@@ -1120,7 +1079,9 @@ static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, - queue->priv = etmq; - etmq->etm = etm; - etmq->queue_nr = queue_nr; -+ queue->cpu = queue_nr; /* Placeholder, may be reset to -1 in per-thread mode */ - etmq->offset = 0; -+ etmq->format = format; - - return 0; - } -@@ -2851,7 +2812,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session, - * formatted in piped mode (true). - */ - err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], -- idx, true, -1); -+ idx, FORMATTED); - if (err) - return err; - -@@ -2972,7 +2933,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o - union perf_event auxtrace_fragment; - __u64 aux_offset, aux_size; - __u32 idx; -- bool formatted; -+ enum cs_etm_format format; - - struct cs_etm_auxtrace *etm = container_of(session->auxtrace, - struct cs_etm_auxtrace, -@@ -3055,9 +3016,10 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o - return err; - - idx = auxtrace_event->idx; -- formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW); -- return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], -- idx, formatted, sample->cpu); -+ format = (aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW) ? -+ UNFORMATTED : FORMATTED; -+ -+ return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], idx, format); - } - - /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */ -@@ -3241,6 +3203,84 @@ static int cs_etm__clear_unused_trace_ids_metadata(int num_cpu, u64 **metadata) - return 0; - } - -+/* -+ * Use the data gathered by the peeks for HW_ID (trace ID mappings) and AUX -+ * (formatted or not) packets to create the decoders. -+ */ -+static int cs_etm__create_queue_decoders(struct cs_etm_queue *etmq) -+{ -+ struct cs_etm_decoder_params d_params; -+ -+ /* -+ * Each queue can only contain data from one CPU when unformatted, so only one decoder is -+ * needed. -+ */ -+ int decoders = etmq->format == FORMATTED ? etmq->etm->num_cpu : 1; -+ -+ /* Use metadata to fill in trace parameters for trace decoder */ -+ struct cs_etm_trace_params *t_params = zalloc(sizeof(*t_params) * decoders); -+ -+ if (!t_params) -+ goto out_free; -+ -+ if (cs_etm__init_trace_params(t_params, etmq->etm, etmq->format, -+ etmq->queue_nr, decoders)) -+ goto out_free; -+ -+ /* Set decoder parameters to decode trace packets */ -+ if (cs_etm__init_decoder_params(&d_params, etmq, -+ dump_trace ? CS_ETM_OPERATION_PRINT : -+ CS_ETM_OPERATION_DECODE)) -+ goto out_free; -+ -+ etmq->decoder = cs_etm_decoder__new(decoders, &d_params, -+ t_params); -+ -+ if (!etmq->decoder) -+ goto out_free; -+ -+ /* -+ * Register a function to handle all memory accesses required by -+ * the trace decoder library. -+ */ -+ if (cs_etm_decoder__add_mem_access_cb(etmq->decoder, -+ 0x0L, ((u64) -1L), -+ cs_etm__mem_access)) -+ goto out_free_decoder; -+ -+ zfree(&t_params); -+ return 0; -+ -+out_free_decoder: -+ cs_etm_decoder__free(etmq->decoder); -+out_free: -+ zfree(&t_params); -+ return -EINVAL; -+} -+ -+static int cs_etm__create_decoders(struct cs_etm_auxtrace *etm) -+{ -+ struct auxtrace_queues *queues = &etm->queues; -+ -+ for (unsigned int i = 0; i < queues->nr_queues; i++) { -+ bool empty = list_empty(&queues->queue_array[i].head); -+ struct cs_etm_queue *etmq = queues->queue_array[i].priv; -+ int ret; -+ -+ /* -+ * Don't create decoders for empty queues, mainly because -+ * etmq->format is unknown for empty queues. -+ */ -+ if (empty) -+ continue; -+ -+ ret = cs_etm__create_queue_decoders(etmq); -+ if (ret) -+ return ret; -+ } -+ return 0; -+} -+ - int cs_etm__process_auxtrace_info_full(union perf_event *event, - struct perf_session *session) - { -@@ -3389,6 +3429,10 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, - if (err) - goto err_free_queues; - -+ err = cs_etm__queue_aux_records(session); -+ if (err) -+ goto err_free_queues; -+ - /* - * Map Trace ID values to CPU metadata. - * -@@ -3411,7 +3455,7 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, - * flags if present. - */ - -- /* first scan for AUX_OUTPUT_HW_ID records to map trace ID values to CPU metadata */ -+ /* Scan for AUX_OUTPUT_HW_ID records to map trace ID values to CPU metadata */ - aux_hw_id_found = 0; - err = perf_session__peek_events(session, session->header.data_offset, - session->header.data_size, -@@ -3429,7 +3473,7 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, - if (err) - goto err_free_queues; - -- err = cs_etm__queue_aux_records(session); -+ err = cs_etm__create_decoders(etm); - if (err) - goto err_free_queues; - --- -2.53.0 - diff --git a/queue-6.6/perf-cs-etm-fix-incorrect-or-missing-decoder-for-raw.patch b/queue-6.6/perf-cs-etm-fix-incorrect-or-missing-decoder-for-raw.patch deleted file mode 100644 index 6534ed931a..0000000000 --- a/queue-6.6/perf-cs-etm-fix-incorrect-or-missing-decoder-for-raw.patch +++ /dev/null @@ -1,247 +0,0 @@ -From 332046fd6952b00536a2f5d92d8a0e36b299f362 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 10 Oct 2023 18:48:03 -0500 -Subject: perf cs-etm: Fix incorrect or missing decoder for raw trace - -From: Besar Wicaksono - -[ Upstream commit a16afcc58a8c5ebc65c852faf001f8f61f05e4ef ] - -The decoder creation for raw trace uses metadata from the first CPU. -On per-cpu mode, this metadata is incorrectly used for every decoder. -On per-process/per-thread traces, the first CPU is CPU0. If CPU0 trace -is not enabled, its metadata will be marked unused and the decoder is -not created. Perf report dump skips the decoding part because the -decoder is missing. - -To fix this, use metadata of the CPU associated with sample object. - -Signed-off-by: Besar Wicaksono -Reviewed-by: James Clark -Cc: suzuki.poulose@arm.com -Cc: mike.leach@linaro.org -Cc: jonathanh@nvidia.com -Cc: rwiley@nvidia.com -Cc: treding@nvidia.com -Cc: vsethi@nvidia.com -Cc: ywan@nvidia.com -Cc: linux-arm-kernel@lists.infradead.org -Cc: coresight@lists.linaro.org -Cc: linux-tegra@vger.kernel.org -Link: https://lore.kernel.org/r/20231010234803.5419-1-bwicaksono@nvidia.com -Signed-off-by: Namhyung Kim -Stable-dep-of: 68ca50bc0fa6 ("perf cs-etm: Queue context packets for frontend") -Signed-off-by: Sasha Levin ---- - tools/perf/util/cs-etm.c | 106 ++++++++++++++++++++++++--------------- - 1 file changed, 65 insertions(+), 41 deletions(-) - -diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c -index 799c104901b4ff..1fb104357eebb8 100644 ---- a/tools/perf/util/cs-etm.c -+++ b/tools/perf/util/cs-etm.c -@@ -283,22 +283,31 @@ static int cs_etm__metadata_set_trace_id(u8 trace_chan_id, u64 *cpu_metadata) - } - - /* -- * Get a metadata for a specific cpu from an array. -+ * Get a metadata index for a specific cpu from an array. - * - */ --static u64 *get_cpu_data(struct cs_etm_auxtrace *etm, int cpu) -+static int get_cpu_data_idx(struct cs_etm_auxtrace *etm, int cpu) - { - int i; -- u64 *metadata = NULL; - - for (i = 0; i < etm->num_cpu; i++) { - if (etm->metadata[i][CS_ETM_CPU] == (u64)cpu) { -- metadata = etm->metadata[i]; -- break; -+ return i; - } - } - -- return metadata; -+ return -1; -+} -+ -+/* -+ * Get a metadata for a specific cpu from an array. -+ * -+ */ -+static u64 *get_cpu_data(struct cs_etm_auxtrace *etm, int cpu) -+{ -+ int idx = get_cpu_data_idx(etm, cpu); -+ -+ return (idx != -1) ? etm->metadata[idx] : NULL; - } - - /* -@@ -641,66 +650,80 @@ static void cs_etm__packet_dump(const char *pkt_string) - } - - static void cs_etm__set_trace_param_etmv3(struct cs_etm_trace_params *t_params, -- struct cs_etm_auxtrace *etm, int idx, -- u32 etmidr) -+ struct cs_etm_auxtrace *etm, int t_idx, -+ int m_idx, u32 etmidr) - { - u64 **metadata = etm->metadata; - -- t_params[idx].protocol = cs_etm__get_v7_protocol_version(etmidr); -- t_params[idx].etmv3.reg_ctrl = metadata[idx][CS_ETM_ETMCR]; -- t_params[idx].etmv3.reg_trc_id = metadata[idx][CS_ETM_ETMTRACEIDR]; -+ t_params[t_idx].protocol = cs_etm__get_v7_protocol_version(etmidr); -+ t_params[t_idx].etmv3.reg_ctrl = metadata[m_idx][CS_ETM_ETMCR]; -+ t_params[t_idx].etmv3.reg_trc_id = metadata[m_idx][CS_ETM_ETMTRACEIDR]; - } - - static void cs_etm__set_trace_param_etmv4(struct cs_etm_trace_params *t_params, -- struct cs_etm_auxtrace *etm, int idx) -+ struct cs_etm_auxtrace *etm, int t_idx, -+ int m_idx) - { - u64 **metadata = etm->metadata; - -- t_params[idx].protocol = CS_ETM_PROTO_ETMV4i; -- t_params[idx].etmv4.reg_idr0 = metadata[idx][CS_ETMV4_TRCIDR0]; -- t_params[idx].etmv4.reg_idr1 = metadata[idx][CS_ETMV4_TRCIDR1]; -- t_params[idx].etmv4.reg_idr2 = metadata[idx][CS_ETMV4_TRCIDR2]; -- t_params[idx].etmv4.reg_idr8 = metadata[idx][CS_ETMV4_TRCIDR8]; -- t_params[idx].etmv4.reg_configr = metadata[idx][CS_ETMV4_TRCCONFIGR]; -- t_params[idx].etmv4.reg_traceidr = metadata[idx][CS_ETMV4_TRCTRACEIDR]; -+ t_params[t_idx].protocol = CS_ETM_PROTO_ETMV4i; -+ t_params[t_idx].etmv4.reg_idr0 = metadata[m_idx][CS_ETMV4_TRCIDR0]; -+ t_params[t_idx].etmv4.reg_idr1 = metadata[m_idx][CS_ETMV4_TRCIDR1]; -+ t_params[t_idx].etmv4.reg_idr2 = metadata[m_idx][CS_ETMV4_TRCIDR2]; -+ t_params[t_idx].etmv4.reg_idr8 = metadata[m_idx][CS_ETMV4_TRCIDR8]; -+ t_params[t_idx].etmv4.reg_configr = metadata[m_idx][CS_ETMV4_TRCCONFIGR]; -+ t_params[t_idx].etmv4.reg_traceidr = metadata[m_idx][CS_ETMV4_TRCTRACEIDR]; - } - - static void cs_etm__set_trace_param_ete(struct cs_etm_trace_params *t_params, -- struct cs_etm_auxtrace *etm, int idx) -+ struct cs_etm_auxtrace *etm, int t_idx, -+ int m_idx) - { - u64 **metadata = etm->metadata; - -- t_params[idx].protocol = CS_ETM_PROTO_ETE; -- t_params[idx].ete.reg_idr0 = metadata[idx][CS_ETE_TRCIDR0]; -- t_params[idx].ete.reg_idr1 = metadata[idx][CS_ETE_TRCIDR1]; -- t_params[idx].ete.reg_idr2 = metadata[idx][CS_ETE_TRCIDR2]; -- t_params[idx].ete.reg_idr8 = metadata[idx][CS_ETE_TRCIDR8]; -- t_params[idx].ete.reg_configr = metadata[idx][CS_ETE_TRCCONFIGR]; -- t_params[idx].ete.reg_traceidr = metadata[idx][CS_ETE_TRCTRACEIDR]; -- t_params[idx].ete.reg_devarch = metadata[idx][CS_ETE_TRCDEVARCH]; -+ t_params[t_idx].protocol = CS_ETM_PROTO_ETE; -+ t_params[t_idx].ete.reg_idr0 = metadata[m_idx][CS_ETE_TRCIDR0]; -+ t_params[t_idx].ete.reg_idr1 = metadata[m_idx][CS_ETE_TRCIDR1]; -+ t_params[t_idx].ete.reg_idr2 = metadata[m_idx][CS_ETE_TRCIDR2]; -+ t_params[t_idx].ete.reg_idr8 = metadata[m_idx][CS_ETE_TRCIDR8]; -+ t_params[t_idx].ete.reg_configr = metadata[m_idx][CS_ETE_TRCCONFIGR]; -+ t_params[t_idx].ete.reg_traceidr = metadata[m_idx][CS_ETE_TRCTRACEIDR]; -+ t_params[t_idx].ete.reg_devarch = metadata[m_idx][CS_ETE_TRCDEVARCH]; - } - - static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, -+ bool formatted, -+ int sample_cpu, - int decoders) - { -- int i; -+ int t_idx, m_idx; - u32 etmidr; - u64 architecture; - -- for (i = 0; i < decoders; i++) { -- architecture = etm->metadata[i][CS_ETM_MAGIC]; -+ for (t_idx = 0; t_idx < decoders; t_idx++) { -+ if (formatted) -+ m_idx = t_idx; -+ else { -+ m_idx = get_cpu_data_idx(etm, sample_cpu); -+ if (m_idx == -1) { -+ pr_warning("CS_ETM: unknown CPU, falling back to first metadata\n"); -+ m_idx = 0; -+ } -+ } -+ -+ architecture = etm->metadata[m_idx][CS_ETM_MAGIC]; - - switch (architecture) { - case __perf_cs_etmv3_magic: -- etmidr = etm->metadata[i][CS_ETM_ETMIDR]; -- cs_etm__set_trace_param_etmv3(t_params, etm, i, etmidr); -+ etmidr = etm->metadata[m_idx][CS_ETM_ETMIDR]; -+ cs_etm__set_trace_param_etmv3(t_params, etm, t_idx, m_idx, etmidr); - break; - case __perf_cs_etmv4_magic: -- cs_etm__set_trace_param_etmv4(t_params, etm, i); -+ cs_etm__set_trace_param_etmv4(t_params, etm, t_idx, m_idx); - break; - case __perf_cs_ete_magic: -- cs_etm__set_trace_param_ete(t_params, etm, i); -+ cs_etm__set_trace_param_ete(t_params, etm, t_idx, m_idx); - break; - default: - return -EINVAL; -@@ -1016,7 +1039,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, - } - - static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, -- bool formatted) -+ bool formatted, int sample_cpu) - { - struct cs_etm_decoder_params d_params; - struct cs_etm_trace_params *t_params = NULL; -@@ -1041,7 +1064,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, - if (!t_params) - goto out_free; - -- if (cs_etm__init_trace_params(t_params, etm, decoders)) -+ if (cs_etm__init_trace_params(t_params, etm, formatted, sample_cpu, decoders)) - goto out_free; - - /* Set decoder parameters to decode trace packets */ -@@ -1081,14 +1104,15 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, - static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, - struct auxtrace_queue *queue, - unsigned int queue_nr, -- bool formatted) -+ bool formatted, -+ int sample_cpu) - { - struct cs_etm_queue *etmq = queue->priv; - - if (list_empty(&queue->head) || etmq) - return 0; - -- etmq = cs_etm__alloc_queue(etm, formatted); -+ etmq = cs_etm__alloc_queue(etm, formatted, sample_cpu); - - if (!etmq) - return -ENOMEM; -@@ -2827,7 +2851,7 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session, - * formatted in piped mode (true). - */ - err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], -- idx, true); -+ idx, true, -1); - if (err) - return err; - -@@ -3033,7 +3057,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o - idx = auxtrace_event->idx; - formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW); - return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], -- idx, formatted); -+ idx, formatted, sample->cpu); - } - - /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */ --- -2.53.0 - diff --git a/queue-6.6/perf-cs-etm-queue-context-packets-for-frontend.patch b/queue-6.6/perf-cs-etm-queue-context-packets-for-frontend.patch deleted file mode 100644 index 933e0459a4..0000000000 --- a/queue-6.6/perf-cs-etm-queue-context-packets-for-frontend.patch +++ /dev/null @@ -1,725 +0,0 @@ -From cc0a6a0ef31195c19d891da55f7266ae0075fb0e Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 9 Jun 2026 15:40:06 +0100 -Subject: perf cs-etm: Queue context packets for frontend - -From: James Clark - -[ 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 -Closes: https://lore.kernel.org/linux-perf-users/20260515021135.1729028-1-aaupov@meta.com/ -Co-authored-by: James Clark -Signed-off-by: Leo Yan -Cc: Ian Rogers -Cc: Jiri Olsa -Cc: Jonathan Corbet -Cc: linux-doc@vger.kernel.org -Cc: Mike Leach -Cc: Namhyung Kim -Cc: Paschalis Mpeis -Cc: Robert Walker -Cc: Shuah Khan -Cc: Suzuki Poulouse -Signed-off-by: James Clark -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - .../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(-) - -diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c -index 640e383cef441c..277da9f767b9d2 100644 ---- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c -+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c -@@ -398,6 +398,8 @@ cs_etm_decoder__buffer_packet(struct cs_etm_packet_queue *packet_queue, - 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; -@@ -445,6 +447,7 @@ cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq, - 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; -@@ -518,7 +521,9 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, - 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. -@@ -539,12 +544,18 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, - 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 -@@ -552,7 +563,7 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, - */ - 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( -diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c -index 9077072994b23b..8dc12759ee62f4 100644 ---- 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 { -@@ -489,10 +496,11 @@ static int cs_etm__init_traceid_queue(struct cs_etm_queue *etmq, - - 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) -@@ -625,21 +633,10 @@ static void cs_etm__packet_swap(struct cs_etm_auxtrace *etm, - /* - * 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); - } - } - -@@ -827,8 +824,8 @@ static void cs_etm__free_traceid_queues(struct cs_etm_queue *etmq) - - /* 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); -@@ -969,47 +966,43 @@ static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address, - } - } - --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); -@@ -1024,7 +1017,7 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, - - 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) { -@@ -1044,6 +1037,30 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id, - 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)); -@@ -1209,12 +1226,13 @@ void cs_etm__reset_last_branch_rb(struct cs_etm_traceid_queue *tidq) - } - - 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 -@@ -1243,16 +1261,16 @@ u64 cs_etm__last_executed_instr(const struct cs_etm_packet *packet) - } - - 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; -@@ -1344,34 +1362,51 @@ cs_etm__get_trace(struct cs_etm_queue *etmq) - 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; - } - -@@ -1381,8 +1416,8 @@ bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq) - } - - 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) - { - /* -@@ -1399,14 +1434,14 @@ static void cs_etm__copy_insn(struct cs_etm_queue *etmq, - * 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) -@@ -1433,6 +1468,7 @@ static inline u64 cs_etm__resolve_sample_time(struct cs_etm_queue *etmq, - - 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; -@@ -1441,23 +1477,23 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq, - 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; -@@ -1501,15 +1537,15 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, - - 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; -@@ -1518,8 +1554,7 @@ static int cs_etm__synth_branch_sample(struct cs_etm_queue *etmq, - 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 -@@ -1672,7 +1707,6 @@ static int cs_etm__sample(struct cs_etm_queue *etmq, - { - 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 */ -@@ -1758,10 +1792,10 @@ static int cs_etm__sample(struct cs_etm_queue *etmq, - * 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; -@@ -1843,7 +1877,7 @@ static int cs_etm__flush(struct cs_etm_queue *etmq, - 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; -@@ -1898,7 +1932,7 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq, - 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; -@@ -1935,9 +1969,9 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq) - 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; -@@ -1959,8 +1993,8 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, - * 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; - -@@ -1975,8 +2009,8 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, - * +---------+---------+-------------------------+ - */ - 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; -@@ -1992,8 +2026,8 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, - * +-----------------------+---------+-----------+ - */ - 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; - -@@ -2009,7 +2043,6 @@ static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq, u8 trace_chan_id, - 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; - -@@ -2024,7 +2057,7 @@ static bool cs_etm__is_syscall(struct cs_etm_queue *etmq, - */ - 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; - } -@@ -2062,7 +2095,6 @@ static bool cs_etm__is_sync_exception(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; - -@@ -2088,7 +2120,7 @@ static bool cs_etm__is_sync_exception(struct cs_etm_queue *etmq, - * (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; - -@@ -2112,7 +2144,6 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, - { - 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; - -@@ -2193,11 +2224,11 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, - 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: - /* -@@ -2278,6 +2309,7 @@ static int cs_etm__set_sample_flags(struct cs_etm_queue *etmq, - PERF_IP_FLAG_RETURN | - PERF_IP_FLAG_INTERRUPT; - break; -+ case CS_ETM_CONTEXT: - case CS_ETM_EMPTY: - default: - break; -@@ -2353,6 +2385,19 @@ static int cs_etm__process_traceid_queue(struct cs_etm_queue *etmq, - */ - 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: - /* -@@ -2381,6 +2426,7 @@ static int cs_etm__process_traceid_queue(struct cs_etm_queue *etmq, - } - } - -+out: - return ret; - } - -@@ -2504,7 +2550,7 @@ static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm, - 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); -@@ -3245,7 +3291,7 @@ static int cs_etm__create_queue_decoders(struct cs_etm_queue *etmq) - */ - 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); -diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h -index 7cca3788791760..f7b4903d9ef726 100644 ---- 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 -@@ -254,8 +257,9 @@ enum cs_etm_pid_fmt { - #include - int cs_etm__get_cpu(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); --- -2.53.0 - diff --git a/queue-6.6/perf-cs-etm-require-full-global-header-in-auxtrace_i.patch b/queue-6.6/perf-cs-etm-require-full-global-header-in-auxtrace_i.patch deleted file mode 100644 index 8ed280a49b..0000000000 --- a/queue-6.6/perf-cs-etm-require-full-global-header-in-auxtrace_i.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 98883f6635158ab03af655b28574d19b6fa40078 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Adrian Hunter -Cc: James Clark -Cc: Leo Yan -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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.6/perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch b/queue-6.6/perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch deleted file mode 100644 index ffb9db0495..0000000000 --- a/queue-6.6/perf-cs-etm-validate-num_cpu-before-metadata-allocat.patch +++ /dev/null @@ -1,61 +0,0 @@ -From c87c6ffb8c6f2a98fd5e116e612202a349664ad4 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sat, 13 Jun 2026 14:16:45 -0300 -Subject: perf cs-etm: Validate num_cpu before metadata allocation - -From: Arnaldo Carvalho de Melo - -[ 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 -Cc: Adrian Hunter -Cc: James Clark -Cc: Leo Yan -Cc: Tor Jeremiassen -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - tools/perf/util/cs-etm.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c -index 8dc12759ee62f4..10ea1e3254fe21 100644 ---- a/tools/perf/util/cs-etm.c -+++ b/tools/perf/util/cs-etm.c -@@ -3355,6 +3355,18 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, - /* 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) { - err = -ENOMEM; --- -2.53.0 - diff --git a/queue-6.6/perf-header-sanity-check-header_event_desc-attr.size.patch b/queue-6.6/perf-header-sanity-check-header_event_desc-attr.size.patch deleted file mode 100644 index d9dd761386..0000000000 --- a/queue-6.6/perf-header-sanity-check-header_event_desc-attr.size.patch +++ /dev/null @@ -1,140 +0,0 @@ -From 405e9041717f0756841c6f187edeb46c8e2f5451 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Jiri Olsa -Cc: Namhyung Kim -Cc: Wang Nan -Assisted-by: Claude:claude-opus-4.6-1m -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 0b44176826bfd9..50b0c98f44b87a 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.6/perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch b/queue-6.6/perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch deleted file mode 100644 index 4449d73cb5..0000000000 --- a/queue-6.6/perf-hists-fix-snprintf-in-hists__scnprintf_title-ui.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 08cedb9ea84e58efed17378c804283198b50d135 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Reviewed-by: Ian Rogers -Cc: Arnaldo Carvalho de Melo -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 aa450cc2648aa5..2f2a8302b796fe 100644 ---- a/tools/perf/util/hist.c -+++ b/tools/perf/util/hist.c -@@ -2800,9 +2800,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.6/perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch b/queue-6.6/perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch deleted file mode 100644 index f2fa1a94ab..0000000000 --- a/queue-6.6/perf-intel-pt-fix-snprintf-size-tracking-bug-in-insn.patch +++ /dev/null @@ -1,67 +0,0 @@ -From dfb1e8789172d87b584d7cd3b6684bfff753578e Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Adrian Hunter -Cc: Andi Kleen -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - .../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 c5d57027ec23d3..03a143a02d40db 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 -@@ -213,7 +213,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); -@@ -222,13 +221,9 @@ const char *dump_insn(struct perf_insn *x, uint64_t ip __maybe_unused, - return ""; - 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.6/perf-machine-use-snprintf-for-guestmount-path-constr.patch b/queue-6.6/perf-machine-use-snprintf-for-guestmount-path-constr.patch deleted file mode 100644 index 8ef393fa1b..0000000000 --- a/queue-6.6/perf-machine-use-snprintf-for-guestmount-path-constr.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 5e004479a0318cbcb9b517a02efb76acf8b8f9ee Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sat, 13 Jun 2026 13:59:39 -0300 -Subject: perf machine: Use snprintf() for guestmount path construction - -From: Arnaldo Carvalho de Melo - -[ 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 -Cc: Zhang, Yanmin -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 2f5a5245483ede..9e462ebdaca686 100644 ---- a/tools/perf/util/machine.c -+++ b/tools/perf/util/machine.c -@@ -369,7 +369,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; - -@@ -1415,9 +1415,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.6/perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch b/queue-6.6/perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch deleted file mode 100644 index 40cd808029..0000000000 --- a/queue-6.6/perf-mmap-fix-null-deref-in-aio-cleanup-on-alloc-fai.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 4a699e34d9fcf171390869dc8f7b8abe2a969c74 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Alexey Budankov -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 99f6235dd16afd..79178528af10e4 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.6/perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch b/queue-6.6/perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch deleted file mode 100644 index 5a6e521bf1..0000000000 --- a/queue-6.6/perf-mmap-guard-cpu__get_node-return-in-aio_bind.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 6d0ce80e9933ccde329905e4f16b009131014385 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Alexey Budankov -Cc: Jiri Olsa -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 49093b21ee2da0..99f6235dd16afd 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.6/perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch b/queue-6.6/perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch deleted file mode 100644 index e1e4035bd5..0000000000 --- a/queue-6.6/perf-pmu-fix-perf_pmu__parse_scale-unit-oob-access-o.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 8b69cba01ceb9555fd9b71f2d41c1035e34c71ad Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Stephane Eranian -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 e05dff925aa069..d5daa6e43522db 100644 ---- a/tools/perf/util/pmu.c -+++ b/tools/perf/util/pmu.c -@@ -318,7 +318,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') -@@ -350,7 +350,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.6/perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch b/queue-6.6/perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch deleted file mode 100644 index 463a8afb19..0000000000 --- a/queue-6.6/perf-pmu-fix-pmu_id-heap-underwrite-on-empty-identif.patch +++ /dev/null @@ -1,46 +0,0 @@ -From f7d2d8790880c73216204ac635db9567f1fc2a45 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: John Garry -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 2587c4b463fa88..e05dff925aa069 100644 ---- a/tools/perf/util/pmu.c -+++ b/tools/perf/util/pmu.c -@@ -774,6 +774,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.6/perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch b/queue-6.6/perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch deleted file mode 100644 index 89b27b3bc0..0000000000 --- a/queue-6.6/perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch +++ /dev/null @@ -1,104 +0,0 @@ -From f96965422da026a3ffc8ca7b2b3621f65a29c330 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 10 Apr 2026 12:13:44 +0100 -Subject: perf pmu: Skip test on Arm64 when #slots is zero - -From: Leo Yan - -[ 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 -Reviewed-by: James Clark -Signed-off-by: Leo Yan -Cc: Adrian Hunter -Cc: Alexander Shishkin -Cc: Jiri Olsa -Cc: Mark Rutland -Cc: Namhyung Kim -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 f5321fbdee79d1..2ed9d2ad792e2b 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" - -@@ -804,6 +805,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) -@@ -842,8 +863,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.6/perf-sched-add-missing-mmap2-handler-in-timehist.patch b/queue-6.6/perf-sched-add-missing-mmap2-handler-in-timehist.patch deleted file mode 100644 index f187f75ab2..0000000000 --- a/queue-6.6/perf-sched-add-missing-mmap2-handler-in-timehist.patch +++ /dev/null @@ -1,54 +0,0 @@ -From 15c0fbdbfccdfca66a34ebfb32e653be30457a46 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 5 May 2026 17:45:42 -0700 -Subject: perf sched: Add missing mmap2 handler in timehist - -From: Ian Rogers - -[ 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 -Cc: Adrian Hunter -Cc: David Ahern -Cc: Gabriel Marin -Cc: Ingo Molnar -Cc: James Clark -Cc: Jiri Olsa -Cc: Namhyung Kim -Cc: Peter Zijlstra -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 16cb7278fabaf7..1a22314094e6ad 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -3067,6 +3067,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.6/perf-sched-clean-up-idle_threads-entry-on-init-failu.patch b/queue-6.6/perf-sched-clean-up-idle_threads-entry-on-init-failu.patch deleted file mode 100644 index 8c3eaf2fdd..0000000000 --- a/queue-6.6/perf-sched-clean-up-idle_threads-entry-on-init-failu.patch +++ /dev/null @@ -1,54 +0,0 @@ -From eb274c7daa284d4f5057eac6aff1679a33634f96 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: David Ahern -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 6df0d1252f197f..0a1a58f33ae651 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -2372,8 +2372,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.6/perf-sched-fix-idle-hist-callchain-display-using-wro.patch b/queue-6.6/perf-sched-fix-idle-hist-callchain-display-using-wro.patch deleted file mode 100644 index 25fd6a16cc..0000000000 --- a/queue-6.6/perf-sched-fix-idle-hist-callchain-display-using-wro.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 2ed9224a2868664155d190aa076b40e504e95880 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Davidlohr Bueso -Cc: Namhyung Kim -Acked-by: Ian Rogers -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 8b1573515c5781..db4ceebab8d8ad 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -2906,7 +2906,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.6/perf-sched-fix-null-dereference-in-latency_runtime_e.patch b/queue-6.6/perf-sched-fix-null-dereference-in-latency_runtime_e.patch deleted file mode 100644 index 4e05ed6306..0000000000 --- a/queue-6.6/perf-sched-fix-null-dereference-in-latency_runtime_e.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 818a0ffd8e4cad58cd96571c01ed1f2231622ec3 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 4 Jun 2026 12:56:02 -0300 -Subject: perf sched: Fix NULL dereference in latency_runtime_event - -From: Arnaldo Carvalho de Melo - -[ 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 -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 9e9bb19f0bc98b..6df0d1252f197f 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -1223,13 +1223,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.6/perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch b/queue-6.6/perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch deleted file mode 100644 index c995f3af7e..0000000000 --- a/queue-6.6/perf-sched-replace-bug_on-and-add-null-checks-in-rep.patch +++ /dev/null @@ -1,121 +0,0 @@ -From b7d7eb3eded41a994946681cb2fd8536052a9181 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Ingo Molnar -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 0a1a58f33ae651..8b1573515c5781 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -363,14 +363,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; - -@@ -401,6 +412,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; -@@ -414,6 +427,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; - -@@ -428,6 +443,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; -@@ -440,6 +459,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.6/perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch b/queue-6.6/perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch deleted file mode 100644 index ec40f0ae08..0000000000 --- a/queue-6.6/perf-sched-replace-bug_on-on-invalid-cpu-with-gracef.patch +++ /dev/null @@ -1,84 +0,0 @@ -From d30ea1fda9f30ebeaa3443bc478dcbcc522574fa Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Stable-dep-of: 8cbca8a480e1 ("perf sched: Fix NULL dereference in latency_runtime_event") -Signed-off-by: Sasha Levin ---- - 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 942fde8a1d52e3..9e9bb19f0bc98b 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -1154,7 +1154,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; -@@ -1225,7 +1230,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; -@@ -1596,7 +1607,12 @@ static int map_switch_event(struct perf_sched *sched, struct evsel *evsel, - const char *color = PERF_COLOR_NORMAL; - char stimestamp[32]; - -- 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.6/perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch b/queue-6.6/perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch deleted file mode 100644 index fe711ce6f8..0000000000 --- a/queue-6.6/perf-symbols-add-bounds-checks-to-elf_read_build_id-.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 52eeb75748cfc35e88befa4cc321282444177e23 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 4a2fb6e3d4ef38..96bb84a8c5c2ed 100644 ---- a/tools/perf/util/symbol-elf.c -+++ b/tools/perf/util/symbol-elf.c -@@ -908,10 +908,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.6/perf-symbols-add-bounds-checks-to-read_build_id-note.patch b/queue-6.6/perf-symbols-add-bounds-checks-to-read_build_id-note.patch deleted file mode 100644 index c711c6abb3..0000000000 --- a/queue-6.6/perf-symbols-add-bounds-checks-to-read_build_id-note.patch +++ /dev/null @@ -1,67 +0,0 @@ -From 0e8d1d780638640ede4da8b5d720f2c40fa0ba2e Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 a81a14769bd101..b95dd77239e835 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" -@@ -45,7 +46,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) { -@@ -57,6 +58,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.6/perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch b/queue-6.6/perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch deleted file mode 100644 index 445496e5ca..0000000000 --- a/queue-6.6/perf-symbols-bounds-check-.gnu_debuglink-section-dat.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 2e8b595348d5a0910489c1ee6e5cf62ff691f1cb Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Sun, 7 Jun 2026 21:05:15 -0300 -Subject: perf symbols: Bounds-check .gnu_debuglink section data - -From: Arnaldo Carvalho de Melo - -[ 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 -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 0f5f60bc4180bf..83b76e88ed603e 100644 ---- a/tools/perf/util/symbol-elf.c -+++ b/tools/perf/util/symbol-elf.c -@@ -1159,7 +1159,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.6/perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch b/queue-6.6/perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch deleted file mode 100644 index 4fd7ec249f..0000000000 --- a/queue-6.6/perf-symbols-bounds-check-descsz-in-sysfs__read_buil.patch +++ /dev/null @@ -1,57 +0,0 @@ -From aca2e8e0042cae7687e3ebe3129ad75899266c23 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 83b76e88ed603e..4a2fb6e3d4ef38 100644 ---- a/tools/perf/util/symbol-elf.c -+++ b/tools/perf/util/symbol-elf.c -@@ -1059,8 +1059,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.6/perf-symbols-break-infinite-loop-on-zero-filled-note.patch b/queue-6.6/perf-symbols-break-infinite-loop-on-zero-filled-note.patch deleted file mode 100644 index adb237dd63..0000000000 --- a/queue-6.6/perf-symbols-break-infinite-loop-on-zero-filled-note.patch +++ /dev/null @@ -1,52 +0,0 @@ -From f0252d4dce87893a824cc3d8fcbdaa13a5570cb1 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Fixes: f1617b40596cb341 ("perf symbols: Record the build_ids of kernel modules too") -Reviewed-by: Ian Rogers -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 96bb84a8c5c2ed..1729efd11ac5cf 100644 ---- a/tools/perf/util/symbol-elf.c -+++ b/tools/perf/util/symbol-elf.c -@@ -1091,6 +1091,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.6/perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch b/queue-6.6/perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch deleted file mode 100644 index 88f4c44c61..0000000000 --- a/queue-6.6/perf-symbols-fix-signed-overflow-in-sysfs__read_buil.patch +++ /dev/null @@ -1,72 +0,0 @@ -From add92f3070796b2154eef6d8e2abdfce2b7e7359 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Cc: Namhyung Kim -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 95e99c332d7e3f..0f5f60bc4180bf 100644 ---- a/tools/perf/util/symbol-elf.c -+++ b/tools/perf/util/symbol-elf.c -@@ -1062,14 +1062,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.6/perf-tools-add-bounds-check-to-cpu__get_node.patch b/queue-6.6/perf-tools-add-bounds-check-to-cpu__get_node.patch deleted file mode 100644 index 337bd190ce..0000000000 --- a/queue-6.6/perf-tools-add-bounds-check-to-cpu__get_node.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 75449cc73298968a3b3696c9615af953121838ae Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 4 Jun 2026 18:14:23 -0300 -Subject: perf tools: Add bounds check to cpu__get_node() - -From: Arnaldo Carvalho de Melo - -[ 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 -Cc: Jiri Olsa -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 0e090e8bc33491..75d9f5d6d185d1 100644 ---- a/tools/perf/util/cpumap.c -+++ b/tools/perf/util/cpumap.c -@@ -498,6 +498,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.6/perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch b/queue-6.6/perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch deleted file mode 100644 index d7a81855c0..0000000000 --- a/queue-6.6/perf-tools-fix-get_max_num-size_t-underflow-on-empty.patch +++ /dev/null @@ -1,50 +0,0 @@ -From e70f080e4a12e41419addb6cb097cd2b5974c87b Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Reviewed-by: Ian Rogers -Cc: Don Zickus -Cc: Ian Rogers -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 75d9f5d6d185d1..de4a710e242146 100644 ---- a/tools/perf/util/cpumap.c -+++ b/tools/perf/util/cpumap.c -@@ -378,6 +378,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.6/perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch b/queue-6.6/perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch deleted file mode 100644 index 2853dc91bc..0000000000 --- a/queue-6.6/perf-tools-fix-thread__set_comm_from_proc-on-empty-c.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 394597a7925a95e0a6a0096b50e67b908afe33f7 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 61e9f449c72581..ec0ccc310cdad8 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.6/perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch b/queue-6.6/perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch deleted file mode 100644 index 1f3ea562f7..0000000000 --- a/queue-6.6/perf-tools-guard-test_bit-from-out-of-bounds-sample-.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 9990eeee66cad1541a119a76b837f1498421f0a6 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Reported-by: sashiko-bot -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 0f1e5787b4edac..e572043be2dbb8 100644 ---- a/tools/perf/builtin-annotate.c -+++ b/tools/perf/builtin-annotate.c -@@ -287,7 +287,8 @@ static int process_sample_event(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 57d300d8e5700c..41f557fcc5567f 100644 ---- a/tools/perf/builtin-diff.c -+++ b/tools/perf/builtin-diff.c -@@ -417,7 +417,8 @@ static int diff__process_sample_event(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 54b06db597862f..eed8a2621d01f7 100644 ---- a/tools/perf/builtin-report.c -+++ b/tools/perf/builtin-report.c -@@ -298,7 +298,8 @@ static int process_sample_event(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 1a22314094e6ad..942fde8a1d52e3 100644 ---- a/tools/perf/builtin-sched.c -+++ b/tools/perf/builtin-sched.c -@@ -2085,7 +2085,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)); -@@ -2671,7 +2672,8 @@ static int timehist_sched_change_event(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.6/perf-tools-use-perf_env__get_cpu_topology-in-machine.patch b/queue-6.6/perf-tools-use-perf_env__get_cpu_topology-in-machine.patch deleted file mode 100644 index e008887f2e..0000000000 --- a/queue-6.6/perf-tools-use-perf_env__get_cpu_topology-in-machine.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 4704847c5f05a24205fde0902af7ad5b6efee5bd Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Reviewed-by: Ian Rogers -Cc: Kan Liang -Cc: Ian Rogers -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 68f45e9e63b6e4..b118766c16e657 100644 ---- a/tools/perf/util/event.c -+++ b/tools/perf/util/event.c -@@ -12,6 +12,7 @@ - #include - #include "cpumap.h" - #include "dso.h" -+#include "env.h" - #include "event.h" - #include "debug.h" - #include "hist.h" -@@ -743,8 +744,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.6/perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch b/queue-6.6/perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch deleted file mode 100644 index 24806dda64..0000000000 --- a/queue-6.6/perf-tools-use-scnprintf-in-cpu_map__snprint-to-prev.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e3d42442ed88cbd352962b1cfb068577d420637e Mon Sep 17 00:00:00 2001 -From: Sasha Levin -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 - -[ 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 -Reviewed-by: Ian Rogers -Cc: Jiri Olsa -Cc: Ian Rogers -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 de4a710e242146..c5126cdbd7dd70 100644 ---- a/tools/perf/util/cpumap.c -+++ b/tools/perf/util/cpumap.c -@@ -601,21 +601,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.6/perf-tools-use-snprintf-for-root_dir-path-constructi.patch b/queue-6.6/perf-tools-use-snprintf-for-root_dir-path-constructi.patch deleted file mode 100644 index 244e781a15..0000000000 --- a/queue-6.6/perf-tools-use-snprintf-for-root_dir-path-constructi.patch +++ /dev/null @@ -1,58 +0,0 @@ -From be21a8a08626870984d3c5ed3fe1fb98d658dbb9 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 10 Jun 2026 20:34:38 -0300 -Subject: perf tools: Use snprintf() for root_dir path construction - -From: Arnaldo Carvalho de Melo - -[ 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 -Fixes: a1645ce12adb6c9c ("perf: 'perf kvm' tool for monitoring guest performance from host") -Cc: Zhang Yanmin -Assisted-by: Claude:claude-opus-4.6 -Signed-off-by: Arnaldo Carvalho de Melo -Signed-off-by: Sasha Levin ---- - 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 e2a6facd1c4e2a..2f5a5245483ede 100644 ---- a/tools/perf/util/machine.c -+++ b/tools/perf/util/machine.c -@@ -1495,7 +1495,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 18556b7a765630..8618e4175e20fd 100644 ---- a/tools/perf/util/symbol.c -+++ b/tools/perf/util/symbol.c -@@ -2215,7 +2215,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.6/series b/queue-6.6/series index 98b72a6ae9..e3b3c0fc7f 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -609,17 +609,14 @@ 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 bus-mhi-ep-fix-potential-deadlock-in-mhi_ep_reset_wo.patch phy-phy-can-transceiver-check-driver-match-and-drive.patch -perf-pmu-skip-test-on-arm64-when-slots-is-zero.patch mailbox-mtk-adsp-fix-uaf-during-device-teardown.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 -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 @@ -633,16 +630,6 @@ fs-ntfs3-fix-mount-failure-on-64k-page-size-kernels.patch drm-amd-display-add-missing-kdoc-for-allm-parameters.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-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-mmap-guard-cpu__get_node-return-in-aio_bind.patch -perf-c2c-bounds-check-cpu-and-node-ids-before-bitmap.patch -perf-sched-clean-up-idle_threads-entry-on-init-failu.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-c2c-fix-use-after-free-in-he__get_c2c_hists-err.patch dmaengine-qcom-gpi-set-dma_private-capability.patch dmaengine-fix-possible-use-after-free.patch clk-qcom-a53-corrected-frequency-multiplier-for-1152.patch @@ -660,13 +647,7 @@ nfsv4-flexfiles-honor-ff_flags_no_io_thru_mds-in-pg_.patch pci-mediatek-fix-operator-precedence-in-pcie_fts_num.patch pci-meson-propagate-devm_add_action_or_reset-failure.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-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-check-frwr_wp_create-during-connect.patch xprtrdma-document-and-assert-reply-handler-invariant.patch xprtrdma-resize-reply-buffers-before-reposting-recei.patch @@ -674,22 +655,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-fix-incorrect-or-missing-decoder-for-raw.patch -perf-cs-etm-create-decoders-after-both-aux-and-hw_id.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 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 @@ -704,19 +672,12 @@ apparmor-put-secmark-label-after-secid-lookup.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-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 gpio-mlxbf3-fail-probe-if-gpiochip-registration-fail.patch spi-dw-fix-wrong-baudr-setting-after-resume.patch xfrm-use-the-xfrm_gro-to-indicate-a-gro-call-on-inpu.patch xfrm-support-crypto-offload-for-inbound-ipv6-esp-pac.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 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