summaryrefslogtreecommitdiff
path: root/libdwfl
diff options
context:
space:
mode:
authorMark Wielaard <mark@klomp.org>2021-12-16 00:29:22 +0100
committerMark Wielaard <mark@klomp.org>2021-12-16 19:50:38 +0100
commit3c9b69161b842708b4ef2f4e0f0b3ad1812798c2 (patch)
treef09dca9a1dd00f26dab14e6f5fdb0f161cb0fc96 /libdwfl
parent8303a9cf380a57d035557a157fe0e4d58e2b3090 (diff)
downloadelfutils-3c9b69161b842708b4ef2f4e0f0b3ad1812798c2.tar.gz
libdwfl: Make sure phent is sane and there is at least one phdr
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>
Diffstat (limited to 'libdwfl')
-rw-r--r--libdwfl/ChangeLog6
-rw-r--r--libdwfl/link_map.c16
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 <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))