This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Verify file vs. core build-id, when both available


Hi Mark,

jankratochvil/buildidcheck

the approved patch
	[patch] Fix non-build-id core files on build-id system
	https://lists.fedorahosted.org/pipermail/elfutils-devel/2013-November/003448.html
	Message-ID: <20131112203642.GA23754@host2.jankratochvil.net>

is right in general but it causes a regression
	FAIL: run-unstrip-n.sh
due to:
+0xf75e9000+0x1a000 29a103420abe341e92072fb14274e250e4072148(a)0xf75e9164 - - libpthread.so.0
-0xf75e8fe0+0x191fc 718a99e8dbf70cd061097f70e5fe21237f86ab4a(a)0xf75e9144 /lib/libpthread.so.0 - libpthread.so.0
+0xf7603000+0x1b0000 0b9bf374699e141e5dfc14757ff42b8c2373b4de(a)0xf7603184 - - libc.so.6
-0xf75f3fe0+0x1bea7c 50ed3f33e3761eefeeceb120121643f843260b27(a)0xf75f4164 /lib/libc.so.6 - libc.so.6
+0xf77b3000+0x9000 c6c5b5e35ab9589d4762ac85b4bd56b1b2720e37(a)0xf77b3164 - - librt.so.1
-0xf77b3004+0x8224 3b3966acca796ba57b538a014bcc77ea0cc5033e(a)0xf77b3168 /lib/librt.so.1 - librt.so.1
+0xf77d7000+0x21000 6d2cb32650054f1c176d01d48713a4a5e5e84c1a(a)0xf77d7124 - - ld-linux.so.2
-0xf77d6ff0+0x208f8 03099056658748f4e58e2cd390fb63babfd1d23b(a)0xf77d7114 /lib/ld-linux.so.2 - ld-linux.so.2

The problem is that:
 * elfutils will find a completely different version of file with the same name
 * the file has build-id
 * as the file is different the computed memory address of the build-id is bogus
 * bogus address is sure not available from the core file
 * elfutils thinks just that the core file was dumped without first ELF page
therefore elfutils approves the file matching as valid.

One could for example restrict the mappings only for PAGE_SIZE-aligned
displacements but that would not work well with prelinked vs. unprelinked
files, see GDB comment:
              /* There is no way to verify the library file matches.  prelink
                 can during prelinking of an unprelinked file (or unprelinking
                 of a prelinked file) shift the DYNAMIC segment by arbitrary
                 offset without any page size alignment.  There is no way to
                 find out the ELF header and/or Program Headers for a limited
                 verification if it they match.  One could do a verification
                 of the DYNAMIC segment.  Still the found address is the best
                 one GDB could find.  */

But as elfutils scans the memory space and finds there files by their build-id
it can verify build-id of the found disk file vs. that in-memory file.

This will make all the tests of the initial patch PASSing again.


Thanks,
Jan

commit 18545b45f6e2ea807467f189d58e2bdce8fb4a3a
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Wed Nov 20 20:27:50 2013 +0100

    Verify file vs. core build-id, when both available
    
    libdwfl/
    2013-11-20  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	* dwfl_segment_report_module.c (dwfl_segment_report_module): New
    	variable close_elf.  Call __libdwfl_find_elf_build_id and compare the
    	content, if possible.
    
    Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>

diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
index 97f4a1a..55f6d38 100644
--- a/libdwfl/dwfl_segment_report_module.c
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -478,20 +478,40 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
 	if ((module_end > module->start && module_start < module->end)
 	    || dyn_vaddr == module->l_ld)
 	  {
+	    bool close_elf = false;
 	    if (! module->disk_file_has_build_id && build_id_len > 0)
 	      {
 		/* Module found in segments with build-id is more reliable
 		   than a module found via DT_DEBUG on disk without any
 		   build-id.   */
 		if (module->elf != NULL)
+		  close_elf = true;
+	      }
+	    if (module->elf != NULL
+		&& module->disk_file_has_build_id && build_id_len > 0)
+	      {
+		const void *elf_build_id;
+		GElf_Addr elf_build_id_elfaddr;
+		int elf_build_id_len;
+
+		if (__libdwfl_find_elf_build_id (NULL, module->elf,
+						 &elf_build_id,
+						 &elf_build_id_elfaddr,
+						 &elf_build_id_len) > 0)
 		  {
-		    elf_end (module->elf);
-		    close (module->fd);
-		    module->elf = NULL;
-		    module->fd = -1;
+		    if (build_id_len != (size_t) elf_build_id_len
+			|| memcmp (build_id, elf_build_id, build_id_len) != 0)
+		      close_elf = true;
 		  }
 	      }
-	    else if (module->elf != NULL)
+	    if (close_elf)
+	      {
+		elf_end (module->elf);
+		close (module->fd);
+		module->elf = NULL;
+		module->fd = -1;
+	      }
+	    if (module->elf != NULL)
 	      {
 		/* Ignore this found module if it would conflict in address
 		   space with any already existing module of DWFL.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]