Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
binutils (2.41-6deepin11) unstable; urgency=medium

* Fix CVE-2026-4647: Out-of-bounds read in XCOFF relocation processing

-- deepin-ci-robot <packages@deepin.org> Wed, 15 Apr 2026 13:38:01 +0800

binutils (2.41-6deepin10) unstable; urgency=medium

* fix CVE-2024-57360 CVE-2024-53589 CVE-2025-0840 CVE-2025-1176 CVE-2025-1178
Expand Down
236 changes: 236 additions & 0 deletions debian/patches/CVE-2026-4647.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
Description: Fix out-of-bounds read in XCOFF relocation processing
A flaw was found in the GNU Binutils BFD library when processing XCOFF object
files. The relocation type value is not properly validated before being used,
which can cause the program to read memory outside of intended bounds.
.
This fix adds proper validation of reloc r_type before accessing
xcoff_howto_table to prevent out-of-bounds memory access.
Author: Alan Modra <amodra@gmail.com>
Origin: upstream, https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=9e99dbc1f19ffaf18d0250788951706066ebe7f2
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33919
Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2026-4647
Forwarded: not-needed
Last-Update: 2026-04-15

From 9e99dbc1f19ffaf18d0250788951706066ebe7f2 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Fri, 13 Mar 2026 17:28:28 +1030
Subject: [PATCH] PR33919 Out-of-bounds read in XCOFF relocation processing

PR 33919
* coff-rs6000.c (xcoff_calculate_relocation): Don't use explicit
array size.
(xcoff_complain_overflow): Likewise.
(xcoff_rtype2howto): Return a NULL howto rather than aborting.
(_bfd_xcoff_reloc_name_lookup): Use ARRAY_SIZE.
(xcoff_ppc_relocate_section): Sanity check reloc r_type before
accessing xcoff_howto_table. Print r_type using %#x. Remove
now redundant later reloc r_type sanity check.
* coff64-rs6000.c: Similarly.
* libxcoff.h (XCOFF_MAX_CALCULATE_RELOCATION): Don't define.
(XCOFF_MAX_COMPLAIN_OVERFLOW): Don't define.
---
bfd/coff-rs6000.c | 36 +++++++++++++++++++++---------------
bfd/coff64-rs6000.c | 33 ++++++++++++++++++++-------------
bfd/libxcoff.h | 3 ---
3 files changed, 41 insertions(+), 31 deletions(-)

diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 62caae64f4e..00e0f5442f7 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -155,8 +155,7 @@ static xcoff_complain_function xcoff_complain_overflow_bitfield_func;
static xcoff_complain_function xcoff_complain_overflow_signed_func;
static xcoff_complain_function xcoff_complain_overflow_unsigned_func;

-xcoff_reloc_function *const
-xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] =
+xcoff_reloc_function *const xcoff_calculate_relocation[] =
{
xcoff_reloc_type_pos, /* R_POS (0x00) */
xcoff_reloc_type_neg, /* R_NEG (0x01) */
@@ -210,8 +209,7 @@ xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] =
xcoff_reloc_type_toc, /* R_TOCL (0x31) */
};

-xcoff_complain_function *const
-xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW] =
+xcoff_complain_function *const xcoff_complain_overflow[] =
{
xcoff_complain_overflow_dont_func,
xcoff_complain_overflow_bitfield_func,
@@ -1158,8 +1156,11 @@ reloc_howto_type xcoff_howto_table[] =
void
xcoff_rtype2howto (arelent *relent, struct internal_reloc *internal)
{
- if (internal->r_type > R_TOCL)
- abort ();
+ if (internal->r_type >= ARRAY_SIZE (xcoff_howto_table))
+ {
+ relent->howto = NULL;
+ return;
+ }

/* Default howto layout works most of the time */
relent->howto = &xcoff_howto_table[internal->r_type];
@@ -1183,7 +1184,7 @@ xcoff_rtype2howto (arelent *relent, struct internal_reloc *internal)
if (relent->howto->dst_mask != 0
&& (relent->howto->bitsize
!= ((unsigned int) internal->r_size & 0x1f) + 1))
- abort ();
+ relent->howto = NULL;
}

reloc_howto_type *
@@ -1236,9 +1237,7 @@ _bfd_xcoff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
{
unsigned int i;

- for (i = 0;
- i < sizeof (xcoff_howto_table) / sizeof (xcoff_howto_table[0]);
- i++)
+ for (i = 0; i < ARRAY_SIZE (xcoff_howto_table); i++)
if (xcoff_howto_table[i].name != NULL
&& strcasecmp (xcoff_howto_table[i].name, r_name) == 0)
return &xcoff_howto_table[i];
@@ -3768,6 +3767,14 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
the csect including the symbol which it references. */
if (rel->r_type == R_REF)
continue;
+ if (rel->r_type >= ARRAY_SIZE (xcoff_howto_table))
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ input_bfd, rel->r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }

/* Retrieve default value in HOWTO table and fix up according
to r_size field, if it can be different.
@@ -3787,7 +3794,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd,

default:
_bfd_error_handler
- (_("%pB: relocation (%d) at 0x%" PRIx64 " has wrong r_rsize (0x%x)\n"),
+ (_("%pB: relocation (%#x) at 0x%" PRIx64 " has wrong r_rsize (0x%x)\n"),
input_bfd, rel->r_type, (uint64_t) rel->r_vaddr, rel->r_size);
return false;
}
@@ -3863,10 +3870,9 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
}
}

- if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
- || !((*xcoff_calculate_relocation[rel->r_type])
- (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
- addend, &relocation, contents, info)))
+ if (!((*xcoff_calculate_relocation[rel->r_type])
+ (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
+ addend, &relocation, contents, info)))
return false;

/* address */
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index fa1759b5925..f6a60433e62 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -177,8 +177,7 @@ static bool xcoff64_bad_format_hook
/* Relocation functions */
static xcoff_reloc_function xcoff64_reloc_type_br;

-xcoff_reloc_function *const
-xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] =
+xcoff_reloc_function *const xcoff64_calculate_relocation[] =
{
xcoff_reloc_type_pos, /* R_POS (0x00) */
xcoff_reloc_type_neg, /* R_NEG (0x01) */
@@ -1439,8 +1438,11 @@ reloc_howto_type xcoff64_howto_table[] =
void
xcoff64_rtype2howto (arelent *relent, struct internal_reloc *internal)
{
- if (internal->r_type > R_TOCL)
- abort ();
+ if (internal->r_type >= ARRAY_SIZE (xcoff64_howto_table))
+ {
+ relent->howto = NULL;
+ return;
+ }

/* Default howto layout works most of the time */
relent->howto = &xcoff64_howto_table[internal->r_type];
@@ -1473,7 +1475,7 @@ xcoff64_rtype2howto (arelent *relent, struct internal_reloc *internal)
if (relent->howto->dst_mask != 0
&& (relent->howto->bitsize
!= ((unsigned int) internal->r_size & 0x3f) + 1))
- abort ();
+ relent->howto = NULL;
}

reloc_howto_type *
@@ -1528,9 +1530,7 @@ xcoff64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
{
unsigned int i;

- for (i = 0;
- i < sizeof (xcoff64_howto_table) / sizeof (xcoff64_howto_table[0]);
- i++)
+ for (i = 0; i < ARRAY_SIZE (xcoff64_howto_table); i++)
if (xcoff64_howto_table[i].name != NULL
&& strcasecmp (xcoff64_howto_table[i].name, r_name) == 0)
return &xcoff64_howto_table[i];
@@ -1574,6 +1574,14 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
the csect including the symbol which it references. */
if (rel->r_type == R_REF)
continue;
+ if (rel->r_type >= ARRAY_SIZE (xcoff64_howto_table))
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ input_bfd, rel->r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }

/* Retrieve default value in HOWTO table and fix up according
to r_size field, if it can be different.
@@ -1595,7 +1603,7 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,

default:
_bfd_error_handler
- (_("%pB: relocation (%d) at (0x%" PRIx64 ") has wrong"
+ (_("%pB: relocation (%#x) at (0x%" PRIx64 ") has wrong"
" r_rsize (0x%x)\n"),
input_bfd, rel->r_type, rel->r_vaddr, rel->r_size);
return false;
@@ -1668,10 +1676,9 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
}
}

- if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
- || !((*xcoff64_calculate_relocation[rel->r_type])
- (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
- addend, &relocation, contents, info)))
+ if (!((*xcoff64_calculate_relocation[rel->r_type])
+ (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
+ addend, &relocation, contents, info)))
return false;

/* address */
diff --git a/bfd/libxcoff.h b/bfd/libxcoff.h
index c116d9b795f..e6b87975ff6 100644
--- a/bfd/libxcoff.h
+++ b/bfd/libxcoff.h
@@ -217,9 +217,6 @@ struct xcoff_backend_data_rec
#define bfd_xcoff_text_align_power(a) ((xcoff_data (a)->text_align_power))
#define bfd_xcoff_data_align_power(a) ((xcoff_data (a)->data_align_power))

-/* xcoff*_ppc_relocate_section macros */
-#define XCOFF_MAX_CALCULATE_RELOCATION (0x32)
-#define XCOFF_MAX_COMPLAIN_OVERFLOW (4)
/* N_ONES produces N one bits, without overflowing machine arithmetic. */
#ifdef N_ONES
#undef N_ONES
--
2.43.7

1 change: 1 addition & 0 deletions debian/patches/series
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,4 @@ CVE-2025-5245.patch
CVE-2025-7545.patch
CVE-2025-7546.patch
CVE-2025-8225.patch
CVE-2026-4647.patch
Loading