This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2] libdwfl: elf_from_remote_memory only trust shdrs of last file-only segment.


If the last PT_LOAD segment that contains the whole shdrs also extends
the segment in memory beyond the end of file the program might be reusing
the memory space that we expect the shdrs to be in. Don't trust the shdrs
are valid in that case.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdwfl/ChangeLog         |    7 +++++++
 libdwfl/elf-from-memory.c |   22 +++++++++++++++-------
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index e371393..8fcdc3b 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,5 +1,12 @@
 2014-03-03  Mark Wielaard  <mjw@redhat.com>
 
+	* elf-from-memory.c (elf_from_remote_memory): Keep track of
+	segments_end_mem. Pass memsz to first handle_segment pass. Only
+	extend contents_size and use shdrs if only file bits are in
+	segment.
+
+2014-03-03  Mark Wielaard  <mjw@redhat.com>
+
 	* elf-from-memory.c (elf_from_remote_memory): Take pagesize as
 	argument. Free buffer when detecting bad elf. Check PT_LOAD
 	alignment requirements on first handle_segment pass. Calculate
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
index c18da27..39e520d 100644
--- a/libdwfl/elf-from-memory.c
+++ b/libdwfl/elf-from-memory.c
@@ -196,12 +196,14 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
   /* Scan for PT_LOAD segments to find the total size of the file image.  */
   size_t contents_size = 0;
   GElf_Off segments_end = 0;
+  GElf_Off segments_end_mem = 0;
   GElf_Addr loadbase = ehdr_vma;
   bool found_base = false;
   switch (ehdr.e32.e_ident[EI_CLASS])
     {
       inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
-				  GElf_Xword filesz, GElf_Xword palign)
+				  GElf_Xword filesz, GElf_Xword memsz,
+				  GElf_Xword palign)
 	{
 	  /* Sanity check the alignment requirements.  */
 	  if ((palign & (pagesize - 1)) != 0
@@ -221,6 +223,7 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 	    }
 
 	  segments_end = offset + filesz;
+	  segments_end_mem = offset + memsz;
 	  return false;
 	}
 
@@ -231,7 +234,8 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if (phdrs.p32[i].p_type == PT_LOAD)
 	  if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
-			      phdrs.p32[i].p_filesz, phdrs.p32[i].p_align))
+			      phdrs.p32[i].p_filesz, phdrs.p32[i].p_memsz,
+			      phdrs.p32[i].p_align))
 	    goto bad_elf;
       break;
 
@@ -242,7 +246,8 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
       for (uint_fast16_t i = 0; i < phnum; ++i)
 	if (phdrs.p64[i].p_type == PT_LOAD)
 	  if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
-			      phdrs.p64[i].p_filesz, phdrs.p64[i].p_align))
+			      phdrs.p64[i].p_filesz, phdrs.p64[i].p_memsz,
+			      phdrs.p64[i].p_align))
 	    goto bad_elf;
       break;
 
@@ -253,9 +258,11 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 
   /* Trim the last segment so we don't bother with zeros in the last page
      that are off the end of the file.  However, if the extra bit in that
-     page includes the section headers, keep them.  */
+     page includes the section headers and the memory isn't extended (which
+     might indicate it will have been reused otherwise), keep them.  */
   if ((GElf_Off) contents_size > segments_end
-      && (GElf_Off) contents_size >= shdrs_end)
+      && (GElf_Off) contents_size >= shdrs_end
+      && segments_end == segments_end_mem)
     {
       contents_size = segments_end;
       if ((GElf_Off) contents_size < shdrs_end)
@@ -321,8 +328,9 @@ elf_from_remote_memory (GElf_Addr ehdr_vma,
 	    goto read_error;
 
       /* If the segments visible in memory didn't include the section
-	 headers, then clear them from the file header.  */
-      if (contents_size < shdrs_end)
+	 headers or the memory might be used for something else, then
+	 clear them from the file header.  */
+      if (contents_size < shdrs_end || segments_end != segments_end_mem)
 	{
 	  ehdr.e64.e_shoff = 0;
 	  ehdr.e64.e_shnum = 0;
-- 
1.7.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]