]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
buffer overflow in score_elf_create_dynamic_relocation
authorAlan Modra <amodra@gmail.com>
Fri, 17 Jan 2025 05:25:12 +0000 (15:55 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 17 Jan 2025 05:37:48 +0000 (16:07 +1030)
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.

bfd/elf32-score.c
bfd/elf32-score7.c

index c656e0d8b70aeeafc32524f70cd3f658ad215e91..9563098dc772f2304b5f25bc94063ec2ddd70e04 100644 (file)
@@ -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;
index f51716297a84302554495dd92f049877ba13fd8e..2ecabf6a47baf67bfb29741dd12a9edf60a7adf7 100644 (file)
@@ -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;