https://sourceware.org/bugzilla/show_bug.cgi?id=33548
Bug ID: 33548
Summary: objdump --ctf: Heap buffer overflow
Product: binutils
Version: 2.45
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: shiraishi at os dot is.s.u-tokyo.ac.jp
Target Milestone: ---
## 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)
{
```
--
You are receiving this mail because:
You are on the CC list for the bug.