https://sourceware.org/bugzilla/show_bug.cgi?id=34323

Paul Wang <lswang1112 at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lswang1112 at gmail dot com

--- Comment #1 from Paul Wang <lswang1112 at gmail dot com> ---
Created attachment 16805
  --> https://sourceware.org/bugzilla/attachment.cgi?id=16805&action=edit
Minimal 64-byte PoC ELF triggering null-pointer dereference in
process_got_section_contents

Additional analysis for bug #34323: null-pointer dereference in
process_got_section_contents via NULL section_headers

Affected version: GNU Binutils 2.46.50.20260629 (git HEAD 0e73a13c)
Confirmed reproduced on latest upstream HEAD as of 2026-06-30.

I independently found this bug through fuzzing and am providing a root
cause analysis, a minimal 64-byte PoC, ASan traces, and a suggested fix,
hoping this helps move the issue toward resolution.

------------------------------------------------------------------------
ROOT CAUSE
------------------------------------------------------------------------

process_got_section_contents() iterates over filedata->section_headers to
locate .got sections, but does not guard against section_headers being NULL:

    /* binutils/readelf.c:21563-21568 */
    initialise_dumps_byname (filedata);

    for (i = 0, section = filedata->section_headers;   /* can be NULL */
         i < filedata->file_header.e_shnum;
         i++, section++)
      if (section->sh_type == SHT_PROGBITS              /* line 21568: NULL
deref */
          && section->sh_size != 0)

filedata->section_headers is populated by get_section_headers(). When the
ELF header's e_shoff points beyond the end of the file, get_section_headers()
fails and returns NULL, leaving section_headers as NULL. However,
process_got_section_contents() is still entered when e_shnum > 0, so the
loop executes and crashes on section->sh_type.

------------------------------------------------------------------------
ASAN + UBSAN OUTPUT
------------------------------------------------------------------------

    ../../src/binutils/readelf.c:21568:16: runtime error:
        member access within null pointer of type 'struct Elf_Internal_Shdr'

    ERROR: AddressSanitizer: SEGV on unknown address 0x000000000004
        #0 process_got_section_contents   binutils/readelf.c:21568
        #1 process_object                 binutils/readelf.c:24981
        #2 process_file                   binutils/readelf.c:25404
        #3 main                           binutils/readelf.c:25470
    SUMMARY: AddressSanitizer: SEGV in process_got_section_contents

GDB on a plain build:

    Program received signal SIGSEGV, Segmentation fault.
    #0  process_got_section_contents (filedata=...) at binutils/readelf.c:21568

------------------------------------------------------------------------
HOW TO REPRODUCE
------------------------------------------------------------------------

Build from latest HEAD:

    git clone --depth 1 https://sourceware.org/git/binutils-gdb.git
    cd binutils-gdb
    mkdir build && cd build
    ../configure --disable-gdb \
      CFLAGS="-g -O1 -fsanitize=address,undefined -Wno-error=format-overflow"
    make -j$(nproc) all-binutils

The attached poc.elf is 64 bytes (minimal ELF -- header only, no sections).
Run with:

    ./binutils/readelf --dyn-syms -D -W -a -s poc.elf

The 64-byte PoC in hexadecimal:

    00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
    00000010: 0300 3e00 0100 0000 2011 0000 0000 0000  ..>..... .......
    00000020: 4000 0000 0000 0000 08be 0000 0000 0000  @...............
    00000030: 0000 0000 4000 3800 0d00 4000 2700 2600  [email protected]...@.'.&.

Key ELF header fields:

    e_type    0x10  0x0003    ET_DYN
    e_machine 0x12  0x003e    x86-64
    e_shoff   0x28  0x0000be08  section header offset (far beyond 64-byte EOF)
    e_shnum   0x3c  0x0027    claims 39 sections

e_shoff = 0xbe08 points past the file end, so get_section_headers() fails
and section_headers remains NULL. But e_shnum = 39 > 0 allows the loop to
run, causing the dereference at line 21568.

------------------------------------------------------------------------
Build & Platform
------------------------------------------------------------------------

binutils version: GNU Binutils 2.46.50.20260629 (git HEAD 0e73a13c)
component: readelf
OS: Ubuntu 24.04.4 LTS
arch: x86_64

------------------------------------------------------------------------
SUGGESTED FIX
------------------------------------------------------------------------

Add a NULL guard at the top of the section-iteration loop in
process_got_section_contents() (binutils/readelf.c):

    + if (filedata->section_headers == NULL)
    +   goto out;

    for (i = 0, section = filedata->section_headers;
         i < filedata->file_header.e_shnum;
         i++, section++)

Alternatively, guard the loop condition directly:

    for (i = 0, section = filedata->section_headers;
    -    i < filedata->file_header.e_shnum;
    +    filedata->section_headers != NULL && i <
filedata->file_header.e_shnum;
         i++, section++)

------------------------------------------------------------------------
IMPACT
------------------------------------------------------------------------

Null-pointer dereference (CWE-476) in process_got_section_contents,
triggered by a 64-byte ELF with an out-of-range section header offset.
Reproducible with standard readelf flags (-a -s -D). Impact is denial
of service.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to