diff mbox series

libdwfl: Make sure phent is sane and there is at least one phdr

Message ID 20211215234057.669569-1-mark@klomp.org
State Committed
Headers show
Series libdwfl: Make sure phent is sane and there is at least one phdr | expand

Commit Message

Mark Wielaard Dec. 15, 2021, 11:40 p.m. UTC
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  |  6 ++++++
 libdwfl/link_map.c | 16 ++++++++++++++--
 2 files changed, 20 insertions(+), 2 deletions(-)
diff mbox series

Patch

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  <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
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 <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))