| Titolo | GNU GNU Binutils binutils 2.47 NULL Pointer Dereference |
|---|
| Descrizione | # Vulnerability: NULL Pointer Dereference in `_bfd_x86_elf_late_size_sections` / `elf_x86_allocate_dynrelocs` of GNU Binutils ld During Dynamic Relocation Size Calculation
**Project:** GNU Binutils / GNU ld (https://sourceware.org/git/?p=binutils-gdb.git)
**Version:** Present in binutils 2.47 (release tarball version date `20260726`) and dev snapshot `2.47.50.20260722` (commit `640a79623`); fixed on master by five commits (target milestone 2.48, marked RESOLVED FIXED on 2026-08-06)
**Date:** 2026-07-28
**Severity:** Medium
**OWASP:** N/A — native binary parsing memory safety
**CWE:** CWE-476 - NULL Pointer Dereference
------
## Affected Files
```text
bfd/elfxx-x86.c (`elf_x86_allocate_dynrelocs`, `_bfd_x86_elf_late_size_sections`)
bfd/elf32-i386.c, bfd/elf64-x86-64.c (relocation scan and validation)
ld/ldlang.c (`lang_init_start_stop`, `lang_gc_sections`)
bfd/elflink.c (`bfd_elf_gc_sections`)
```
## Root Cause
When malformed input drives dynamic relocation size calculation, the x86 ELF size-sections path dereferences a NULL `htab`/`sreloc` (or equivalent pointer):
- `bug_1.o` crashes in `elf_x86_allocate_dynrelocs()` at `bfd/elfxx-x86.c:337` (SEGV reading `0x70`);
- `bug_4.o` crashes in the same function at `:553` (SEGV reading `0x38`);
- `bug_18.o` crashes in its caller `_bfd_x86_elf_late_size_sections()` at `:2334` (SEGV reading `0x38`).
All three PoCs point to one class of root cause: section/`sreloc` pointers being NULL and unvalidated during dynamic relocation allocation. Upstream (H.J. Lu) fixed it across five commits at multiple levels:
1. `d1268210b6f6` — do not define section symbols for excluded sections: when a section has `SEC_EXCLUDE` set (e.g., `SHF_EXCLUDE` set in the ELF input), define `__start`, `__stop`, `.startof.`, `.sizeof.` symbols only for relocatable links or when the bit is cleared;
2. `471130b39c0` — validate illegal GOT/PLT/TLS relocations: error on TLS/GOT/PLT relocations in non-alloc, non-debug sections; error on TLS relocations against non-thread-local symbols;
3. `283d3198bed` — improve relocation error reporting: report `out of section range` for `bfd_reloc_outofrange` instead of the obscure `error 4`;
4. `0a84e560216` — check that required dynamic relocation sections were created: after `elf_link_read_relocs_from_section` aborts on a bad relocation, no further relocations are processed and the required dynamic relocation section is never created; skip dynamic relocation counting in that case;
5. `a692a633d40` — check input section GC errors: `bfd_elf_gc_sections` returns false when `gc_mark_extra_sections` returns false, and `lang_gc_sections` checks the return value and reports a fatal error (e.g., `bad reloc symbol index ... in section '.text.get_tls[get_tls]'`).
## Steps to Reproduce
The following commands assume this report's `pocs` directory sits next to the built `binutils-gdb` directory:
```bash
git clone https://sourceware.org/git/binutils-gdb.git binutils-gdb
cd binutils-gdb
git checkout 640a79623
CC=gcc CFLAGS='-g -O1 -fsanitize=address -fno-omit-frame-pointer -fno-common' \
LDFLAGS='-fsanitize=address' \
./configure --disable-gdb --disable-gdbserver --disable-sim --disable-cet \
--disable-werror --disable-nls --enable-targets=x86_64-linux-gnu MAKEINFO=true
make -j
```
The binutils 2.47 release tarball (version date `20260726`) also reproduces (all three PoCs). Run the PoCs:
```bash
export ASAN_OPTIONS="abort_on_error=0:symbolize=1:detect_leaks=0:allocator_may_return_null=1:halt_on_error=1"
./ld/ld-new --gc-sections --no-print-gc-sections -w -o /dev/null ../pocs/34448/bug_1.o # :337
./ld/ld-new --shared --gc-sections -o /dev/null ../pocs/34448/bug_4.o # :553
./ld/ld-new --shared --gc-sections -o /dev/null ../pocs/34448/bug_18.o # :2334
```
Expected result on the vulnerable version:
bug_1 (`:337`):
```text
==64986==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000070
The signal is caused by a READ memory access.
#0 elf_x86_allocate_dynrelocs bfd/elfxx-x86.c:337
#1 bfd_link_hash_traverse bfd/linker.c:693
#2 _bfd_x86_elf_late_size_sections bfd/elfxx-x86.c:2418
#3 bfd_elf_size_dynamic_sections bfd/elflink.c:7756
SUMMARY: AddressSanitizer: SEGV in elf_x86_allocate_dynrelocs
```
bug_4 (`:553`):
```text
==65031==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000038
The signal is caused by a READ memory access.
#0 elf_x86_allocate_dynrelocs bfd/elfxx-x86.c:553
SUMMARY: AddressSanitizer: SEGV in elf_x86_allocate_dynrelocs
```
bug_18 (`:2334`):
```text
==65836==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000038
The signal is caused by a READ memory access.
#0 _bfd_x86_elf_late_size_sections bfd/elfxx-x86.c:2334
#1 bfd_elf_size_dynamic_sections bfd/elflink.c:7756
#2 ldelf_before_allocation ld/ldelf.c:1840
SUMMARY: AddressSanitizer: SEGV in _bfd_x86_elf_late_size_sections
```

## Impact
A crafted object file can crash `ld` during dynamic relocation size calculation (a regular `--gc-sections`/`--shared` combination), causing denial of service. Any build service, toolchain, or CI pipeline that links untrusted object files can be terminated by this malformed input.
## Recommended Fix
Apply the five upstream fix commits (`d1268210b6f6`, `471130b39c0`, `283d3198bed`, `0a84e560216`, `a692a633d40`), or upgrade to binutils 2.48 or later which contains them. The fix series completes the error paths — section-symbol definition conditions, GOT/PLT/TLS relocation validation, dynamic relocation section existence checks, and garbage-collection error propagation — so bad input gets a clear error instead of a NULL dereference.
Keep these three malformed samples (non-alloc section relocations, out-of-range relocation symbol indexes, etc.) in AddressSanitizer regression coverage.
------
## References
- Bugzilla issue 34448: https://sourceware.org/bugzilla/show_bug.cgi?id=34448
- PoC attachment (bug_1): https://sourceware.org/bugzilla/attachment.cgi?id=16878
- PoC attachment (bug_4): https://sourceware.org/bugzilla/attachment.cgi?id=16879
- PoC attachment (bug_18): https://sourceware.org/bugzilla/attachment.cgi?id=16880
- Fix commit 1: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d1268210b6f6eddd267a4ebe4b7d36b802af628d
- Fix commit 2: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=471130b39c03623ec6d78ece377ff4da3f6bfe7b
- Fix commit 3: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=283d3198beda5110a8417fd09b336a34bbd2705c
- Fix commit 4: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0a84e5602163e9f95a6f137ced28aff0507ce790
- Fix commit 5: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a692a633d407995a5ce87e84a0b1032e9ac51360
- Affected versions: binutils 2.47 (version date 20260726) / dev snapshot commit 640a79623
- Binutils repository: https://sourceware.org/git/?p=binutils-gdb.git
- Reproduction materials (PoC): https://github.com/Ech06/CVE_submit/tree/main/bugzilla/pocs/34448
## Notes
The issue was marked RESOLVED FIXED on 2026-08-06 (target milestone 2.48); H.J. Lu confirmed "Fixed for 2.48". The fix spans five commits; `471130b39c0` is also related to PR ld/34444 (heap out-of-bounds read/write in `elf_x86_64_relocate_section`). |
|---|
| Fonte | ⚠️ https://github.com/Ech06/CVE_submit/tree/main/bugzilla/pocs/34448 |
|---|
| Utente | Ech06 (UID 98792) |
|---|
| Sottomissione | 16/08/2026 13:04 (30 giorni fa) |
|---|
| Moderazione | 15/09/2026 04:01 (30 days later) |
|---|
| Stato | Accettato |
|---|
| Voce VulDB | 404053 [GNU Binutils 2.47 Dynamic Relocation Allocation bfd/elfxx-x86.c elf_x86_allocate_dynrelocs negazione del servizio] |
|---|
| Punti | 20 |
|---|