[PATCH 1/2] LoongArch: Avoid heap-buffer-overflow in loongarch_elf_relocate_section

Xi Ruoyao xry111@xry111.site
Tue Sep 13 15:44:13 GMT 2022


If a and b are different sections, we cannot access something in b with
"a->contents + (offset from a)" because "a->contents" and "b->contents"
are heap buffers allocated separately, not slices of a large buffer.

The issue was found during an attempt to add static-pie support to the
toolchain with ASAN.
---
 bfd/elfnn-loongarch.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index ed42b8b6770..4b408b1db72 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -3128,6 +3128,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	      unresolved_reloc = false;
 	      BFD_ASSERT (rel->r_addend == 0);
 
+	      asection *my_got = got;
 	      bfd_vma got_off = 0;
 	      if (h != NULL)
 		{
@@ -3145,17 +3146,14 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 			{
 			  idx = (h->plt.offset - PLT_HEADER_SIZE)
 			    / PLT_ENTRY_SIZE;
-			  got_off = sec_addr (htab->elf.sgotplt)
-			    + GOTPLT_HEADER_SIZE
-			    + (idx * GOT_ENTRY_SIZE)
-			    - sec_addr (htab->elf.sgot);
+			  my_got = htab->elf.sgotplt;
+			  got_off = GOTPLT_HEADER_SIZE + idx * GOT_ENTRY_SIZE;
 			}
 		      else
 			{
 			  idx = h->plt.offset / PLT_ENTRY_SIZE;
-			  got_off = sec_addr (htab->elf.sgotplt)
-			    + (idx * GOT_ENTRY_SIZE)
-			    - sec_addr (htab->elf.sgot);
+			  my_got = htab->elf.sgotplt;
+			  got_off = idx * GOT_ENTRY_SIZE;
 			}
 		    }
 
@@ -3172,7 +3170,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 			  && SYMBOL_REFERENCES_LOCAL (info, h))
 			{
 			  Elf_Internal_Rela rela;
-			  rela.r_offset = sec_addr (got) + got_off;
+			  rela.r_offset = sec_addr (my_got) + got_off;
 			  rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
 			  rela.r_addend = relocation;
 			  loongarch_elf_append_rela (output_bfd,
@@ -3202,9 +3200,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		    }
 		}
 
-	      bfd_put_NN (output_bfd, relocation, got->contents + got_off);
+	      bfd_put_NN (output_bfd, relocation, my_got->contents + got_off);
 
-	      relocation = got_off + sec_addr (got);
+	      relocation = got_off + sec_addr (my_got);
 	    }
 
 	  if (r_type == R_LARCH_GOT_PC_HI20)
-- 
2.37.0



More information about the Binutils mailing list