PR 34327 More out of bounds accesses in reloc special functions

Message ID akXWTenS9zB13ypw@squeak.grove.modra.org
State New
Headers
Series PR 34327 More out of bounds accesses in reloc special functions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply

Commit Message

Alan Modra July 2, 2026, 3:09 a.m. UTC
  I don't claim to have caught all places where reloc special functions
don't sanity check input, but this should be most of them.  Hopefully
this does not expose odd reloc howto entries like the mmix one in the
previous patch.

	* coff-arm.c (aoutarm_fix_pcrel_26): Sanity check reloc offset.
	Remove some unnecessary casts.
	(coff_thumb_pcrel_common): Likewise.
	* coff-mips.c (mips_generic_reloc): Remove unnecessary casts.
	(mips_refhi_reloc): Likewise.
	(mips_gprel_reloc): Likewise.  Use bfd_reloc_offset_in_range.
	* cpu-ns32k.c (do_ns32k_reloc): Likewise.
	* elf32-m68hc1x.c (m68hc11_elf_special_reloc): Likewise.  Don't
	abort, return notsupported instead.
	* elf32-pj.c (pj_elf_reloc): Sanity check reloc offset.
	* elf32-pru.c (pru_elf32_do_s10_pcrel_relocate): Update reloc
	offset sanity check.
	(pru_elf32_do_ldi32_relocate): Likewise.
	* elf32-s390.c (s390_elf_ldisp_reloc): Use bfd_reloc_offset_in_range.
	Remove unnecessary casts.
	* elf32-score7.c (score_elf_got_lo16_reloc): Remove redundant old
	reloc offset sanity check.
	* elf32-sh.c (sh_elf_reloc): Use bfd_reloc_offset_in_range.
	* elf32-v850.c (v850_elf_reloc): Likewise.
  

Patch

diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c
index a90a5f4507f..5697acd941c 100644
--- a/bfd/coff-arm.c
+++ b/bfd/coff-arm.c
@@ -603,7 +603,7 @@  aoutarm_fix_pcrel_26 (bfd *abfd,
 {
   bfd_vma relocation;
   bfd_size_type addr = reloc_entry->address;
-  long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+  long target;
   bfd_reloc_status_type flag = bfd_reloc_ok;
 
   /* If this is an undefined symbol, return error.  */
@@ -614,9 +614,14 @@  aoutarm_fix_pcrel_26 (bfd *abfd,
   /* If the sections are different, and we are doing a partial relocation,
      just ignore it for now.  */
   if (symbol->section->name != input_section->name
-      && output_bfd != (bfd *)NULL)
+      && output_bfd != NULL)
     return bfd_reloc_continue;
 
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, addr))
+    return bfd_reloc_outofrange;
+
+  target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
   relocation = (target & 0x00ffffff) << 2;
   relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend.  */
   relocation += symbol->value;
@@ -662,7 +667,7 @@  coff_thumb_pcrel_common (bfd *abfd,
 {
   bfd_vma relocation = 0;
   bfd_size_type addr = reloc_entry->address;
-  long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+  long target;
   bfd_reloc_status_type flag = bfd_reloc_ok;
   bfd_vma dstmsk;
   bfd_vma offmsk;
@@ -702,9 +707,15 @@  coff_thumb_pcrel_common (bfd *abfd,
   /* If the sections are different, and we are doing a partial relocation,
      just ignore it for now.  */
   if (symbol->section->name != input_section->name
-      && output_bfd != (bfd *)NULL)
+      && output_bfd != NULL)
     return bfd_reloc_continue;
 
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, addr))
+    return bfd_reloc_outofrange;
+
+  target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+
   switch (btype)
     {
     case b9:
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index 35848d94ca1..da7a666cebc 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -403,7 +403,7 @@  mips_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 		    bfd *output_bfd,
 		    char **error_message ATTRIBUTE_UNUSED)
 {
-  if (output_bfd != (bfd *) NULL
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && reloc_entry->addend == 0)
     {
@@ -438,7 +438,7 @@  mips_refhi_reloc (bfd *abfd,
 
   /* If we're relocating, and this an external symbol, we don't want
      to change anything.  */
-  if (output_bfd != (bfd *) NULL
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && reloc_entry->addend == 0)
     {
@@ -448,7 +448,7 @@  mips_refhi_reloc (bfd *abfd,
 
   ret = bfd_reloc_ok;
   if (bfd_is_und_section (symbol->section)
-      && output_bfd == (bfd *) NULL)
+      && output_bfd == NULL)
     ret = bfd_reloc_undefined;
 
   if (bfd_is_com_section (symbol->section))
@@ -484,7 +484,7 @@  mips_refhi_reloc (bfd *abfd,
   n->next = sdata->mips_refhi_list;
   sdata->mips_refhi_list = n;
 
-  if (output_bfd != (bfd *) NULL)
+  if (output_bfd != NULL)
     reloc_entry->address += input_section->output_offset;
 
   return ret;
@@ -561,7 +561,7 @@  mips_reflo_reloc (bfd *abfd,
    the offset from the gp register.  */
 
 static bfd_reloc_status_type
-mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+mips_gprel_reloc (bfd *abfd,
 		  arelent *reloc_entry,
 		  asymbol *symbol,
 		  void * data,
@@ -579,7 +579,7 @@  mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
      addend, we don't want to change anything.  We will only have an
      addend if this is a newly created reloc, not read from an ECOFF
      file.  */
-  if (output_bfd != (bfd *) NULL
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && reloc_entry->addend == 0)
     {
@@ -587,7 +587,7 @@  mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
       return bfd_reloc_ok;
     }
 
-  if (output_bfd != (bfd *) NULL)
+  if (output_bfd != NULL)
     relocatable = true;
   else
     {
@@ -660,7 +660,8 @@  mips_gprel_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   relocation += symbol->section->output_section->vma;
   relocation += symbol->section->output_offset;
 
-  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, reloc_entry->address))
     return bfd_reloc_outofrange;
 
   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
diff --git a/bfd/cpu-ns32k.c b/bfd/cpu-ns32k.c
index 684a38add0b..4f92be03b64 100644
--- a/bfd/cpu-ns32k.c
+++ b/bfd/cpu-ns32k.c
@@ -163,7 +163,7 @@  do_ns32k_reloc (bfd *      abfd,
   bfd_byte *location;
 
   if (bfd_is_abs_section (symbol->section)
-      && output_bfd != (bfd *) NULL)
+      && output_bfd != NULL)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -174,11 +174,11 @@  do_ns32k_reloc (bfd *      abfd,
      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
   if (bfd_is_und_section (symbol->section)
       && (symbol->flags & BSF_WEAK) == 0
-      && output_bfd == (bfd *) NULL)
+      && output_bfd == NULL)
     flag = bfd_reloc_undefined;
 
-  /* Is the address of the relocation really within the section?  */
-  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, reloc_entry->address))
     return bfd_reloc_outofrange;
 
   /* Work out which section the relocation is targeted at and the
@@ -242,7 +242,7 @@  do_ns32k_reloc (bfd *      abfd,
 	relocation -= reloc_entry->address;
     }
 
-  if (output_bfd != (bfd *) NULL)
+  if (output_bfd != NULL)
     {
       if (! howto->partial_inplace)
 	{
diff --git a/bfd/elf32-m68hc1x.c b/bfd/elf32-m68hc1x.c
index 2b7c4500851..8b5bacafd31 100644
--- a/bfd/elf32-m68hc1x.c
+++ b/bfd/elf32-m68hc1x.c
@@ -814,7 +814,7 @@  m68hc11_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 }
 
 bfd_reloc_status_type
-m68hc11_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+m68hc11_elf_special_reloc (bfd *abfd,
 			   arelent *reloc_entry,
 			   asymbol *symbol,
 			   void *data ATTRIBUTE_UNUSED,
@@ -822,7 +822,7 @@  m68hc11_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 			   bfd *output_bfd,
 			   char **error_message ATTRIBUTE_UNUSED)
 {
-  if (output_bfd != (bfd *) NULL
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && (! reloc_entry->howto->partial_inplace
 	  || reloc_entry->addend == 0))
@@ -834,10 +834,11 @@  m68hc11_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   if (output_bfd != NULL)
     return bfd_reloc_continue;
 
-  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, reloc_entry->address))
     return bfd_reloc_outofrange;
 
-  abort();
+  return bfd_reloc_notsupported;
 }
 
 /* Look through the relocs for a section during the first phase.
diff --git a/bfd/elf32-pj.c b/bfd/elf32-pj.c
index 6ec17c219c5..a758bd27f0a 100644
--- a/bfd/elf32-pj.c
+++ b/bfd/elf32-pj.c
@@ -58,6 +58,10 @@  pj_elf_reloc (bfd *abfd,
       && bfd_is_und_section (symbol_in->section))
     return bfd_reloc_undefined;
 
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, reloc_entry->address))
+    return bfd_reloc_outofrange;
+
   if (bfd_is_com_section (symbol_in->section))
     sym_value = 0;
   else
diff --git a/bfd/elf32-pru.c b/bfd/elf32-pru.c
index 6e699004d04..640fc83b0b8 100644
--- a/bfd/elf32-pru.c
+++ b/bfd/elf32-pru.c
@@ -470,8 +470,7 @@  pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
   bfd_vma qboff;
   bfd_reloc_status_type flag = bfd_reloc_ok;
 
-  /* Sanity check the address.  */
-  if (address > bfd_get_section_limit (input_bfd, input_section))
+  if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, address))
     return bfd_reloc_outofrange;
 
   BFD_ASSERT (howto->pc_relative);
@@ -546,9 +545,7 @@  pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
 
   /* A hacked-up version of _bfd_final_link_relocate() follows.  */
 
-  /* Sanity check the address.  */
-  if (octets + bfd_get_reloc_size (howto)
-      > bfd_get_section_limit_octets (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
     return bfd_reloc_outofrange;
 
   /* This function assumes that we are dealing with a basic relocation
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index fb00971c7b6..dd9149a4824 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -384,7 +384,7 @@  s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   bfd_vma relocation;
   bfd_vma insn;
 
-  if (output_bfd != (bfd *) NULL
+  if (output_bfd != NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
       && (! howto->partial_inplace
 	  || reloc_entry->addend == 0))
@@ -396,7 +396,8 @@  s390_elf_ldisp_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   if (output_bfd != NULL)
     return bfd_reloc_continue;
 
-  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, reloc_entry->address))
     return bfd_reloc_outofrange;
 
   relocation = (symbol->value
diff --git a/bfd/elf32-score7.c b/bfd/elf32-score7.c
index 81c079ff631..cf01059013f 100644
--- a/bfd/elf32-score7.c
+++ b/bfd/elf32-score7.c
@@ -543,8 +543,6 @@  score_elf_got_lo16_reloc (bfd *abfd,
   addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
   offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1;
   val = reloc_entry->addend;
-  if (reloc_entry->address > input_section->size)
-    return bfd_reloc_outofrange;
   uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val;
   if (hi16_rel_addr)
     {
diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index 8446d13c973..2107e3f807a 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -256,8 +256,8 @@  sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in,
     return bfd_reloc_undefined;
 
   /* PR 17512: file: 9891ca98.  */
-  if (octets + bfd_get_reloc_size (reloc_entry->howto)
-      > bfd_get_section_limit_octets (abfd, input_section))
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, octets))
     return bfd_reloc_outofrange;
 
   if (bfd_is_com_section (symbol_in->section))
diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c
index 6bee3af2e61..8ffbc024156 100644
--- a/bfd/elf32-v850.c
+++ b/bfd/elf32-v850.c
@@ -813,7 +813,7 @@  v850_elf_perform_relocation (bfd *abfd,
 /* Insert the addend into the instruction.  */
 
 static bfd_reloc_status_type
-v850_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+v850_elf_reloc (bfd *abfd,
 		arelent *reloc,
 		asymbol *symbol,
 		void * data ATTRIBUTE_UNUSED,
@@ -845,8 +845,8 @@  v850_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 
   /* We handle final linking of some relocs ourselves.  */
 
-  /* Is the address of the relocation really within the section?  */
-  if (reloc->address > bfd_get_section_limit (abfd, isection))
+  if (!bfd_reloc_offset_in_range (reloc->howto, abfd,
+				  isection, reloc->address))
     return bfd_reloc_outofrange;
 
   /* Work out which section the relocation is targeted at and the