[PATCH 3/9] perf thread-stack: Bound wrapped branch stack copy

Amir Ayupov <[email protected]> Mon, 3 Aug 2026 02:06:34 -0700
Newsgroups org.kernel.vger.linux-perf-users,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-doc
Message-ID <[email protected]>
When the internal branch ring has wrapped, thread_stack__br_sample()
computes the number of entries that still fit in the destination:

	nr = min(ts->br_stack_pos, sz);

but then copies ts->br_stack_pos entries regardless, overrunning the
destination whenever sz is smaller than ts->br_stack_pos.

No caller can trigger this today: both intel-pt and cs-etm size the
thread stack ring and the output buffer from the same
synth_opts.last_branch_sz, so sz is never less than ts->br_stack_sz and
the two values always agree. It becomes reachable as soon as a caller
keeps a larger reconstruction ring than the requested output depth,
which is what --itrace=L does for late branch sampling.

Copy nr entries instead, so the destination bound is honoured whatever
the caller asks for.

Signed-off-by: Amir Ayupov <[email protected]>
---
 tools/perf/util/thread-stack.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index 1a3dffa83bde2..51eaedb47bb1d 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -643,7 +643,7 @@ void thread_stack__br_sample(struct thread *thread, int cpu,
 		sz -= nr;
 		be = &dst->entries[nr];
 		nr = min(ts->br_stack_pos, sz);
-		memcpy(be, &src->entries[0], bsz * ts->br_stack_pos);
+		memcpy(be, &src->entries[0], bsz * nr);
 	}
 }
 
-- 
2.52.0