diff options
author | Roland McGrath <roland@redhat.com> | 2010-05-06 00:52:51 -0700 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2010-05-06 00:52:51 -0700 |
commit | ed431ddb74331f24add8c6d932ebed129c4385d8 (patch) | |
tree | fb400789e4956074d5f3fa29f20c83f4538995bd | |
parent | b4bb301f76828bcbd84e467b736fedf44fe50317 (diff) | |
download | elfutils-ed431ddb74331f24add8c6d932ebed129c4385d8.tar.gz |
libdwfl: Refuse to fall back to an ELF file opened by name when that mismatches the module build ID.
-rw-r--r-- | libdwfl/ChangeLog | 14 | ||||
-rw-r--r-- | libdwfl/dwfl_build_id_find_elf.c | 8 | ||||
-rw-r--r-- | libdwfl/dwfl_error.c | 3 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getdwarf.c | 45 | ||||
-rw-r--r-- | libdwfl/libdwflP.h | 4 |
5 files changed, 70 insertions, 4 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 32ff63b2..b1ba7a5d 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -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 diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c index fcc6f1e5..e27c8e12 100644 --- a/libdwfl/dwfl_build_id_find_elf.c +++ b/libdwfl/dwfl_build_id_find_elf.c @@ -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) diff --git a/libdwfl/dwfl_error.c b/libdwfl/dwfl_error.c index df2765af..9144a378 100644 --- a/libdwfl/dwfl_error.c +++ b/libdwfl/dwfl_error.c @@ -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 diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index b084673e..6065257d 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -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. */ diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 58edacb9..e4c7e7c8 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -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) |