]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
asan: ppc64_elf_get_synthetic_symtab heap buffer overflow
authorAlan Modra <amodra@gmail.com>
Fri, 5 Aug 2022 10:10:23 +0000 (19:40 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 5 Aug 2022 11:18:29 +0000 (20:48 +0930)
Fuzzed input files with sizes of .dynamic not a multiple of dynamic
tag size can result in reading past the end of the buffer with the
current simple checks.  Fix that, and use the same check in other
files that process input object .dynamic section.  (There is no need
for buffer overflow checks in the linker's generated .dynamic
section.)

* elf32-ppc.c (ppc_elf_get_synthetic_symtab): Sanity check
.dynamic content buffer reads.
* elf64-ppc.c (ppc64_elf_get_synthetic_symtab): Likewise.
* elf64-ia64-vms.c (elf64_vms_link_add_object_symbols): Likewise.
* elf.c (_bfd_elf_print_private_bfd_data): Simplify .dynamic
buffer sanity checks.
* elflink.c (elf_link_add_object_symbols): Avoid possible UB
subtracting sizeof_dyn from pointer.

bfd/elf.c
bfd/elf32-ppc.c
bfd/elf64-ia64-vms.c
bfd/elf64-ppc.c
bfd/elflink.c

index 346eea39b1ff4bbff7d4ffbe6bb24868f725a076..1b9b7fad15af7f18d343eed758a33fc85e738f08 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1721,14 +1721,9 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
       extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
-      extdyn = dynbuf;
-      /* PR 17512: file: 6f427532.  */
-      if (s->size < extdynsize)
-       goto error_return;
-      extdynend = extdyn + s->size;
-      /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
-        Fix range check.  */
-      for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
+      for (extdyn = dynbuf, extdynend = dynbuf + s->size;
+          (size_t) (extdynend - extdyn) >= extdynsize;
+          extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
          const char *name = "";
index 3582711d9620054219c014a5c8e8d8b0104e138f..1f77e18133addee44bc5df8022a552501183f024 100644 (file)
@@ -1852,9 +1852,9 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms,
       extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
       swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
-      extdyn = dynbuf;
-      extdynend = extdyn + dynamic->size;
-      for (; extdyn < extdynend; extdyn += extdynsize)
+      for (extdyn = dynbuf, extdynend = dynbuf + dynamic->size;
+          (size_t) (extdynend - extdyn) >= extdynsize;
+          extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
          (*swap_dyn_in) (abfd, extdyn, &dyn);
index 4d8f98550a34d5b18f44b1b96d50dcdbe479b397..613dacd755b88f63ad9f88ea614e37fc83e78004 100644 (file)
@@ -4845,7 +4845,7 @@ elf64_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
 
       for (extdyn = dynbuf;
-          extdyn < dynbuf + s->size;
+          (size_t) (dynbuf + s->size - extdyn) >= bed->s->sizeof_dyn;
           extdyn += bed->s->sizeof_dyn)
        {
          Elf_Internal_Dyn dyn;
index cfcd263173c45c5b11e40b6c9220c0cd5cbfb57b..f1e482faed4e6e2228618ff832e639e505f42e9f 100644 (file)
@@ -2513,9 +2513,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
          extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
          swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
-         extdyn = dynbuf;
-         extdynend = extdyn + dynamic->size;
-         for (; extdyn < extdynend; extdyn += extdynsize)
+         for (extdyn = dynbuf, extdynend = dynbuf + dynamic->size;
+              (size_t) (extdynend - extdyn) >= extdynsize;
+              extdyn += extdynsize)
            {
              Elf_Internal_Dyn dyn;
              (*swap_dyn_in) (abfd, extdyn, &dyn);
index 2b1450fa4e146936ba4fd6d02691a863f26a88b6..89dcf26108c55a4a1b04af0fb5387bfdecac8dc1 100644 (file)
@@ -4406,7 +4406,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
          shlink = elf_elfsections (abfd)[elfsec]->sh_link;
 
          for (extdyn = dynbuf;
-              extdyn <= dynbuf + s->size - bed->s->sizeof_dyn;
+              (size_t) (dynbuf + s->size - extdyn) >= bed->s->sizeof_dyn;
               extdyn += bed->s->sizeof_dyn)
            {
              Elf_Internal_Dyn dyn;
@@ -8219,9 +8219,9 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
   extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
   swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
 
-  extdyn = dynbuf;
-  extdynend = extdyn + s->size;
-  for (; extdyn < extdynend; extdyn += extdynsize)
+  for (extdyn = dynbuf, extdynend = dynbuf + s->size;
+       (size_t) (extdynend - extdyn) >= extdynsize;
+       extdyn += extdynsize)
     {
       Elf_Internal_Dyn dyn;