Blob Blame History Raw
commit fba365b4d365f54ab7ef60272996dc2889461640
Author: Frank Ch. Eigler <fche@redhat.com>
Date:   Thu Nov 15 16:27:58 2018 -0500

    PR23890: tolerate f29+ style ELF files
    
    Reported by kenj@pcp, with mjw et al.'s help, we found out why
    systemtap on fedora 29+ routinely fails to verify build-ids for
    userspace programs.  F29 adds a separate loadable segment with the
    relevante .note's, before the main text segment.  The runtime code
    that listens to mmaps-in-progress now accepts this configuration.
    As long as the .note section is loaded (time-wise and space-wise)
    before the .text one(s), we're good.

diff --git a/runtime/linux/uprobes-inode.c b/runtime/linux/uprobes-inode.c
index 6d450c90d87c..b9604e6385ce 100644
--- a/runtime/linux/uprobes-inode.c
+++ b/runtime/linux/uprobes-inode.c
@@ -563,9 +563,11 @@ stapiu_change_plus(struct stapiu_target* target, struct task_struct *task,
 			return rc;
 		}
 
-		/* Actually do the check. */
+		/* Actually do the check.  NB: on F29+, offset may not equal 0
+                   for LOADable "R E" segments, because the read-only .note.*
+                   stuff may have been loaded earlier, separately.  PR23890. */
 		if ((rc = _stp_usermodule_check(task, target->filename,
-						relocation))) {
+						relocation - offset))) {
 			/* Be sure to release the inode on failure. */
 			iput(target->inode);
 			target->inode = NULL;

commit 824e9ab80108c1882842fc2a4b4abd1aee990ecc (upstream/master)
Author: Frank Ch. Eigler <fche@redhat.com>
Date:   Thu Nov 15 20:22:34 2018 -0500

    PR23890 bonus: show nicer messages upon a buildid mismatch
    
    Instead of producing only a one-byte error, we now compute the entire
    builds into hex text strings, and report the whole shebang on an
    error.  (Also, ditch some 2.6.27 kernel-bug compatibiltiy fossil
    in the area.)

diff --git a/runtime/sym.c b/runtime/sym.c
index 60f0fa980964..111147ee555d 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -636,30 +636,46 @@ unsigned long _stp_linenumber_lookup(unsigned long addr, struct task_struct *tas
   return 0;
 }
 
+
+// Compare two build-id hex strings, each of length m->build_id_len bytes.
+// Since mismatches can mystify, produce a hex-textual version of both
+// expected and actual strings, and compare textually.  Failure messages
+// are more intelligible this way.
 static int _stp_build_id_check (struct _stp_module *m,
 				unsigned long notes_addr,
 				struct task_struct *tsk)
 {
-  int j;
+  enum { max_buildid_hexstring = 65 };
+  static const char hexnibble[16]="0123456789abcdef";
+  char hexstring_theory[max_buildid_hexstring], hexstring_practice[max_buildid_hexstring];
+  int buildid_len = min((max_buildid_hexstring-1)/2, m->build_id_len);
+
+  int i, j;
+  
+  memset(hexstring_theory, '\0', max_buildid_hexstring);
+  for (i=0, j=0; j<buildid_len; j++) {
+     unsigned char theory = m->build_id_bits[j];
+     hexstring_theory[i++] = hexnibble[theory >> 4];
+     hexstring_theory[i++] = hexnibble[theory & 15];
+  }
 
-  for (j = 0; j < m->build_id_len; j++) {
+  memset(hexstring_practice, '\0', max_buildid_hexstring);
+  for (i=0, j=0; j<buildid_len; j++) {
     /* Use set_fs / get_user to access conceivably invalid addresses.
      * If loc2c-runtime.h were more easily usable, a deref() loop
      * could do it too. */
     mm_segment_t oldfs = get_fs();
     int rc;
-    unsigned char theory, practice = 0;
+    unsigned char practice = 0;
 
 #ifdef STAPCONF_PROBE_KERNEL
     if (!tsk) {
-      theory = m->build_id_bits[j];
       set_fs(KERNEL_DS);
       rc = probe_kernel_read(&practice, (void*)(notes_addr + j), 1);
     }
     else
 #endif
     {
-      theory = m->build_id_bits[j];
       set_fs (tsk ? USER_DS : KERNEL_DS);
 
       /*
@@ -685,21 +701,19 @@ static int _stp_build_id_check (struct _stp_module *m,
     }
     set_fs(oldfs);
 
-    if (rc || (theory != practice)) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
-      _stp_error ("Build-id mismatch [man error::buildid]: \"%s\" byte %d (0x%02x vs 0x%02x) address %#lx rc %d\n",
-		  m->path, j, theory, practice, notes_addr, rc);
+    if (rc == 0) { // got actual data byte
+            hexstring_practice[i++] = hexnibble[practice >> 4];
+            hexstring_practice[i++] = hexnibble[practice & 15];
+    }
+  }
+
+  // have two strings, will travel
+  if (strcmp (hexstring_practice, hexstring_theory)) {
+          _stp_error ("Build-id mismatch [man error::buildid]: \"%s\" address %#lx, expected %s actual %s\n",
+                      m->path, notes_addr, hexstring_theory, hexstring_practice);
       return 1;
-#else
-      /* This branch is a surrogate for kernels affected by Fedora bug
-       * #465873. */
-      _stp_warn (KERN_WARNING
-		 "Build-id mismatch [man error::buildid]: \"%s\" byte %d (0x%02x vs 0x%02x) rc %d\n",
-		 m->path, j, theory, practice, rc);
-#endif
-      break;
-    } /* end mismatch */
-  } /* end per-byte check loop */
+  }
+  
   return 0;
 }