]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdwfl: Refuse to fall back to an ELF file opened by name when that mismatches the...
authorRoland McGrath <roland@redhat.com>
Thu, 6 May 2010 07:52:51 +0000 (00:52 -0700)
committerRoland McGrath <roland@redhat.com>
Thu, 6 May 2010 07:52:51 +0000 (00:52 -0700)
libdwfl/ChangeLog
libdwfl/dwfl_build_id_find_elf.c
libdwfl/dwfl_error.c
libdwfl/dwfl_module_getdwarf.c
libdwfl/libdwflP.h

index 32ff63b29f2942ed805e550214f459f7eb2831b1..b1ba7a5df5754469c03bc3cce18fdd68af571d4f 100644 (file)
@@ -1,3 +1,17 @@
+2010-05-06  Roland McGrath  <roland@redhat.com>
+
+       * libdwflP.h (DWFL_ERRORS): Add WRONG_ID_ELF.
+       * dwfl_build_id_find_elf.c: Set MOD->main.valid when there is a build
+       ID but we didn't find a file.
+       * dwfl_module_getdwarf.c (__libdwfl_getelf): When that's set, check
+       and refuse any fallback file-by-name if it lacks the matching ID.
+
+       * dwfl_error.c (dwfl_errno): Add INTDEF.
+       * libdwflP.h: Add INTDECL.
+
+       * dwfl_module_getdwarf.c (open_elf): Do elf_end and clear FILE->elf in
+       failure cases.
+
 2010-05-04  Roland McGrath  <roland@redhat.com>
 
        * dwfl_segment_report_module.c: Use "[pie]" rather than "[dso]" for an
index fcc6f1e5a1d722a0282864267c32b6f4cad90d81..e27c8e120828fa5a7e6b8bdb6196a0365bb8231d 100644 (file)
@@ -1,5 +1,5 @@
 /* Find an ELF file for a module from its build ID.
-   Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
+   Copyright (C) 2007-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -160,6 +160,12 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
       free (*file_name);
       *file_name = NULL;
     }
+  else if (errno == 0 && mod->build_id_len > 0)
+    /* Setting this with no file yet loaded is a marker that
+       the build ID is authoritative even if we also know a
+       putative *FILE_NAME.  */
+    mod->main.valid = true;
+
   return fd;
 }
 INTDEF (dwfl_build_id_find_elf)
index df2765afb84d2410b07db4ddd94cf05186260ec1..9144a378cc4a5ff9b64eae3a488e65e0e8c2b7be 100644 (file)
@@ -1,5 +1,5 @@
 /* Error handling in libdwfl.
-   Copyright (C) 2005, 2006, 2009 Red Hat, Inc.
+   Copyright (C) 2005-2010 Red Hat, Inc.
    This file is part of Red Hat elfutils.
 
    Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -72,6 +72,7 @@ dwfl_errno (void)
   global_error = DWFL_E_NOERROR;
   return result;
 }
+INTDEF (dwfl_errno)
 
 
 static const struct msgtable
index b084673ebaffb6353523071ad1350c243cd09328..6065257dfcf721cca5ff70c61c336082b8e5f37c 100644 (file)
@@ -75,6 +75,8 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
     }
   else if (unlikely (elf_kind (file->elf) != ELF_K_ELF))
     {
+      elf_end (file->elf);
+      file->elf = NULL;
       close (file->fd);
       file->fd = -1;
       return DWFL_E_BADELF;
@@ -84,6 +86,8 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
   if (ehdr == NULL)
     {
     elf_error:
+      elf_end (file->elf);
+      file->elf = NULL;
       close (file->fd);
       file->fd = -1;
       return DWFL_E (LIBELF, elf_errno ());
@@ -137,9 +141,12 @@ __libdwfl_getelf (Dwfl_Module *mod)
   mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod),
                                                    &mod->main.name,
                                                    &mod->main.elf);
+  const bool fallback = mod->main.elf == NULL && mod->main.fd < 0;
   mod->elferr = open_elf (mod, &mod->main);
+  if (mod->elferr != DWFL_E_NOERROR)
+    return;
 
-  if (mod->elferr == DWFL_E_NOERROR && !mod->main.valid)
+  if (!mod->main.valid)
     {
       /* Clear any explicitly reported build ID, just in case it was wrong.
         We'll fetch it from the file when asked.  */
@@ -147,6 +154,42 @@ __libdwfl_getelf (Dwfl_Module *mod)
       mod->build_id_bits = NULL;
       mod->build_id_len = 0;
     }
+  else if (fallback)
+    {
+      /* We have an authoritative build ID for this module, so
+        don't use a file by name that doesn't match that ID.  */
+
+      assert (mod->build_id_len > 0);
+
+      switch (__builtin_expect (__libdwfl_find_build_id (mod, false,
+                                                        mod->main.elf), 2))
+       {
+       case 2:
+         /* Build ID matches as it should. */
+         return;
+
+       case -1:                        /* ELF error.  */
+         mod->elferr = INTUSE(dwfl_errno) ();
+         break;
+
+       case 0:                 /* File has no build ID note.  */
+       case 1:                 /* FIle has a build ID that does not match.  */
+         mod->elferr = DWFL_E_WRONG_ID_ELF;
+         break;
+
+       default:
+         abort ();
+       }
+
+      /* We get here when it was the right ELF file.  Clear it out.  */
+      elf_end (mod->main.elf);
+      mod->main.elf = NULL;
+      if (mod->main.fd >= 0)
+       {
+         close (mod->main.fd);
+         mod->main.fd = -1;
+       }
+    }
 }
 
 /* Search an ELF file for a ".gnu_debuglink" section.  */
index 58edacb9fab9dc05745ab09d6471096ee860dab5..e4c7e7c828a809e17b2352cf5689202448bbf32b 100644 (file)
@@ -93,7 +93,8 @@
   DWFL_ERROR (TRUNCATED, N_("image truncated"))                                      \
   DWFL_ERROR (ALREADY_ELF, N_("ELF file opened"))                            \
   DWFL_ERROR (BADELF, N_("not a valid ELF file"))                            \
-  DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description"))
+  DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description"))        \
+  DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID"))
 
 #define DWFL_ERROR(name, text) DWFL_E_##name,
 typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
@@ -404,6 +405,7 @@ extern int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 /* Avoid PLT entries.  */
 INTDECL (dwfl_begin)
 INTDECL (dwfl_errmsg)
+INTDECL (dwfl_errno)
 INTDECL (dwfl_addrmodule)
 INTDECL (dwfl_addrsegment)
 INTDECL (dwfl_addrdwarf)