]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
readelf: Fix heap-buffer-overflow reading .debug_cu_index size table
authorSujal Tuladhar <sujaltuladhar1231@gmail.com>
Wed, 24 Jun 2026 16:22:34 +0000 (22:07 +0545)
committerMark Wielaard <mark@klomp.org>
Thu, 25 Jun 2026 16:14:33 +0000 (18:14 +0200)
print_cu_index_section validated the .debug_cu_index/.debug_tu_index size
table against dataend using only a single row:

  lengths_end = lengths + section_count * 4;

but the size-table print loop iterates one row per used unit, with
prow = lengths + (row - 1) * section_count * 4 for row up to unit_count,
reading up to lengths + unit_count * section_count * 4.  For unit_count >= 2
this reads (unit_count - 1) * section_count * 4 bytes past the validated end
of the section -- a heap-buffer-overflow read reachable from a crafted
.dwp/ELF via 'eu-readelf --debug-dump=cu_index FILE' (or 'eu-readelf -w').

The offset table is not affected: its extent
(unit_count * section_count * off_bytes, which equals lengths) is already
validated against dataend.  Size lengths_end over all unit_count rows to
match, and guard the multiplication against overflow.

* src/readelf.c (print_cu_index_section): Size the size table over
all unit_count rows; add an overflow guard.

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

Signed-off-by: Sujal Tuladhar <sujaltuladhar1231@gmail.com>
src/readelf.c

index 0258d41ae16d2ae17711c89658acabd74aae53cf..8d7950d3a6c893c8b73cabc07a15f33b07b39014 100644 (file)
@@ -12332,7 +12332,10 @@ print_cu_index_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
   /* Size slots for each section follow the offsets (used rows).  */
   const unsigned char *lengths = (offsets +
                                  unit_count * section_count * off_bytes);
-  const unsigned char *lengths_end = lengths + section_count * 4;
+  /* The size table has one row of section_count 4-byte slots per unit,
+     just like the offset table, so it spans unit_count rows (not one).  */
+  const unsigned char *lengths_end = (lengths +
+                                     unit_count * section_count * 4);
 
   /* Sanity check the above against dataend.  */
   if ((slot_count > UINT32_MAX / 8)
@@ -12340,6 +12343,8 @@ print_cu_index_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
       || (unit_count > SIZE_MAX / off_bytes)
       || ((unit_count != 0) && (section_count > SIZE_MAX / unit_count))
       || ((section_count != 0) && (unit_count > SIZE_MAX / section_count))
+      || ((unit_count != 0)
+         && (section_count > SIZE_MAX / (4 * (size_t) unit_count)))
       || (indices > dataend)
       || (sections > dataend)
       || (offsets > dataend)