]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Fix RHBZ#494858: fix bad address checks in core file support.
authorRoland McGrath <roland@redhat.com>
Tue, 14 Apr 2009 09:38:19 +0000 (02:38 -0700)
committerRoland McGrath <roland@redhat.com>
Tue, 14 Apr 2009 09:38:19 +0000 (02:38 -0700)
libdwfl/ChangeLog
libdwfl/core-file.c
libdwfl/dwfl_segment_report_module.c
libdwfl/link_map.c

index a2487ed0c8110131520887df4827aef93097e7b1..d2c823fa313ec9005ec86ffd2c4d7c829b9f35af 100644 (file)
@@ -1,3 +1,13 @@
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+       * dwfl_segment_report_module.c: Handle DT_STRTAB value being either
+       absolute (already adjusted in place) or needing load bias adjustment.
+
+       * core-file.c (dwfl_elf_phdr_memory_callback): Fix return value for
+       gelf_getphdr failure.  Fix file size limit checks.
+
+       * dwfl_segment_report_module.c: Fix underflow in DYNSTRSZ check.
+
 2009-04-08  Roland McGrath  <roland@redhat.com>
 
        * dwfl_module_getsym.c: Don't adjust for bias again after
index bc881eb90623686c19448f8347c1bc5334bdf7ba..77f208cc7c5a20ca0ab9479d6b4fc967d87c0079 100644 (file)
@@ -1,5 +1,5 @@
 /* Core file handling.
-   Copyright (C) 2008 Red Hat, Inc.
+   Copyright (C) 2008, 2009 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -278,7 +278,7 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
 
   do
     if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
-      return true;
+      return false;
   while (phdr.p_type != PT_LOAD
         || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
 
@@ -320,8 +320,14 @@ dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
   if (elf->map_address != NULL)
     (void) more (elf->maximum_size - start);
 
-  if (unlikely (end - start > elf->maximum_size))
-    end = start + elf->maximum_size;
+  /* Make sure we don't look past the end of the actual file,
+     even if the headers tell us to.  */
+  if (unlikely (end > elf->maximum_size))
+    end = elf->maximum_size;
+
+  /* If the file is too small, there is nothing at all to get.  */
+  if (unlikely (start >= end))
+    return false;
 
   if (elf->map_address != NULL)
     {
index a6639be57f05c9c596c55b76497db5f0e345a485..10787bdc39b1c7fa04f041ade18105384f92ba56 100644 (file)
@@ -519,13 +519,28 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
   size_t soname_size = 0;
   if (dynstrsz != 0 && dynstr_vaddr != 0)
     {
-      /* We know the bounds of the .dynstr section.  */
-      dynstr_vaddr += bias;
+      /* We know the bounds of the .dynstr section.
+
+        The DYNSTR_VADDR pointer comes from the .dynamic section
+        (DT_STRTAB, detected above).  Ordinarily the dynamic linker
+        will have adjusted this pointer in place so it's now an
+        absolute address.  But sometimes .dynamic is read-only (in
+        vDSOs and odd architectures), and sometimes the adjustment
+        just hasn't happened yet in the memory image we looked at.
+        So treat DYNSTR_VADDR as an absolute address if it falls
+        within the module bounds, or try applying the phdr bias
+        when that adjusts it to fall within the module bounds.  */
+
+      if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
+         && dynstr_vaddr + bias >= module_start
+         && dynstr_vaddr + bias < module_end)
+       dynstr_vaddr += bias;
+
       if (unlikely (dynstr_vaddr + dynstrsz > module_end))
        dynstrsz = 0;
 
       /* Try to get the DT_SONAME string.  */
-      if (soname_stroff != 0 && soname_stroff < dynstrsz - 1
+      if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
          && ! read_portion (&soname, &soname_size,
                             dynstr_vaddr + soname_stroff, 0))
        name = soname;
index 30fb445abac5c0245e6da39aa904177112ced06a..2d4d75f1a85837c14e2358502514b51eda03bc19 100644 (file)
@@ -585,7 +585,6 @@ consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
          (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
                              memory_callback_arg);
 
-
          if (*elfclass == ELFCLASSNONE)
            *elfclass = ehdr.e_ident[EI_CLASS];
          else if (*elfclass != ehdr.e_ident[EI_CLASS])