libdwfl: Make sure phent is sane and there is at least one phdr
authorMark Wielaard <mark@klomp.org>
Wed, 15 Dec 2021 23:29:22 +0000 (00:29 +0100)
committerMark Wielaard <mark@klomp.org>
Thu, 16 Dec 2021 18:50:38 +0000 (19:50 +0100)
dwfl_link_map_report can only handle program headers that are the
correct (32 or 64 bit) size. The buffer read in needs to contain room
for at least one Phdr.

https://sourceware.org/bugzilla/show_bug.cgi?id=28660

Signed-off-by: Mark Wielaard <mark@klomp.org>
libdwfl/ChangeLog
libdwfl/link_map.c

index aaea164..7bf789e 100644 (file)
@@ -1,3 +1,9 @@
+2021-12-15  Mark Wielaard  <mark@klomp.org>
+
+       * link_map.c (dwfl_link_map_report): Make sure phent is either sizeof
+       Elf32_Phdr or sizeof Elf64_Phdr. Check in.d_size can hold at least one
+       Phdr.
+
 2021-12-12  Mark Wielaard  <mark@klomp.org>
 
        * dwfl_segment_report_module.c (dwfl_segment_report_module): Don't
index ad93501..82df7b6 100644 (file)
@@ -1,5 +1,6 @@
 /* Report modules by examining dynamic linker data structures.
    Copyright (C) 2008-2016 Red Hat, Inc.
+   Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -784,7 +785,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
       GElf_Xword dyn_filesz = 0;
       GElf_Addr dyn_bias = (GElf_Addr) -1;
 
-      if (phdr != 0 && phnum != 0 && phent != 0)
+      if (phdr != 0 && phnum != 0
+         && ((elfclass == ELFCLASS32 && phent == sizeof (Elf32_Phdr))
+             || (elfclass == ELFCLASS64 && phent == sizeof (Elf64_Phdr))))
        {
          Dwfl_Module *phdr_mod;
          int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
@@ -904,7 +907,16 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
                  .d_buf = buf
                };
              if (in.d_size > out.d_size)
-               in.d_size = out.d_size;
+               {
+                 in.d_size = out.d_size;
+                 phnum = in.d_size / phent;
+                 if (phnum == 0)
+                   {
+                     free (buf);
+                     __libdwfl_seterrno (DWFL_E_BADELF);
+                     return false;
+                   }
+               }
              if (likely ((elfclass == ELFCLASS32
                           ? elf32_xlatetom : elf64_xlatetom)
                          (&out, &in, elfdata) != NULL))