[binutils-gdb] buffer overflow in score_elf_create_dynamic_relocation

Alan Modra amodra@sourceware.org
Fri Jan 17 06:07:30 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b565ac119bdf8ed857cfa1352ddc732ccdac7b66

commit b565ac119bdf8ed857cfa1352ddc732ccdac7b66
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Jan 17 15:55:12 2025 +1030

    buffer overflow in score_elf_create_dynamic_relocation
    
    score_elf_create_dynamic_relocation sets up three output dynamic
    relocs from rel[0], rel[1] and rel[2].  When rel[0] is the last reloc
    in a section this of course results in a buffer overflow.  It's a
    weird thing to do given that only one relocation is output.
    
            * elf32-score.c (score_elf_create_dynamic_relocation): Do not
            set up three dynamic relocations when only one is output.
            * elf32-score7.c: Likewise.

Diff:
---
 bfd/elf32-score.c  | 30 ++++++++++--------------------
 bfd/elf32-score7.c | 30 ++++++++++--------------------
 2 files changed, 20 insertions(+), 40 deletions(-)

diff --git a/bfd/elf32-score.c b/bfd/elf32-score.c
index c656e0d8b70..9563098dc77 100644
--- a/bfd/elf32-score.c
+++ b/bfd/elf32-score.c
@@ -1287,7 +1287,7 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
 				     bfd_vma symbol,
 				     bfd_vma *addendp, asection *input_section)
 {
-  Elf_Internal_Rela outrel[3];
+  Elf_Internal_Rela outrel;
   asection *sreloc;
   bfd *dynobj;
   int r_type;
@@ -1301,18 +1301,14 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
   BFD_ASSERT (sreloc->contents != NULL);
   BFD_ASSERT (sreloc->reloc_count * SCORE_ELF_REL_SIZE (output_bfd) < sreloc->size);
 
-  outrel[0].r_offset =
-    _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
-  outrel[1].r_offset =
-    _bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset);
-  outrel[2].r_offset =
-    _bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset);
+  outrel.r_offset =
+    _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset);
 
-  if (outrel[0].r_offset == MINUS_ONE)
+  if (outrel.r_offset == MINUS_ONE)
     /* The relocation field has been deleted.  */
     return true;
 
-  if (outrel[0].r_offset == MINUS_TWO)
+  if (outrel.r_offset == MINUS_TWO)
     {
       /* The relocation field has been converted into a relative value of
 	 some sort.  Functions like _bfd_elf_write_section_eh_frame expect
@@ -1351,7 +1347,7 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
 
   /* The relocation is always an REL32 relocation because we don't
      know where the shared library will wind up at load-time.  */
-  outrel[0].r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32);
+  outrel.r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32);
 
   /* For strict adherence to the ABI specification, we should
      generate a R_SCORE_64 relocation record by itself before the
@@ -1365,24 +1361,18 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
      invocation if ABI_64_P, and here we should generate an
      additional relocation record with R_SCORE_64 by itself for a
      NULL symbol before this relocation record.  */
-  outrel[1].r_info = ELF32_R_INFO (0, R_SCORE_NONE);
-  outrel[2].r_info = ELF32_R_INFO (0, R_SCORE_NONE);
 
   /* Adjust the output offset of the relocation to reference the
      correct location in the output file.  */
-  outrel[0].r_offset += (input_section->output_section->vma
-			 + input_section->output_offset);
-  outrel[1].r_offset += (input_section->output_section->vma
-			 + input_section->output_offset);
-  outrel[2].r_offset += (input_section->output_section->vma
-			 + input_section->output_offset);
+  outrel.r_offset += (input_section->output_section->vma
+		      + input_section->output_offset);
 
   /* Put the relocation back out.  We have to use the special
      relocation outputter in the 64-bit case since the 64-bit
      relocation format is non-standard.  */
   bfd_elf32_swap_reloc_out
-      (output_bfd, &outrel[0],
-       (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
+    (output_bfd, &outrel,
+     sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel));
 
   /* We've now added another relocation.  */
   ++sreloc->reloc_count;
diff --git a/bfd/elf32-score7.c b/bfd/elf32-score7.c
index f51716297a8..2ecabf6a47b 100644
--- a/bfd/elf32-score7.c
+++ b/bfd/elf32-score7.c
@@ -1147,7 +1147,7 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
 				     bfd_vma symbol,
 				     bfd_vma *addendp, asection *input_section)
 {
-  Elf_Internal_Rela outrel[3];
+  Elf_Internal_Rela outrel;
   asection *sreloc;
   bfd *dynobj;
   int r_type;
@@ -1161,18 +1161,14 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
   BFD_ASSERT (sreloc->contents != NULL);
   BFD_ASSERT (sreloc->reloc_count * SCORE_ELF_REL_SIZE (output_bfd) < sreloc->size);
 
-  outrel[0].r_offset =
-    _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset);
-  outrel[1].r_offset =
-    _bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset);
-  outrel[2].r_offset =
-    _bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset);
+  outrel.r_offset =
+    _bfd_elf_section_offset (output_bfd, info, input_section, rel->r_offset);
 
-  if (outrel[0].r_offset == MINUS_ONE)
+  if (outrel.r_offset == MINUS_ONE)
     /* The relocation field has been deleted.  */
     return true;
 
-  if (outrel[0].r_offset == MINUS_TWO)
+  if (outrel.r_offset == MINUS_TWO)
     {
       /* The relocation field has been converted into a relative value of
 	 some sort.  Functions like _bfd_elf_write_section_eh_frame expect
@@ -1211,7 +1207,7 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
 
   /* The relocation is always an REL32 relocation because we don't
      know where the shared library will wind up at load-time.  */
-  outrel[0].r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32);
+  outrel.r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32);
 
   /* For strict adherence to the ABI specification, we should
      generate a R_SCORE_64 relocation record by itself before the
@@ -1225,24 +1221,18 @@ score_elf_create_dynamic_relocation (bfd *output_bfd,
      invocation if ABI_64_P, and here we should generate an
      additional relocation record with R_SCORE_64 by itself for a
      NULL symbol before this relocation record.  */
-  outrel[1].r_info = ELF32_R_INFO (0, R_SCORE_NONE);
-  outrel[2].r_info = ELF32_R_INFO (0, R_SCORE_NONE);
 
   /* Adjust the output offset of the relocation to reference the
      correct location in the output file.  */
-  outrel[0].r_offset += (input_section->output_section->vma
-			 + input_section->output_offset);
-  outrel[1].r_offset += (input_section->output_section->vma
-			 + input_section->output_offset);
-  outrel[2].r_offset += (input_section->output_section->vma
-			 + input_section->output_offset);
+  outrel.r_offset += (input_section->output_section->vma
+		      + input_section->output_offset);
 
   /* Put the relocation back out.  We have to use the special
      relocation outputter in the 64-bit case since the 64-bit
      relocation format is non-standard.  */
   bfd_elf32_swap_reloc_out
-      (output_bfd, &outrel[0],
-       (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel)));
+    (output_bfd, &outrel,
+     sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel));
 
   /* We've now added another relocation.  */
   ++sreloc->reloc_count;


More information about the Binutils-cvs mailing list