>From 3514ed156b02bdbbc9b37bf7a4b8cb8ee5e7e402 Mon Sep 17 00:00:00 2001 From: Wang Haoran Date: Thu, 28 May 2026 15:16:53 +0800 Subject: [PATCH 2/6] perf/header: validate bitmap size before allocation in do_read_bitmap do_read_bitmap() reads a u64 size from the file and passes it directly to bitmap_zalloc(), which takes an int. If size exceeds INT_MAX the truncated int value produces a tiny allocation while the subsequent loop reads BITS_TO_U64(size) u64 values using the original u64, writing far beyond the allocated buffer and causing a heap overflow. Add a bounds check that rejects any size that does not fit in an int before the allocation. Fixes: Signed-off-by: Wang Haoran --- tools/perf/util/header.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9142a8ba4..e000eb9c1 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -287,6 +287,9 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize) if (ret) return ret; + if (size > INT_MAX) + return -EINVAL; + set = bitmap_zalloc(size); if (!set) return -ENOMEM; -- 2.53.0 --- ASan output on perf 7.0.6 (unpatched) with the attached PoC: ================================================================= ==55925==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6e688dfe0950 at pc 0x724890083d4c bp 0x7ffddd8621b0 sp 0x7ffddd861978 WRITE of size 8 at 0x6e688dfe0950 thread T0 #0 0x724890083d4b in read ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:1017 #1 0x6111c68ee74f in read /usr/include/x86_64-linux-gnu/bits/unistd.h:32 #2 0x6111c68ee74f in ion #3 0x6111c68ee74f in readn #4 0x6111c6b57dcb in process_mem_topology (perf+0x603dcb) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #5 0x6111c6b51698 in perf_file_section__process (perf+0x5fd698) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #6 0x6111c6b70992 in perf_header__process_sections (perf+0x61c992) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #7 0x6111c6b72437 in perf_session__read_header (perf+0x61e437) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #8 0x6111c6bace67 in __perf_session__new (perf+0x658e67) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #9 0x6111c6898edd in cmd_sched (perf+0x344edd) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #10 0x6111c68d787f in handle_internal_command (perf+0x38387f) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #11 0x6111c674a836 in main (perf+0x1f6836) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #12 0x72488ec2a600 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:59 #13 0x72488ec2a717 in __libc_start_main_impl ../csu/libc-start.c:360 #14 0x6111c6752754 in _start (perf+0x1fe754) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) 0x6e688dfe0951 is located 0 bytes after 1-byte region [0x6e688dfe0950,0x6e688dfe0951) allocated by thread T0 here: #0 0x72489012b40f in calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:74 #1 0x6111c6b5779d in process_mem_topology (perf+0x60379d) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #2 0x6111c6b51698 in perf_file_section__process (perf+0x5fd698) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #3 0x6111c6b70992 in perf_header__process_sections (perf+0x61c992) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #4 0x6111c6b72437 in perf_session__read_header (perf+0x61e437) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #5 0x6111c6bace67 in __perf_session__new (perf+0x658e67) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #6 0x6111c6898edd in cmd_sched (perf+0x344edd) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #7 0x6111c68d787f in handle_internal_command (perf+0x38387f) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #8 0x6111c674a836 in main (perf+0x1f6836) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #9 0x72488ec2a600 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:59 #10 0x72488ec2a717 in __libc_start_main_impl ../csu/libc-start.c:360 #11 0x6111c6752754 in _start (perf+0x1fe754) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) SUMMARY: AddressSanitizer: heap-buffer-overflow /usr/include/x86_64-linux-gnu/bits/unistd.h:32 in read Shadow bytes around the buggy address: 0x6e688dfe0680: fa fa 00 00 fa fa 00 fa fa fa 00 00 fa fa 00 fa 0x6e688dfe0700: fa fa fa fa fa fa 00 00 fa fa 00 fa fa fa 00 00 0x6e688dfe0780: fa fa 00 fa fa fa 00 fa fa fa 00 00 fa fa 00 fa 0x6e688dfe0800: fa fa 00 00 fa fa 00 fa fa fa 00 fa fa fa 00 00 0x6e688dfe0880: fa fa 00 00 fa fa 00 fa fa fa 01 fa fa fa 00 00 =>0x6e688dfe0900: fa fa 00 04 fa fa 00 fa fa fa[fa]fa fa fa fa fa 0x6e688dfe0980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x6e688dfe0a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x6e688dfe0a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x6e688dfe0b00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x6e688dfe0b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb AddressSanitizer:DEADLYSIGNAL ================================================================= ==55925==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x6111c687a20c bp 0x7ffddd8628e0 sp 0x7ffddd862810 T0) ==55925==The signal is caused by a READ memory access. ==55925==Hint: address points to the zero page. #0 0x6111c687a20c in show_schedstat_data (perf+0x32620c) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #1 0x6111c6899d09 in cmd_sched (perf+0x345d09) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #2 0x6111c68d787f in handle_internal_command (perf+0x38387f) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #3 0x6111c674a836 in main (perf+0x1f6836) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) #4 0x72488ec2a600 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:59 #5 0x72488ec2a717 in __libc_start_main_impl ../csu/libc-start.c:360 #6 0x6111c6752754 in _start (perf+0x1fe754) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) ==55925==Register values: rax = 0x0000000000000000 rbx = 0x00006eb88dfe2710 rcx = 0x0000000000000000 rdx = 0x0000000000000000 rdi = 0x0000000000000000 rsi = 0x0000000000000000 rbp = 0x00007ffddd8628e0 rsp = 0x00007ffddd862810 r8 = 0x0000000000000000 r9 = 0x0000000000000000 r10 = 0x0000000000000002 r11 = 0x0000000000000000 r12 = 0x0000000000000000 r13 = 0x0000000000000000 r14 = 0x0000000000000000 r15 = 0x000070188dfe0080 AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV (perf+0x32620c) (BuildId: 25d667fa7a7274046cb5bcb3375c4b1074f3f6db) in show_schedstat_data ==55925==ABORTING