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

            Bug ID: 34934
           Summary: libdw: out-of-bounds read in DWARF 5 location list
                    parsing with a wrapped block length
           Product: elfutils
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: libdw
          Assignee: unassigned at sourceware dot org
          Reporter: vivekjha7424 at gmail dot com
                CC: elfutils-devel at sourceware dot org
  Target Milestone: ---

elfutils-0.197 (tag elfutils-0.197, commit 9f0a0fd0), built with
AddressSanitizer and UBSan, reports a heap-buffer-overflow read when
dwarf_getlocation_addr() is called on a crafted DWARF 5 .debug_loclists entry.

Where: __libdw_read_begin_end_pair_inc() reads the entry's code byte at
libdw/dwarf_ranges.c:270. It is called from getlocations_addr() at
libdw/dwarf_getlocation.c:858.

Cause: the block length of the entry is read as a ULEB128 at
libdw/dwarf_getlocation.c:889. The check at line 892 compares it as a signed
value, so a length of 2^63 or more passes. The read position is then advanced
by the unchecked addition at line 894, which wraps it below the start of the
section. The code byte at dwarf_ranges.c:270 is then read from memory before
the section data.

Reproduction (ASan, elfutils-0.197):
- Control, benign length: no report, dwarf_getlocation_addr() returns 0 or 1 as
expected.
- Entry with block length 2^64 - (77 + k), called with address 0x1000: READ of
size 1 at dwarf_ranges.c:270, located k bytes before the allocated section
image. Tested with k = 1, 2 and 8.
- The same entry with address -1: no report, returns -1.

Impact: an out-of-bounds read at an address derived from the input file. A
crash is the expected result. I have not shown information disclosure.

Scope: the reproduction covers the block-length route only. Two related routes
were found by reading the code and are not yet reproduced: a DWARF64 entry
using DW_FORM_loclistx (dwarf_getlocation.c:813-838), and the rnglistx read at
dwarf_ranges.c:447-543. Neither checks the lower bound.

Current main: dwarf_ranges.c and dwarf_getlocation.c are unchanged between
elfutils-0.197 and origin/main (656c58e1), so the defect is present there too.

Suggested fix: reject a block length larger than the bytes remaining before the
position update at dwarf_getlocation.c:894, and check the lower bound before
reads at dwarf_ranges.c lines 160 and 267.

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

Reply via email to