public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Protect mips_hi16_list from fuzzed debug info
@ 2023-02-06 12:33 Alan Modra
  2023-02-07 14:11 ` Maciej W. Rozycki
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2023-02-06 12:33 UTC (permalink / raw)
  To: binutils; +Cc: Chenghua Xu, Maciej W. Rozycki

This is another fix for the testcase mentioned in
https://sourceware.org/pipermail/binutils/2023-February/125915.html
either of which will stop the addr2line segfault.  This one also fixes
a potential problem when linking corrupted debug info.

OK to apply?

	* elfxx-mips.c (struct mips_elf_obj_tdata): Add freeze_mips_hi16_list.
	(_bfd_mips_elf_hi16_reloc): Heed freeze_mips_hi16_list.
	(_bfd_mips_elf_lo16_reloc): Likewise.
	(find_nearest_line): Rename from _bfd_mips_elf_find_nearest_line
	and make static.
	(_bfd_mips_elf_find_nearest_line): New wrapper function setting
	freeze_mips_hi16_list around find_nearest_line.

diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index e9fb61ff9e7..20934c477e2 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -599,6 +599,7 @@ struct mips_elf_obj_tdata
   asection *elf_text_section;
 
   struct mips_hi16 *mips_hi16_list;
+  bool freeze_mips_hi16_list;
 };
 
 /* Get MIPS ELF private object data from BFD's tdata.  */
@@ -2534,11 +2535,14 @@ _bfd_mips_elf_hi16_reloc (bfd *abfd, arelent *reloc_entry,
   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
 
+  tdata = mips_elf_tdata (abfd);
+  if (tdata->freeze_mips_hi16_list)
+    return bfd_reloc_outofrange;
+
   n = bfd_malloc (sizeof *n);
   if (n == NULL)
     return bfd_reloc_outofrange;
 
-  tdata = mips_elf_tdata (abfd);
   n->next = tdata->mips_hi16_list;
   n->data = data;
   n->input_section = input_section;
@@ -2596,38 +2600,41 @@ _bfd_mips_elf_lo16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 			       location);
 
   tdata = mips_elf_tdata (abfd);
-  while (tdata->mips_hi16_list != NULL)
-    {
-      bfd_reloc_status_type ret;
-      struct mips_hi16 *hi;
-
-      hi = tdata->mips_hi16_list;
-
-      /* R_MIPS*_GOT16 relocations are something of a special case.  We
-	 want to install the addend in the same way as for a R_MIPS*_HI16
-	 relocation (with a rightshift of 16).  However, since GOT16
-	 relocations can also be used with global symbols, their howto
-	 has a rightshift of 0.  */
-      if (hi->rel.howto->type == R_MIPS_GOT16)
-	hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, false);
-      else if (hi->rel.howto->type == R_MIPS16_GOT16)
-	hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS16_HI16, false);
-      else if (hi->rel.howto->type == R_MICROMIPS_GOT16)
-	hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16, false);
-
-      /* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that any
-	 carry or borrow will induce a change of +1 or -1 in the high part.  */
-      hi->rel.addend += (vallo + 0x8000) & 0xffff;
-
-      ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
-					 hi->input_section, output_bfd,
-					 error_message);
-      if (ret != bfd_reloc_ok)
-	return ret;
-
-      tdata->mips_hi16_list = hi->next;
-      free (hi);
-    }
+  if (!tdata->freeze_mips_hi16_list)
+    while (tdata->mips_hi16_list != NULL)
+      {
+	bfd_reloc_status_type ret;
+	struct mips_hi16 *hi;
+
+	hi = tdata->mips_hi16_list;
+
+	/* R_MIPS*_GOT16 relocations are something of a special case.
+	   We want to install the addend in the same way as for a
+	   R_MIPS*_HI16 relocation (with a rightshift of 16).
+	   However, since GOT16 relocations can also be used with
+	   global symbols, their howto has a rightshift of 0.  */
+	if (hi->rel.howto->type == R_MIPS_GOT16)
+	  hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS_HI16, false);
+	else if (hi->rel.howto->type == R_MIPS16_GOT16)
+	  hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MIPS16_HI16, false);
+	else if (hi->rel.howto->type == R_MICROMIPS_GOT16)
+	  hi->rel.howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, R_MICROMIPS_HI16,
+						   false);
+
+	/* VALLO is a signed 16-bit number.  Bias it by 0x8000 so that
+	   any carry or borrow will induce a change of +1 or -1 in the
+	   high part.  */
+	hi->rel.addend += (vallo + 0x8000) & 0xffff;
+
+	ret = _bfd_mips_elf_generic_reloc (abfd, &hi->rel, symbol, hi->data,
+					   hi->input_section, output_bfd,
+					   error_message);
+	if (ret != bfd_reloc_ok)
+	  return ret;
+
+	tdata->mips_hi16_list = hi->next;
+	free (hi);
+      }
 
   return _bfd_mips_elf_generic_reloc (abfd, reloc_entry, symbol, data,
 				      input_section, output_bfd,
@@ -13118,13 +13125,11 @@ struct mips_elf_find_line
   struct ecoff_find_line i;
 };
 
-bool
-_bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
-				 asection *section, bfd_vma offset,
-				 const char **filename_ptr,
-				 const char **functionname_ptr,
-				 unsigned int *line_ptr,
-				 unsigned int *discriminator_ptr)
+static bool
+find_nearest_line (bfd *abfd, asymbol **symbols,
+		   asection *section, bfd_vma offset,
+		   const char **filename_ptr, const char **functionname_ptr,
+		   unsigned int *line_ptr, unsigned int *discriminator_ptr)
 {
   asection *msec;
 
@@ -13228,6 +13233,25 @@ _bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
 				     line_ptr, discriminator_ptr);
 }
 
+bool
+_bfd_mips_elf_find_nearest_line (bfd *abfd, asymbol **symbols,
+				 asection *section, bfd_vma offset,
+				 const char **filename_ptr,
+				 const char **functionname_ptr,
+				 unsigned int *line_ptr,
+				 unsigned int *discriminator_ptr)
+{
+  /* Debug info should not contain hi16 or lo16 relocs.  If it does
+     then someone is playing fuzzing games.  Altering the hi16 list
+     during linking when printing an error message is bad.  */
+  mips_elf_tdata (abfd)->freeze_mips_hi16_list = true;
+  bool ret = find_nearest_line (abfd, symbols, section, offset,
+				filename_ptr, functionname_ptr,
+				line_ptr, discriminator_ptr);
+  mips_elf_tdata (abfd)->freeze_mips_hi16_list = false;
+  return ret;
+}
+
 bool
 _bfd_mips_elf_find_inliner_info (bfd *abfd,
 				 const char **filename_ptr,
@@ -13321,16 +13345,19 @@ _bfd_elf_mips_get_relocated_section_contents
 	 mips_hi16_list that point into this section's data.  Data
 	 will typically be freed on return from this function.  */
       tdata = mips_elf_tdata (abfd);
-      hip = &tdata->mips_hi16_list;
-      while ((hi = *hip) != NULL)
+      if (!tdata->freeze_mips_hi16_list)
 	{
-	  if (hi->input_section == input_section)
+	  hip = &tdata->mips_hi16_list;
+	  while ((hi = *hip) != NULL)
 	    {
-	      *hip = hi->next;
-	      free (hi);
+	      if (hi->input_section == input_section)
+		{
+		  *hip = hi->next;
+		  free (hi);
+		}
+	      else
+		hip = &hi->next;
 	    }
-	  else
-	    hip = &hi->next;
 	}
       if (orig_data == NULL)
 	free (data);

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 12+ messages in thread
* mips hi16/lo16 reloc handling
@ 2023-12-19  9:35 Alan Modra
  2023-12-19  9:35 ` coff-mips refhi list Alan Modra
  0 siblings, 1 reply; 12+ messages in thread
From: Alan Modra @ 2023-12-19  9:35 UTC (permalink / raw)
  To: binutils; +Cc: Maciej W . Rozycki, Chenghua Xu, Alan Modra

In May this year I posted a patch to move the list of hi16 relocs from
per-file data to per-section data, where it makes more sense and is
not vunerable to fuzzed object file attacks.
https://sourceware.org/pipermail/binutils/2023-May/127534.html and
https://sourceware.org/pipermail/binutils/2023-May/127535.html
These incorporated the results of an earlier discussion in February.

A lot was going on in May with mips, so I'm not at all surprised that
no one reviewed the patch.  Or perhaps a review only went so far as
finding a segfault in gas..  That is fixed in this version.  We do
need to keep struct mips_hi16 "data" field to cope with gas frags.  A
lo16 reloc might apply to a different frag than the corresponding hi16
reloc.  Also, some other infrastructure changes meant that the posted
patches no longer apply cleanly.

The patches have been tested by running the binutils testsuite, and
building and regression testing a current gcc cross from x86_64-linux
to mips-linux (no sim installed).

Alan Modra (2):
  Move mips_hi16_list to mips_elf_section_data
  coff-mips refhi list

 bfd/coff-alpha.c |   6 +-
 bfd/coff-mips.c  | 121 +++++++++++-----------------
 bfd/ecoff.c      |  34 ++++++--
 bfd/elfxx-mips.c | 206 ++++++++++++++++++++++++-----------------------
 bfd/libecoff.h   |  30 +++----
 5 files changed, 201 insertions(+), 196 deletions(-)


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-12-19  9:36 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-06 12:33 Protect mips_hi16_list from fuzzed debug info Alan Modra
2023-02-07 14:11 ` Maciej W. Rozycki
2023-02-08  0:32   ` Alan Modra
2023-02-08 23:28     ` Maciej W. Rozycki
2023-02-09  0:29       ` Alan Modra
2023-02-09  1:26         ` Maciej W. Rozycki
2023-02-09 10:14           ` Alan Modra
2023-02-10 18:13             ` Maciej W. Rozycki
2023-05-20 11:41             ` Alan Modra
2023-05-20 11:44               ` coff-mips refhi list Alan Modra
2023-05-23 21:19               ` Protect mips_hi16_list from fuzzed debug info Maciej W. Rozycki
2023-12-19  9:35 mips hi16/lo16 reloc handling Alan Modra
2023-12-19  9:35 ` coff-mips refhi list Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).