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 <m...@klomp.org>
---
 libdwfl/ChangeLog  |  6 ++++++
 libdwfl/link_map.c | 16 ++++++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index aaea164c..7bf789e0 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2021-12-15  Mark Wielaard  <m...@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  <m...@klomp.org>
 
        * dwfl_segment_report_module.c (dwfl_segment_report_module): Don't
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index ad93501e..82df7b69 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -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 <m...@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))
-- 
2.30.2

Reply via email to