commit fba365b4d365f54ab7ef60272996dc2889461640 Author: Frank Ch. Eigler 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 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; jbuild_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; jbuild_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; }