asan: heap-buffer-overflow in bpf_elf_generic_reloc
authorAlan Modra <amodra@gmail.com>
Fri, 17 Dec 2021 03:02:36 +0000 (13:32 +1030)
committerAlan Modra <amodra@gmail.com>
Fri, 17 Dec 2021 05:31:34 +0000 (16:01 +1030)
The bpf reloc howtos are a bit weird, using bitpos to specify an
offset from r_offset that is outside the size of the reloc as given by
howto.size.  That means bfd_get_reloc_size gives the wrong answer for
range checking, and thus bfd_reloc_offset_in_range can't be used.

* elf64-bpf.c (bpf_elf_generic_reloc): Handle bitpos offset reloc
range checking.

bfd/elf64-bpf.c

index beabad79aff1ba3b9bc9588be03ace441758b492..4e5f9d1e2f7ab29ab111530ad0adc88936cd90c4 100644 (file)
@@ -608,15 +608,16 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   bfd_byte *where;
 
   /* Sanity check that the address is in range.  */
+  bfd_size_type end = bfd_get_section_limit_octets (abfd, input_section);
+  bfd_size_type reloc_size;
   if (reloc_entry->howto->type == R_BPF_INSN_64)
-    {
-      bfd_size_type end = bfd_get_section_limit_octets (abfd, input_section);
-      if (reloc_entry->address > end
-         || end - reloc_entry->address < 16)
-       return bfd_reloc_outofrange;
-    }
-  else if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, input_section,
-                                      reloc_entry->address))
+    reloc_size = 16;
+  else
+    reloc_size = (reloc_entry->howto->bitsize
+                 + reloc_entry->howto->bitpos) / 8;
+
+  if (reloc_entry->address > end
+      || end - reloc_entry->address < reloc_size)
     return bfd_reloc_outofrange;
 
   /*  Get the symbol value.  */