From ff5b3e1458875830595e8c1d1fab6624264b3935 Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Thu, 25 Mar 2021 10:31:48 -0700 Subject: [PATCH] Save/restore file offset while reading notes in core file A recent bug (RH BZ 1931344) has exposed a bug in the core file build-ID support that I introduced a while ago. It is pretty easy to demonstate the problem following a simplified procedure outlined in that bug: [shell1] shell1$ /usr/libexec/qemu-kvm [shell2] shell2$ pkill -SEGV -x qemu-kvm [shell1] Segmentation fault (core dumped) Load this core file into GDB without specifying an executable (an unfortunate Fedora/RHEL-ism), and GDB will inform the user to install debuginfo for the "missing" executable: $ gdb -nx -q core.12345 ... Missing separate debuginfo for the main executable file Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/e2/e9c66d3117fb2bbb5b2be122f04f2664e5df54 Core was generated by `/usr/libexec/qemu-kvm'. Program terminated with signal SIGSEGV, Segmentation fault. ... The suggested build-ID is actaully for gmp not qemu-kvm. The problem lies in _bfd_elf_core_find_build_id, where we loop over program headers looking for note segments: /* Read in program headers and parse notes. */ for (i = 0; i < i_ehdr.e_phnum; ++i, ++i_phdr) { Elf_External_Phdr x_phdr; if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr)) goto fail; elf_swap_phdr_in (abfd, &x_phdr, i_phdr); if (i_phdr->p_type == PT_NOTE && i_phdr->p_filesz > 0) { elf_read_notes (abfd, offset + i_phdr->p_offset, i_phdr->p_filesz, i_phdr->p_align); if (abfd->build_id != NULL) return TRUE; } elf_read_notes uses bfd_seek to forward the stream to the location of the note segment. When control returns to _bfd_elf_core_fild_build_id, the stream is no longer in the location looking at program headers, and all subsequent reads will read from the wrong file offset. To fix this, this patch marks the stream location and ensures that it is restored after elf_read_notes is called. bfd/ChangeLog 2021-03-26 Keith Seitz * elfcore.h (_bfd_elf_core_find_build_id): Seek file offset of program headers after calling elf_read_notes. --- bfd/ChangeLog | 5 +++++ bfd/elfcore.h | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3245f8c5ad3..6f3fccc0a6a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,8 @@ +2021-03-26 Keith Seitz + + * elfcore.h (_bfd_elf_core_find_build_id): Seek file + offset of program headers after calling elf_read_notes. + 2021-03-23 Jan Beulich * dwarf2.c (read_indexed_string): Rename index to idx. diff --git a/bfd/elfcore.h b/bfd/elfcore.h index 3015e582ef0..4e6383415f7 100644 --- a/bfd/elfcore.h +++ b/bfd/elfcore.h @@ -410,6 +410,13 @@ NAME(_bfd_elf, core_find_build_id) { elf_read_notes (abfd, offset + i_phdr->p_offset, i_phdr->p_filesz, i_phdr->p_align); + + /* Make sure ABFD returns to processing the program headers. */ + if (bfd_seek (abfd, (file_ptr) (offset + i_ehdr.e_phoff + + (i + 1) * sizeof (x_phdr)), + SEEK_SET) != 0) + goto fail; + if (abfd->build_id != NULL) return TRUE; } -- 2.30.2