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

            Bug ID: 34392
           Summary: libdw: heap-buffer-overflow read in dwarf_getpubnames
                    while parsing .debug_pubnames
           Product: elfutils
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libdw
          Assignee: unassigned at sourceware dot org
          Reporter: karankurani3k at gmail dot com
                CC: elfutils-devel at sourceware dot org
  Target Milestone: ---

Created attachment 16840
  --> https://sourceware.org/bugzilla/attachment.cgi?id=16840&action=edit
Standalone reproducer and ASan trace for .debug_pubnames OOB read

On current elfutils HEAD 304f2a62981badd1d1c8f2507dc8d156856e065b,
dwarf_getpubnames() can read 4 bytes past the end of a malloc-backed ELF image
while parsing .debug_pubnames.

git status --porcelain printed no output.

The issue is in libdw/dwarf_getpubnames.c:get_offsets().

The code validates the referenced .debug_info CU offset with only a 3-byte
minimum:

  if (__libdw_read_offset (dbg, dbg, IDX_debug_pubnames,
                           readp + 2, len_bytes,
                           &mem[cnt].cu_offset, IDX_debug_info, 3))

It then immediately performs a 4-byte read from that offset:

  if (read_4ubyte_unaligned_noncvt (infop) == DWARF3_LENGTH_64_BIT)

A malformed ELF can set the .debug_pubnames CU offset to 0 and provide a
.debug_info section that is exactly 3 bytes long and placed as the final
section
ending at EOF. The offset check passes, then the 4-byte read crosses one byte
past the malloc-backed file buffer.

Public API path:

  elf_memory()
  -> dwarf_begin_elf()
  -> dwarf_getpubnames()
  -> get_offsets()
  -> read_4ubyte_unaligned_noncvt()

PoC ELF layout:

  .debug_pubnames offset=320 size=18
  .debug_info offset=377 size=3
  total ELF size=380
  .debug_info is final at EOF

ASan result:

  ERROR: AddressSanitizer: heap-buffer-overflow
  READ of size 4
  #0 read_4ubyte_unaligned_noncvt ../../elfutils/libdw/memory-access.h:283
  #1 get_offsets ../../elfutils/libdw/dwarf_getpubnames.c:116
  #2 dwarf_getpubnames ../../elfutils/libdw/dwarf_getpubnames.c:163

Impact:

  A malicious or malformed ELF/DWARF file can trigger an out-of-bounds read in
  libdw consumers that parse untrusted debug data and call dwarf_getpubnames().

  The immediate impact is crash/DoS or undefined behavior while processing the
  malformed ELF/DWARF file. I am not claiming RCE.

Not a duplicate:

  This is a different path from the recently fixed issues in .debug_macro,
  .debug_str_offsets, .debug_rnglists, .debug_loclists, .debug_frame CIE
  augmentation, and .debug_line.

  This issue is specifically in .debug_pubnames / .debug_info validation
through
  dwarf_getpubnames().

Additional check:

  I also checked .debug_pubtypes on this HEAD. There appears to be no
  dwarf_getpubtypes() API, no IDX_debug_pubtypes, and no reachable libdw
  .debug_pubtypes parser path, so this report is limited to .debug_pubnames.

Please include the following credit if this is fixed:

  Reported-by: Karan Kurani <[email protected]>

Suggested fix:

  Require at least 4 bytes at the referenced .debug_info CU offset before
  reading the initial unit_length field.

  For example, change the size argument in the __libdw_read_offset() call from
  3 to 4:

    if (__libdw_read_offset (dbg, dbg, IDX_debug_pubnames,
                             readp + 2, len_bytes,
                             &mem[cnt].cu_offset, IDX_debug_info, 4))
      goto err_return;

  Alternatively, add an explicit 4-byte bounds check before:

    read_4ubyte_unaligned_noncvt (infop)

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

Reply via email to