summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Yan <leo.yan@arm.com>2026-07-20 11:01:21 +0100
committerNamhyung Kim <namhyung@kernel.org>2026-07-22 22:42:25 -0700
commitec99be8a31db999a4f866be74ea7db61dbb19f24 (patch)
tree759544b24a45f76ae6b4bab33a8a1e20b61b7e3d
parent64724095a33fbee805657415a4eb374bef5161c9 (diff)
downloadlinux-next-ec99be8a31db999a4f866be74ea7db61dbb19f24.tar.gz
linux-next-ec99be8a31db999a4f866be74ea7db61dbb19f24.zip
perf cs-etm: Avoid truncating AUX buffer sizes to int
cs_etm__get_trace() returns an int, but it used to return etmq->buf_len on success. That value comes from auxtrace_buffer::size, which is a size_t. For a large AUX trace block, returning the byte count through an int can overflow and make a valid buffer look like a negative error. The callers do not need the actual byte count from cs_etm__get_trace(). The buffer length is already stored in the etmq->buf_len. The callers only need to distinguish three states: < 0: error = 0: no more AUX buffers > 0: data is available Make cs_etm__get_trace() return 0 for all non-error cases and use etmq->buf_len to indicate whether a new buffer was found. Then make cs_etm__get_data_block() return 1 whenever data is available, instead of returning the buffer length. Also refactor cs_etm__get_data_block() to make its return value semantics clearer. Reported-by: Suyash Mahar <smahar@meta.com> Fixes: 8224531cf5a1 ("perf cs-etm: Modularize auxtrace_buffer fetch function") Signed-off-by: Leo Yan <leo.yan@arm.com> Reviewed-by: James Clark <james.clark@linaro.org> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-rw-r--r--tools/perf/util/cs-etm.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 95e3ec1171ac..114b3cd2da49 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -1467,8 +1467,7 @@ cs_etm__get_trace(struct cs_etm_queue *etmq)
etmq->buf_used = 0;
etmq->buf_len = aux_buffer->size;
etmq->buf = aux_buffer->data;
-
- return etmq->buf_len;
+ return 0;
}
/*
@@ -2151,26 +2150,33 @@ static int cs_etm__get_data_block(struct cs_etm_queue *etmq)
{
int ret;
- if (!etmq->buf_len) {
- ret = cs_etm__get_trace(etmq);
- if (ret <= 0)
- return ret;
- /*
- * We cannot assume consecutive blocks in the data file
- * are contiguous, reset the decoder to force re-sync.
- */
- ret = cs_etm_decoder__reset(etmq->decoder);
- if (ret)
- return ret;
+ /* The current block is not finished */
+ if (etmq->buf_len)
+ return 1;
- /*
- * Since the decoder is reset, this causes a global trace
- * discontinuity. Flush all thread stacks.
- */
- cs_etm__flush_all_stack(etmq);
- }
+ ret = cs_etm__get_trace(etmq);
+ if (ret < 0)
+ return ret;
+
+ /* No more buffer to read */
+ if (!etmq->buf_len)
+ return 0;
+
+ /*
+ * We cannot assume consecutive blocks in the data file
+ * are contiguous, reset the decoder to force re-sync.
+ */
+ ret = cs_etm_decoder__reset(etmq->decoder);
+ if (ret)
+ return ret;
+
+ /*
+ * Since the decoder is reset, this causes a global trace
+ * discontinuity. Flush all thread stacks.
+ */
+ cs_etm__flush_all_stack(etmq);
- return etmq->buf_len;
+ return 1;
}
static bool cs_etm__is_svc_instr(struct cs_etm_queue *etmq,