Skip to content

Commit fa9c497

Browse files
captain5050acmel
authored andcommitted
perf symbol-minimal: Fix double free in filename__read_build_id
Running the "perf script task-analyzer tests" with address sanitizer showed a double free: ``` FAIL: "test_csv_extended_times" Error message: "Failed to find required string:'Out-Out;'." ================================================================= ==19190==ERROR: AddressSanitizer: attempting double-free on 0x50b000017b10 in thread T0: #0 0x55da9601c78a in free (perf+0x26078a) (BuildId: e7ef50e08970f017a96fde6101c5e2491acc674a) #1 0x55da96640c63 in filename__read_build_id tools/perf/util/symbol-minimal.c:221:2 0x50b000017b10 is located 0 bytes inside of 112-byte region [0x50b000017b10,0x50b000017b80) freed by thread T0 here: #0 0x55da9601ce40 in realloc (perf+0x260e40) (BuildId: e7ef50e08970f017a96fde6101c5e2491acc674a) #1 0x55da96640ad6 in filename__read_build_id tools/perf/util/symbol-minimal.c:204:10 previously allocated by thread T0 here: #0 0x55da9601ca23 in malloc (perf+0x260a23) (BuildId: e7ef50e08970f017a96fde6101c5e2491acc674a) #1 0x55da966407e7 in filename__read_build_id tools/perf/util/symbol-minimal.c:181:9 SUMMARY: AddressSanitizer: double-free (perf+0x26078a) (BuildId: e7ef50e08970f017a96fde6101c5e2491acc674a) in free ==19190==ABORTING FAIL: "invocation of perf script report task-analyzer --csv-summary csvsummary --summary-extended command failed" Error message: "" FAIL: "test_csvsummary_extended" Error message: "Failed to find required string:'Out-Out;'." ---- end(-1) ---- 132: perf script task-analyzer tests : FAILED! ``` The buf_size if always set to phdr->p_filesz, but that may be 0 causing a free and realloc to return NULL. This is treated in filename__read_build_id like a failure and the buffer is freed again. To avoid this problem only grow buf, meaning the buf_size will never be 0. This also reduces the number of memory (re)allocations. Fixes: b691f64 ("perf symbols: Implement poor man's ELF parser") Signed-off-by: Ian Rogers <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent f745817 commit fa9c497

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

tools/perf/util/symbol-minimal.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,19 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
147147
if (phdr->p_type != PT_NOTE)
148148
continue;
149149

150-
buf_size = phdr->p_filesz;
151150
offset = phdr->p_offset;
152-
tmp = realloc(buf, buf_size);
153-
if (tmp == NULL)
154-
goto out_free;
155-
156-
buf = tmp;
151+
if (phdr->p_filesz > buf_size) {
152+
buf_size = phdr->p_filesz;
153+
tmp = realloc(buf, buf_size);
154+
if (tmp == NULL)
155+
goto out_free;
156+
buf = tmp;
157+
}
157158
fseek(fp, offset, SEEK_SET);
158-
if (fread(buf, buf_size, 1, fp) != 1)
159+
if (fread(buf, phdr->p_filesz, 1, fp) != 1)
159160
goto out_free;
160161

161-
ret = read_build_id(buf, buf_size, bid, need_swap);
162+
ret = read_build_id(buf, phdr->p_filesz, bid, need_swap);
162163
if (ret == 0) {
163164
ret = bid->size;
164165
break;
@@ -199,18 +200,19 @@ int filename__read_build_id(const char *filename, struct build_id *bid)
199200
if (phdr->p_type != PT_NOTE)
200201
continue;
201202

202-
buf_size = phdr->p_filesz;
203203
offset = phdr->p_offset;
204-
tmp = realloc(buf, buf_size);
205-
if (tmp == NULL)
206-
goto out_free;
207-
208-
buf = tmp;
204+
if (phdr->p_filesz > buf_size) {
205+
buf_size = phdr->p_filesz;
206+
tmp = realloc(buf, buf_size);
207+
if (tmp == NULL)
208+
goto out_free;
209+
buf = tmp;
210+
}
209211
fseek(fp, offset, SEEK_SET);
210-
if (fread(buf, buf_size, 1, fp) != 1)
212+
if (fread(buf, phdr->p_filesz, 1, fp) != 1)
211213
goto out_free;
212214

213-
ret = read_build_id(buf, buf_size, bid, need_swap);
215+
ret = read_build_id(buf, phdr->p_filesz, bid, need_swap);
214216
if (ret == 0) {
215217
ret = bid->size;
216218
break;

0 commit comments

Comments
 (0)