diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2026-07-27 13:17:02 -0300 |
|---|---|---|
| committer | Namhyung Kim <namhyung@kernel.org> | 2026-08-03 12:42:53 -0700 |
| commit | 96fcc9ea5f18c083a1fa73da23afef7e953f7dca (patch) | |
| tree | eb247b54a83b9c3cec73d842a429b44f6b7bf91d | |
| parent | ab9c84d1cd59e6b3b73de34982a35a76e3a9b032 (diff) | |
| download | linux-96fcc9ea5f18c083a1fa73da23afef7e953f7dca.tar.gz linux-96fcc9ea5f18c083a1fa73da23afef7e953f7dca.zip | |
perf auxtrace: Fix queue grow overflow and old array leak
auxtrace_queues__grow() has two bugs:
1. When idx is UINT_MAX, the caller passes new_nr_queues = idx + 1 = 0.
The function skips growing (since any nr_queues >= 0), returns
success, and the caller accesses queue_array[UINT_MAX] — an OOB
heap write. Fix by rejecting new_nr_queues == 0 up front.
2. The function allocates a new queue_array via calloc and copies
elements from the old array, but never frees the old array. Fix
by saving the old pointer and freeing it after the copy.
Fixes: e502789302a6ece9 ("perf auxtrace: Add helpers for queuing AUX area tracing data")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Reviewed-by: James Clark <james.clark@linaro.org>
Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
| -rw-r--r-- | tools/perf/util/auxtrace.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 0b851f32e98c..aa749e1c3036 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -251,8 +251,12 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues, { unsigned int nr_queues = queues->nr_queues; struct auxtrace_queue *queue_array; + struct auxtrace_queue *old_array = queues->queue_array; unsigned int i; + if (!new_nr_queues) + return -EINVAL; + if (!nr_queues) nr_queues = AUXTRACE_INIT_NR_QUEUES; @@ -267,16 +271,17 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues, return -ENOMEM; for (i = 0; i < queues->nr_queues; i++) { - list_splice_tail(&queues->queue_array[i].head, + list_splice_tail(&old_array[i].head, &queue_array[i].head); - queue_array[i].tid = queues->queue_array[i].tid; - queue_array[i].cpu = queues->queue_array[i].cpu; - queue_array[i].set = queues->queue_array[i].set; - queue_array[i].priv = queues->queue_array[i].priv; + queue_array[i].tid = old_array[i].tid; + queue_array[i].cpu = old_array[i].cpu; + queue_array[i].set = old_array[i].set; + queue_array[i].priv = old_array[i].priv; } queues->nr_queues = nr_queues; queues->queue_array = queue_array; + free(old_array); return 0; } |
