https://sourceware.org/bugzilla/show_bug.cgi?id=34654
Bug ID: 34654
Summary: Heap-buffer-overflow write in ELF synthetic-symbol
construction (`bfd/elf.c`)
Product: binutils
Version: 2.47
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: hdzhao214 at gmail dot com
Target Milestone: ---
Created attachment 17013
--> https://sourceware.org/bugzilla/attachment.cgi?id=17013&action=edit
The `artifacts.zip` package includes the PoC generation script, the sanitizer
report, the bug report, and the candidate patch
## Vulnerability description
`_bfd_elf_get_synthetic_symtab` computes one allocation size for both an
`asymbol` array and the generated `name@plt+addend` strings. On a 32-bit build,
attacker-controlled dynamic-symbol names make the cumulative `size_t size`
wrap. The small allocation is then followed by unbounded copies of addend text,
and `memcpy` writes past its end.
```c
size = count * sizeof (asymbol);
for (...) {
size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
if (p->addend != 0)
size += sizeof ("+0x") - 1 + 8;
}
s = *ret = bfd_malloc (size);
```
The supplied big-endian PPC ELF shares very long string-table entries to make
the arithmetic wrap with a relatively compact input.
## Version and commit
GNU Binutils 2.47.50, commit `d715260f420066befb2d30ec8f5befcdf7ecfd84`
(2026-09-08).
## Environment
Ubuntu 24.04.4 LTS on x86_64, using an i686 AddressSanitizer build (32-bit
`size_t`), GCC 13.3.0, and Python 3.12.3.
## Steps to reproduce
1. Install the native build prerequisites plus 32-bit compiler and libc
development support:
```sh
sudo apt-get update
sudo apt-get install -y build-essential bison flex texinfo python3 \\
gcc-multilib g++-multilib libc6-dev-i386 \\
libgmp-dev libmpfr-dev libmpc-dev zlib1g-dev
```
2. Obtain the affected revision and make a 32-bit AddressSanitizer build:
```sh
export SRC="$PWD/binutils-gdb"
git clone https://sourceware.org/git/binutils-gdb.git "$SRC"
git -C "$SRC" checkout d715260f420066befb2d30ec8f5befcdf7ecfd84
mkdir "$SRC/build-i686-asan" && cd "$SRC/build-i686-asan"
CC='gcc -m32' CXX='g++ -m32' \\
CFLAGS='-O1 -g -m32 -fsanitize=address -static-libasan
-fno-omit-frame-pointer' \\
LDFLAGS='-m32 -fsanitize=address -static-libasan' \\
"$SRC/configure" --target=i686-linux-gnu --enable-targets=all \\
--enable-64-bit-bfd --disable-gdb --disable-gdbserver --disable-sim \\
--disable-gas --disable-ld --disable-gold --disable-gprof
--disable-gprofng \\
--disable-nls --disable-werror --without-zlib
make -j"$(nproc)" all-binutils
export BUILD="$SRC/build-i686-asan"
```
3. Place the supplied `gen_ppc_synth_overflow.py` in a writable directory and
generate the input:
```sh
export WORK="$PWD/poc-work"
mkdir -p "$WORK"
python3 gen_ppc_synth_overflow.py "$WORK/evil_ppc32_plt.elf"
```
4. Trigger the fault:
```sh
ASAN_OPTIONS=detect_leaks=0:abort_on_error=1 \\
"$BUILD/binutils/objdump" -d "$WORK/evil_ppc32_plt.elf" >/dev/null
```
## Sanitizer report
The following is the complete, unmodified contents of `sanitizer_report.txt`.
```text
=================================================================
==2500255==ERROR: AddressSanitizer: heap-buffer-overflow on address 0xe7b03ec8
at pc 0x5c712017 bp 0xff9ee838 sp 0xff9ee40c
WRITE of size 8 at 0xe7b03ec8 thread T0
#0 0x5c712016 in memcpy
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/build32-asan/binutils/objdump+0xef016)
(BuildId: 470c59223d09ac1bd1019052b101518a1f12b5cf)
#1 0x5c9eece7 in memcpy
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:29
#2 0x5c9eece7 in _bfd_elf_get_synthetic_symtab
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/bfd/elf.c:13488
#3 0x5cb014cd in ppc_elf_get_synthetic_symtab
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/bfd/elf32-ppc.c:1818
#4 0x5c801a26 in dump_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5878
#5 0x5c805012 in display_object_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5971
#6 0x5c805012 in display_any_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6050
#7 0x5c805190 in display_file
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6071
#8 0x5c807489 in main
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6494
#9 0xf4767c74
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/sysroot/usr/lib32/libc.so.6+0x24c74)
(BuildId: a6ac4013957ce900e167743cd60a25daff1344bb)
#10 0xf4767d37 in __libc_start_main
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/sysroot/usr/lib32/libc.so.6+0x24d37)
(BuildId: a6ac4013957ce900e167743cd60a25daff1344bb)
#11 0x5c6c2916 in _start
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/build32-asan/binutils/objdump+0x9f916)
(BuildId: 470c59223d09ac1bd1019052b101518a1f12b5cf)
0xe7b03ec8 is located 0 bytes after 1608-byte region [0xe7b03880,0xe7b03ec8)
allocated by thread T0 here:
#0 0x5c78b76b in malloc
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/build32-asan/binutils/objdump+0x16876b)
(BuildId: 470c59223d09ac1bd1019052b101518a1f12b5cf)
#1 0x5c943c07 in bfd_malloc
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/bfd/libbfd.c:291
#2 0x5c9eee0c in _bfd_elf_get_synthetic_symtab
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/bfd/elf.c:13449
#3 0x5cb014cd in ppc_elf_get_synthetic_symtab
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/bfd/elf32-ppc.c:1818
#4 0x5c801a26 in dump_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5878
#5 0x5c805012 in display_object_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:5971
#6 0x5c805012 in display_any_bfd
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6050
#7 0x5c805190 in display_file
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6071
#8 0x5c807489 in main
/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/binutils-gdb/binutils/objdump.c:6494
#9 0xf4767c74
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/sysroot/usr/lib32/libc.so.6+0x24c74)
(BuildId: a6ac4013957ce900e167743cd60a25daff1344bb)
SUMMARY: AddressSanitizer: heap-buffer-overflow
(/home/shootduck/hotracer-experiments/0-day/hotracer/pilot/objdump/2026-09-08-2.47.50-d715260/hotracer/poc/task12_access34/build32-asan/binutils/objdump+0xef016)
(BuildId: 470c59223d09ac1bd1019052b101518a1f12b5cf) in memcpy
Shadow bytes around the buggy address:
0xe7b03c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xe7b03c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xe7b03d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xe7b03d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0xe7b03e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0xe7b03e80: 00 00 00 00 00 00 00 00 00[fa]fa fa fa fa fa fa
0xe7b03f00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0xe7b03f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0xe7b04000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0xe7b04080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0xe7b04100: 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
==2500255==ABORTING
```
## Potential fix
Use a wide count and reject every overflowing component of the allocation
calculation before allocating. This leaves valid synthetic symbols unchanged
and reports an oversized malformed input as `bfd_error_file_too_big`.
```diff
diff --git a/bfd/elf.c b/bfd/elf.c
@@
- size = count * sizeof (asymbol);
+ if (count > (size_t) -1 / sizeof (*s))
+ { bfd_set_error (bfd_error_file_too_big); return -1; }
+ size = (size_t) count * sizeof (*s);
@@
- size += strlen (...) + sizeof ("@plt");
+ if (len > (size_t) -1 - sizeof ("@plt")
+ || size > (size_t) -1 - len - sizeof ("@plt"))
+ { bfd_set_error (bfd_error_file_too_big); return -1; }
+ size += len + sizeof ("@plt");
```
The complete, apply-ready patch is included as `proposed-fix.patch`. It was
applied to a disposable checkout of the stated commit and the supplied proof of
concept was rerun without an AddressSanitizer finding.
--
You are receiving this mail because:
You are on the CC list for the bug.