Hi maintainers, we have found a heap-buffer-overflow and would like to report this issue. Could you confirm if this qualifies as a bug? I am happy to provide any additional information needed.
## Summary We found a bug in objdump's CTF handling where missing file size validation leads to out-of-bounds memory access and a segmentation fault (SEGV) when processing malformed input. ## Reproduction Tested Environment ``` OS: Manjaro Linux arch: x86_64 CC: clang 20.1.8 glibc: 2.41 ``` ## Reproduction Steps ``` wget https://ftp.gnu.org/gnu/binutils/binutils-2.45.tar.xz tar -xvf binutils-2.45.tar.xz cd binutils-2.45 export CFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer" export CXXFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer" export LDFLAGS="-fsanitize=address" mkdir build cd build ../configure --prefix=$PWD/install --disable-nls make -j$(nproc) printf '\xEB\x3E\x62\xD7\xA4\xF2\x47\x8B\x00' > mini ./binutils/objdump ./mini --target=binary --ctf=.data ``` ## Output ``` ==723251==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7b68d4de00d0 at pc 0x55e15dcf16cb bp 0x7fff4fca9a60 sp 0x7fff4fca9a50 READ of size 8 at 0x7b68d4de00d0 thread T0 #0 0x55e15dcf16ca in ctf_arc_bufpreamble ../../libctf/ctf-archive.c:402 #1 0x55e15dd2bbc4 in ctf_bfdopen_ctfsect ../../libctf/ctf-open-bfd.c:121 #2 0x55e15dc25fdb in dump_ctf ../../binutils/objdump.c:4919 #3 0x55e15dc2a9c5 in dump_bfd ../../binutils/objdump.c:5837 #4 0x55e15dc2ad46 in display_object_bfd ../../binutils/objdump.c:5911 #5 0x55e15dc2b06a in display_any_bfd ../../binutils/objdump.c:5990 #6 0x55e15dc2b0d6 in display_file ../../binutils/objdump.c:6011 #7 0x55e15dc2d22e in main ../../binutils/objdump.c:6438 #8 0x7f48d6c376b4 (/usr/lib/libc.so.6+0x276b4) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #9 0x7f48d6c37768 in __libc_start_main (/usr/lib/libc.so.6+0x27768) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #10 0x55e15dc0fa54 in _start (/home/pine/Documents/fuzz/analysis2/test/binutils-2.45/build/binutils/objdump+0x145a54) (BuildId: 7cdbf8eb625396e3744720a861ca2f10ac8b8c72) 0x7b68d4de00d0 is located 23 bytes after 9-byte region [0x7b68d4de00b0,0x7b68d4de00b9) allocated by thread T0 here: #0 0x7f48d6f20e15 in malloc /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_malloc_linux.cpp:67 #1 0x55e15dd797ed in bfd_malloc ../../bfd/libbfd.c:291 #2 0x55e15dd6c7ee in bfd_get_full_section_contents ../../bfd/compress.c:742 #3 0x55e15dd845f7 in bfd_malloc_and_get_section ../../bfd/section.c:1662 #4 0x55e15dc24408 in read_section ../../binutils/objdump.c:4581 #5 0x55e15dc25f12 in dump_ctf ../../binutils/objdump.c:4907 #6 0x55e15dc2a9c5 in dump_bfd ../../binutils/objdump.c:5837 #7 0x55e15dc2ad46 in display_object_bfd ../../binutils/objdump.c:5911 #8 0x55e15dc2b06a in display_any_bfd ../../binutils/objdump.c:5990 #9 0x55e15dc2b0d6 in display_file ../../binutils/objdump.c:6011 #10 0x55e15dc2d22e in main ../../binutils/objdump.c:6438 #11 0x7f48d6c376b4 (/usr/lib/libc.so.6+0x276b4) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #12 0x7f48d6c37768 in __libc_start_main (/usr/lib/libc.so.6+0x27768) (BuildId: 468e3585c794491a48ea75fceb9e4d6b1464fc35) #13 0x55e15dc0fa54 in _start (/home/pine/Documents/fuzz/analysis2/test/binutils-2.45/build/binutils/objdump+0x145a54) (BuildId: 7cdbf8eb625396e3744720a861ca2f10ac8b8c72) SUMMARY: AddressSanitizer: heap-buffer-overflow ../../libctf/ctf-archive.c:402 in ctf_arc_bufpreamble Shadow bytes around the buggy address: 0x7b68d4ddfe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b68d4ddfe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b68d4ddff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b68d4ddff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7b68d4de0000: fa fa fd fa fa fa 00 04 fa fa 00 04 fa fa 00 04 =>0x7b68d4de0080: fa fa 06 fa fa fa 00 01 fa fa[fa]fa fa fa fa fa 0x7b68d4de0100: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b68d4de0180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b68d4de0200: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b68d4de0280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x7b68d4de0300: 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 ==723251==ABORTING ``` ## Root Cause Analysis At libctf/ctf-archive.c:402, the code only verifies that ctfsect->cts_size is at least 8 bytes, but then accesses struct members assuming 16 bytes are available, resulting in out-of-bounds heap memory access. ``` if (ctfsect->cts_data != NULL && ctfsect->cts_size > sizeof (uint64_t) && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC)) { struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data; return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs) + sizeof (uint64_t)); ``` Additionally, this eventually leads to an out-of-bounds memory reference at libctf/ctf-open-bfd.c:123, resulting in a SEGV. ``` if (ctfsect->cts_data == NULL) { bfderrstr = N_("CTF section is NULL"); goto err; } preamble = ctf_arc_bufpreamble (ctfsect); if (preamble->ctp_flags & CTF_F_DYNSTR) { symhdr = &elf_tdata (abfd)->dynsymtab_hdr; strtab_name = ".dynstr"; symtab_name = ".dynsym"; ``` ## Proposed Fix ``` diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index 6c4595fc..d4cd5642 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -399,6 +399,10 @@ ctf_arc_bufpreamble (const ctf_sect_t *ctfsect) && (le64toh ((*(uint64_t *) ctfsect->cts_data)) == CTFA_MAGIC)) { struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data; + if(ctfsect->cts_size < sizeof(uint64_t) * 2) + { + return NULL; + } return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs) + sizeof (uint64_t)); } diff --git a/libctf/ctf-open-bfd.c b/libctf/ctf-open-bfd.c index 7241de70..def9cf6d 100644 --- a/libctf/ctf-open-bfd.c +++ b/libctf/ctf-open-bfd.c @@ -119,6 +119,10 @@ ctf_bfdopen_ctfsect (struct bfd *abfd _libctf_unused_, goto err; } preamble = ctf_arc_bufpreamble (ctfsect); + if(preamble == NULL) + { + goto err; + } if (preamble->ctp_flags & CTF_F_DYNSTR) { ``` Best wishes, Momoko Shiraishi
