We already checked this in all other cases except for the special case of relocs in statically_linked executables. Found with afl.
Signed-off-by: Mark Wielaard mjw@redhat.com --- src/ChangeLog | 6 +++++ src/readelf.c | 77 +++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 60 insertions(+), 23 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog index a6d18b5..072146a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2014-11-28 Mark Wielaard mjw@redhat.com + + * readelf.c (handle_relocs_rel): Print INVALID SECTION if destshdr + is NULL also for statically_linked relocations. + (handle_relocs_rela): Likewise. + 2014-11-26 Mark Wielaard mjw@redhat.com
* readelf.c (print_debug_aranges_section): Cast Dwarf_Word length diff --git a/src/readelf.c b/src/readelf.c index cd15e4c..6060851 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1857,17 +1857,32 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) }
if (is_statically_linked > 0 && shdr->sh_link == 0) - printf ("\ - %#0*" PRIx64 " %-20s %*s %s\n", - class == ELFCLASS32 ? 10 : 18, rel->r_offset, - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) - /* Avoid the leading R_ which isn't carrying any - information. */ - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), - buf, sizeof (buf)) + 2 - : gettext ("<INVALID RELOC>"), - class == ELFCLASS32 ? 10 : 18, "", - elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + { + if (unlikely (destshdr == NULL)) + printf (" %#0*" PRIx64 " %-20s %*s <%s %ld>\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + class == ELFCLASS32 ? 10 : 18, "", + gettext ("INVALID SECTION"), + (long int) (sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx)); + else + printf (" %#0*" PRIx64 " %-20s %*s %s\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + class == ELFCLASS32 ? 10 : 18, "", + elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + } else printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", class == ELFCLASS32 ? 10 : 18, rel->r_offset, @@ -2045,18 +2060,34 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) }
if (is_statically_linked > 0 && shdr->sh_link == 0) - printf ("\ - %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n", - class == ELFCLASS32 ? 10 : 18, rel->r_offset, - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) - /* Avoid the leading R_ which isn't carrying any - information. */ - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), - buf, sizeof (buf)) + 2 - : gettext ("<INVALID RELOC>"), - class == ELFCLASS32 ? 10 : 18, "", - rel->r_addend, - elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + { + if (unlikely (destshdr == NULL)) + printf (" %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " <%s %ld>\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + class == ELFCLASS32 ? 10 : 18, "", + rel->r_addend, + gettext ("INVALID SECTION"), + (long int) (sym->st_shndx == SHN_XINDEX + ? xndx : sym->st_shndx)); + else + printf (" %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext ("<INVALID RELOC>"), + class == ELFCLASS32 ? 10 : 18, "", + rel->r_addend, + elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + } else printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", class == ELFCLASS32 ? 10 : 18, rel->r_offset,
On Fri, Nov 28, 2014 at 10:24:46PM +0100, Mark Wielaard wrote:
We already checked this in all other cases except for the special case of relocs in statically_linked executables. Found with afl.
Sorry, this patch is bogus. It works around the actual cause. The destshdr should not be NULL to begin with. We actually check that before processing the relocations. But when we see a STT_SECTION symbol relocation we reuse destshdr to lookup that section. The correct fix is to not trash destshdr in that case. Which the attached patch does.
Cheers,
Mark
On Sat, 2014-11-29 at 15:03 +0100, Mark Wielaard wrote:
On Fri, Nov 28, 2014 at 10:24:46PM +0100, Mark Wielaard wrote:
We already checked this in all other cases except for the special case of relocs in statically_linked executables. Found with afl.
Sorry, this patch is bogus. It works around the actual cause. The destshdr should not be NULL to begin with. We actually check that before processing the relocations. But when we see a STT_SECTION symbol relocation we reuse destshdr to lookup that section. The correct fix is to not trash destshdr in that case. Which the attached patch does. [...] +2014-11-28 Mark Wielaard mjw@redhat.com
- readelf.c (handle_relocs_rel): Don't reuse destshdr to store
- section header of a relocation against a STT_SECTION symbol. Use
- a new local variable secshdr.
- (handle_relocs_rela): Likewise.
I pushed this fixed version of the fix to master now.
elfutils-devel@lists.fedorahosted.org