[binutils-gdb] asan: use after free in _bfd_elf_mips_get_relocated_section_contents

Alan Modra amodra@sourceware.org
Fri Dec 17 06:26:06 GMT 2021


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

commit 7ebf6ed02bde3a488bb588316e47b4df68796076
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Dec 17 15:01:20 2021 +1030

    asan: use after free in _bfd_elf_mips_get_relocated_section_contents
    
    Leaving entries on mips_hi16_list from a previous pass over relocs
    leads to confusing bugs.
    
            * elfxx-mips.c (_bfd_elf_mips_get_relocated_section_contents):
            Free mips_hi16_list entries on error exit.

Diff:
---
 bfd/elfxx-mips.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 4aaa3ea1fc3..34005c6aee0 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -13242,7 +13242,26 @@ _bfd_elf_mips_get_relocated_section_contents
 
   reloc_vector = (arelent **) bfd_malloc (reloc_size);
   if (reloc_vector == NULL)
-    return NULL;
+    {
+      struct mips_hi16 **hip, *hi;
+    error_return:
+      /* If we are going to return an error, remove entries on
+	 mips_hi16_list that point into this section's data.  Data
+	 will typically be freed on return from this function.  */
+      hip = &mips_hi16_list;
+      while ((hi = *hip) != NULL)
+	{
+	  if (hi->input_section == input_section)
+	    {
+	      *hip = hi->next;
+	      free (hi);
+	    }
+	  else
+	    hip = &hi->next;
+	}
+      data = NULL;
+      goto out;
+    }
 
   reloc_count = bfd_canonicalize_reloc (input_bfd,
 					input_section,
@@ -13432,12 +13451,9 @@ _bfd_elf_mips_get_relocated_section_contents
 	}
     }
 
+ out:
   free (reloc_vector);
   return data;
-
- error_return:
-  free (reloc_vector);
-  return NULL;
 }
 
 static bool


More information about the Binutils-cvs mailing list