Hi maintainers, we have found another issue in objdump's CTF handling 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 where file size verification is not performed, which causes a segmentation fault (SEGV) due to out-of-bounds memory access when an invalid size is 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\x01\x02\x03\x04\x05\x06\x07\x06\x07\x6C\x2D\x2D\x64\x65\x62\x75\x67\x67\x69\x8D\x67\x20\x2C\x2D\x46\x00\x00\x00\x00\x20\x2D' > mini ./binutils/objdump ./mini --target=binary --ctf=.data ``` ## Output ``` AddressSanitizer:DEADLYSIGNAL ================================================================= ==222433==ERROR: AddressSanitizer: SEGV on unknown address (pc 0x55e6ee18837e bp 0x7ffc7b018db0 sp 0x7ffc7b018b00 T0) ==222433==The signal is caused by a READ memory access. ==222433==Hint: this fault was caused by a dereference of a high value address (see register values below). Disassemble the provided pc to learn which register was used. #0 0x55e6ee18837e in ctf_bfdopen_ctfsect /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/libctf/../../libctf/ctf-open-bfd.c:123:17 #1 0x55e6ee06bbd8 in dump_ctf /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:4919:15 #2 0x55e6ee0697f0 in dump_bfd /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:5837:2 #3 0x55e6ee068b87 in display_object_bfd /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:5911:7 #4 0x55e6ee068a97 in display_any_bfd /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:5990:5 #5 0x55e6ee067aa6 in display_file /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:6011:3 #6 0x55e6ee066a2d in main /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/binutils/../../binutils/objdump.c:6438:6 #7 0x7f78c7e466b4 in __libc_start_call_main /usr/src/debug/glibc/glibc/csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #8 0x7f78c7e46768 in __libc_start_main /usr/src/debug/glibc/glibc/csu/../csu/libc-start.c:360:3 #9 0x55e6edf123d4 in _start (/home/pine/Documents/fuzz/analysis2/analysis2/result_zig/objdump/out_objdump_1/default/objdump+0x1663d4) (BuildId: 77c0b96fce4c4af073e1b502b33c63b354bcea51) ==222433==Register values: rax = 0x04000f9318cbc92f rbx = 0x00007ffc7b018b00 rcx = 0x200000000000462d rdx = 0x000000000000000c rdi = 0x200000000000462d rsi = 0x000055e6ee5be5c0 rbp = 0x00007ffc7b018db0 rsp = 0x00007ffc7b018b00 r8 = 0x00000000ffffffff r9 = 0x0000000000000000 r10 = 0x0000000000000000 r11 = 0x00007f78c7e60420 r12 = 0x00007ffc7b019528 r13 = 0x0000000000000004 r14 = 0x00007f78c82ab000 r15 = 0x000055e6ee680710 AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV /home/pine/Documents/fuzz/analysis2/binutils-2.45/build/libctf/../../libctf/ctf-open-bfd.c:123:17 in ctf_bfdopen_ctfsect ``` ## Root Cause Analysis The size of le64toh (arc->ctfa_ctfs) is not validated at libctf/ctf-archive.c:402 ``` struct ctf_archive *arc = (struct ctf_archive *) ctfsect->cts_data; return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs) + sizeof (uint64_t)); ``` Therefore, when an invalid size is input, an out-of-bounds memory reference occurs at libctf/ctf-open-bfd.c:121, 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..b5d51a84 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -399,7 +399,13 @@ 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; - return (const ctf_preamble_t *) ((char *) arc + le64toh (arc->ctfa_ctfs) + size_t offset = le64toh (arc->ctfa_ctfs); + + if((offset + sizeof(uint64_t)) > ctfsect->cts_size) + { + return NULL; + } + return (const ctf_preamble_t *) ((char *) arc + offset + sizeof (uint64_t)); } else 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
