diff mbox series

[scarthgap] binutils: fix CVE-2025-69645

Message ID 20260716095854.65840-1-roland.kovacs@est.tech
State New
Headers show
Series [scarthgap] binutils: fix CVE-2025-69645 | expand

Commit Message

Roland Kovacs July 16, 2026, 9:58 a.m. UTC
Binutils objdump contains a denial-of-service vulnerability when processing
a crafted binary with malformed DWARF debug information. A logic error in
the handling of DWARF compilation units can result in an invalid offset_size
value being used inside byte_get_little_endian, leading to an abort (SIGABRT).
A local attacker can trigger the crash by supplying a malicious input file.

Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
---
 .../binutils/binutils-2.42.inc                |   1 +
 .../binutils/binutils/CVE-2025-69645.patch    | 135 ++++++++++++++++++
 2 files changed, 136 insertions(+)
 create mode 100644 meta/recipes-devtools/binutils/binutils/CVE-2025-69645.patch
diff mbox series

Patch

diff --git a/meta/recipes-devtools/binutils/binutils-2.42.inc b/meta/recipes-devtools/binutils/binutils-2.42.inc
index 7e83f72632..8f775f20e7 100644
--- a/meta/recipes-devtools/binutils/binutils-2.42.inc
+++ b/meta/recipes-devtools/binutils/binutils-2.42.inc
@@ -74,5 +74,6 @@  SRC_URI = "\
      file://0030-CVE-2025-11840.patch \
      file://CVE-2025-69644-CVE-2025-69647.patch \
      file://CVE-2025-69648.patch \
+     file://CVE-2025-69645.patch \
 "
 S  = "${WORKDIR}/git"
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2025-69645.patch b/meta/recipes-devtools/binutils/binutils/CVE-2025-69645.patch
new file mode 100644
index 0000000000..78d2d62a50
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2025-69645.patch
@@ -0,0 +1,135 @@ 
+From 3fe207e0625a76c8cba932e435762bfb5f544131 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Sun, 30 Nov 2025 12:51:54 +1030
+Subject: [PATCH] PR 33637, abort in byte_get
+
+When DWARF5 support was added to binutils in commit 77145576fadc,
+the loop over CUs in process_debug_info set do_types when finding a
+DW_UT_type unit, in order to process the signature and type offset
+entries.  Unfortunately that broke debug_information/debug_info_p
+handling, which previously was allocated and initialised for each unit
+in .debug_info.  debug_info_p was NULL when processing a DWARF4
+.debug_types section.  After the 77145576fadc change it was possible
+for debug_infp_p to be non-NULL but point to zeroed data, in
+particular a zeroed offset_size.  A zero for offset_size led to the
+byte_get_little_endian abort triggered by the fuzzer testcase.
+
+I haven't investigated whether there is any need for a valid
+offset_size when processing a non-fuzzed DWARF4 .debug_types section.
+Presumably we'd have found that out in the last 6 years if that was
+the case.  We don't want to change debug_information[] for
+.debug_types!
+
+	PR 33637
+	* dwarf.c (process_debug_info): Don't change DO_TYPES flag bit
+	depending on cu_unit_type.  Instead test cu_unit_type along
+	with DO_TYPES to handle signature and type_offset for a type
+	unit.  Move find_cu_tu_set_v2 call a little later.
+
+CVE: CVE-2025-69645
+Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cdb728d4da6184631989b192f1022c219dea7677]
+
+Note:
+  Backported patch differs from upstream as commit
+  1f7e70ddd2c49dd5442b8873dd6ef29b0a10fdc3 is not cherry-picked
+  just to introduce `do_flags` instead of the separate `do_type`
+  and `do_loc` booleans for it to apply cleanly.
+
+Signed-off-by: Roland Kovacs <roland.kovacs@est.tech>
+---
+ binutils/dwarf.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/binutils/dwarf.c b/binutils/dwarf.c
+index 615e051b2bf..836872f1b26 100644
+--- a/binutils/dwarf.c
++++ b/binutils/dwarf.c
+@@ -3865,8 +3865,6 @@ process_debug_info (struct dwarf_section * section,
+ 
+       SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu);
+ 
+-      this_set = find_cu_tu_set_v2 (cu_offset, do_types);
+-
+       if (compunit.cu_version < 5)
+ 	{
+ 	  compunit.cu_unit_type = DW_UT_compile;
+@@ -3876,8 +3874,6 @@ process_debug_info (struct dwarf_section * section,
+       else
+ 	{
+ 	  SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
+-	  do_types = (compunit.cu_unit_type == DW_UT_type);
+-
+ 	  SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
+ 	}
+ 
+@@ -3891,6 +3887,7 @@ process_debug_info (struct dwarf_section * section,
+ 	  SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end_cu);
+ 	}
+ 
++      this_set = find_cu_tu_set_v2 (cu_offset, do_types);
+       if (this_set == NULL)
+ 	{
+ 	  abbrev_base = 0;
+@@ -3947,8 +3944,6 @@ process_debug_info (struct dwarf_section * section,
+ 
+       SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu);
+ 
+-      this_set = find_cu_tu_set_v2 (cu_offset, do_types);
+-
+       if (compunit.cu_version < 5)
+ 	{
+ 	  compunit.cu_unit_type = DW_UT_compile;
+@@ -3958,13 +3953,12 @@ process_debug_info (struct dwarf_section * section,
+       else
+ 	{
+ 	  SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
+-	  do_types = (compunit.cu_unit_type == DW_UT_type);
+-
+ 	  SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
+ 	}
+ 
+       SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end_cu);
+ 
++      this_set = find_cu_tu_set_v2 (cu_offset, do_types);
+       if (this_set == NULL)
+ 	{
+ 	  abbrev_base = 0;
+@@ -3996,7 +3990,7 @@ process_debug_info (struct dwarf_section * section,
+ 	  compunit.cu_pointer_size = offset_size;
+ 	}
+ 
+-      if (do_types)
++      if (do_types || compunit.cu_unit_type == DW_UT_type)
+ 	{
+ 	  SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, end_cu);
+ 	  SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end_cu);
+@@ -4011,7 +4005,7 @@ process_debug_info (struct dwarf_section * section,
+       if ((do_loc || do_debug_loc || do_debug_ranges || do_debug_info)
+ 	  && num_debug_info_entries == 0
+ 	  && alloc_num_debug_info_entries > unit
+-	  && ! do_types)
++	  && !do_types)
+ 	{
+ 	  free_debug_information (&debug_information[unit]);
+ 	  memset (&debug_information[unit], 0, sizeof (*debug_information));
+@@ -4042,7 +4036,7 @@ process_debug_info (struct dwarf_section * section,
+ 	  printf (_("   Abbrev Offset: %#" PRIx64 "\n"),
+ 		  compunit.cu_abbrev_offset);
+ 	  printf (_("   Pointer Size:  %d\n"), compunit.cu_pointer_size);
+-	  if (do_types)
++	  if (do_types || compunit.cu_unit_type == DW_UT_type)
+ 	    {
+ 	      printf (_("   Signature:     %#" PRIx64 "\n"), signature);
+ 	      printf (_("   Type Offset:   %#" PRIx64 "\n"), type_offset);
+@@ -4319,7 +4313,7 @@ process_debug_info (struct dwarf_section * section,
+      we need to process .debug_loc and .debug_ranges sections.  */
+   if ((do_loc || do_debug_loc || do_debug_ranges || do_debug_info)
+       && num_debug_info_entries == 0
+-      && ! do_types)
++      && !do_types)
+     {
+       if (num_units > alloc_num_debug_info_entries)
+ 	num_debug_info_entries = alloc_num_debug_info_entries;
+-- 
+2.34.1
+