diff --git a/SOURCES/rhbz1558350.patch b/SOURCES/rhbz1558350.patch new file mode 100644 index 0000000..d9b7b55 --- /dev/null +++ b/SOURCES/rhbz1558350.patch @@ -0,0 +1,21 @@ +commit 4b308597838f0fbfdcc3d11845c3065ba61eb57b +Author: Serhei Makarov +Date: Tue Apr 10 16:13:36 2018 -0400 + + RHBZ1558350: fix typo in linux/nfsd.stp + + * linux/nfsd.stp (probe nfsd.proc2.create): fix typo. + +diff --git a/tapset/linux/nfsd.stp b/tapset/linux/nfsd.stp +index 5a70e84..74124df 100644 +--- a/tapset/linux/nfsd.stp ++++ b/tapset/linux/nfsd.stp +@@ -901,7 +901,7 @@ probe nfsd.proc2.create = kernel.function("nfsd_proc_create") !, + + if (@defined($rqstp->rq_argp)) { + fh = & @nfsd2_createargs($rqstp->rq_argp)->fh +- filelen = @nfsd2_createargs($rqstp->rq_argp->len) ++ filelen = @nfsd2_createargs($rqstp->rq_argp)->len + filename = kernel_string_n(@nfsd2_createargs($rqstp->rq_argp)->name, + @nfsd2_createargs($rqstp->rq_argp)->len) + } diff --git a/SOURCES/rhbz1563052.patch b/SOURCES/rhbz1563052.patch new file mode 100644 index 0000000..2d752dc --- /dev/null +++ b/SOURCES/rhbz1563052.patch @@ -0,0 +1,60 @@ +commit 3b2cf9012d600bf61aaeff855e9dc95200859b1d +Author: Serhei Makarov +Date: Tue Apr 10 14:40:19 2018 -0400 + + RHBZ1563052: fix off-by-one error in loc2c-runtime.h + + The new version of kderef_string (added along with the new eBPF + runtime) copies an additional character compared to the old version. + + * runtime/linux/loc2c-runtime.h (_stp_deref_string_nofault): reduce len by 1 to leave room for NUL terminator. + * testsuite/systemtap.base/set_kernel.stp: testcase for this bug. + +diff --git a/runtime/linux/loc2c-runtime.h b/runtime/linux/loc2c-runtime.h +index 39dece0..fd736bd 100644 +--- a/runtime/linux/loc2c-runtime.h ++++ b/runtime/linux/loc2c-runtime.h +@@ -722,7 +722,7 @@ static inline char *kderef_buffer_(char *dst, void *addr, size_t len) + * + * dst: read the string into this address + * addr: address to read from +- * len: maximum number of bytes to read ++ * len: maximum number of bytes to store in dst, including the trailing NUL + * seg: memory segment to use, either kernel (KERNEL_DS) or user + * (USER_DS) + * +@@ -745,7 +745,8 @@ static inline long _stp_deref_string_nofault(char *dst, const char *addr, + err = 1; + else + { +- for (i = 0; i < len; ++i) ++ /* Reduce len by 1 to leave room for '\0' terminator. */ ++ for (i = 0; i + 1 < len; ++i) + { + u8 v; + err = __stp_get_user(v, (u8 *)addr + i); +diff --git a/testsuite/systemtap.base/set_kernel.stp b/testsuite/systemtap.base/set_kernel.stp +index 729b477..dc93582 100644 +--- a/testsuite/systemtap.base/set_kernel.stp ++++ b/testsuite/systemtap.base/set_kernel.stp +@@ -62,6 +62,20 @@ probe end(1) + assert_not_reached(test) + } catch {} + ++ /* Be sure to also test in the other direction: */ ++ test = "kernel_string_n" ++ addr = get_buffer() ++ if (assert_string(test, "", kernel_string_n(addr, 0))) { ++ set_kernel_string_n(addr, 7, "potatoe") ++ if (assert_string(test, "potatoe", kernel_string_n(addr, 7))) { ++ assert_string(test, "potato", kernel_string_n(addr, 6)) ++ } ++ } ++ try { ++ println(kernel_string_n(-1, 10)) ++ assert_not_reached(test) ++ } catch {} ++ + test = "set_kernel_long" + addr = get_buffer() + long_val = %( CONFIG_64BIT == "y" %? 0x123456789ABCDEF0 %: 0x12345678 %) diff --git a/SOURCES/rhbz1566422.patch b/SOURCES/rhbz1566422.patch new file mode 100644 index 0000000..494e4c9 --- /dev/null +++ b/SOURCES/rhbz1566422.patch @@ -0,0 +1,46 @@ +commit db9c9d6e30c6cfd7b85475b5c79ee2cc51201934 +Author: Serhei Makarov +Date: Tue Apr 17 11:35:00 2018 -0400 + + RHBZ1566422 - fix spurious Build-id mismatch when probing reinserted kernel module + + Code for newer kernels did not clear the address of the notes-section + when a probed module was unloaded. This caused spurious Build-id mismatch + when the module was reinserted as new addresses are not computed for + dynamically loaded modules (see also: PR23068) and the Build-id check + was trying to read the notes section at the no-longer-valid old address. + + * runtime/sym.c (_stp_module_notifier): clear addresses on + MODULE_STATE_GOING in newer kernels (>=3.10) too. + * runtime/transport/symbols.c (_stp_kmodule_update_address): fix logic + error and clear notes section addr when reloc=NULL (aka. 'all'). + +diff --git a/runtime/sym.c b/runtime/sym.c +index c11a35a..b6e0fd6 100644 +--- a/runtime/sym.c ++++ b/runtime/sym.c +@@ -1045,7 +1045,7 @@ static void _stp_kmodule_update_address(const char* module, + if (strcmp (_stp_modules[mi]->name, module)) + continue; + +- if (reloc && !strcmp (note_sectname, reloc)) { ++ if (!reloc || !strcmp (note_sectname, reloc)) { + dbug_sym(1, "module %s special section %s address %#lx\n", + _stp_modules[mi]->name, + note_sectname, +diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c +index 64c2aeb..076c562 100644 +--- a/runtime/transport/symbols.c ++++ b/runtime/transport/symbols.c +@@ -167,6 +167,11 @@ static int _stp_module_notifier (struct notifier_block * nb, + /* Verify build-id. */ + _stp_kmodule_check (mod->name); + } ++ else if (val == MODULE_STATE_GOING) { ++ /* Unregister all sections. */ ++ dbug_sym(2, "unregister sections\n"); ++ _stp_kmodule_update_address(mod->name, NULL, 0); ++ } + else if (val != MODULE_STATE_GOING) { + return NOTIFY_DONE; + } diff --git a/SOURCES/rhbz1567356.patch b/SOURCES/rhbz1567356.patch new file mode 100644 index 0000000..cf8fd2c --- /dev/null +++ b/SOURCES/rhbz1567356.patch @@ -0,0 +1,272 @@ +commit 553b6df07c9b7ab30ed468a6a4374cbdf73d1c0d +Author: Mark Wielaard +Date: Tue Apr 17 14:36:13 2018 +0200 + + linux runtime: Add support for new kernel unwind fallback. + + In newer kernels dump_trace got replaced by a new unwind infrastructure. + Add a new autoconf-unwind-stack-trace.c to detect whether we can use it. + Extend the runtime/stack.c _stp_stack_print_fallback with a new pt_regs* + argument. Update all callers and add dbug_unwind output to show which + fallback unwinder we are selecting (or if we are just giving up). + Rename the struct unwind_state in unwind.c and unwind.h to uw_state + because the old name now conflicts with the one used in the kernel. + +diff --git a/buildrun.cxx b/buildrun.cxx +index 403fa71..59b9e88 100644 +--- a/buildrun.cxx ++++ b/buildrun.cxx +@@ -365,6 +365,8 @@ compile_pass (systemtap_session& s) + "STAPCONF_KERNEL_STACKTRACE", NULL); + output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c", + "STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL); ++ output_autoconf(s, o, "autoconf-unwind-stack-trace.c", ++ "STAPCONF_KERNEL_UNWIND_STACK", NULL); + output_autoconf(s, o, "autoconf-asm-syscall.c", + "STAPCONF_ASM_SYSCALL_H", NULL); + output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL); +diff --git a/runtime/linux/autoconf-unwind-stack-trace.c b/runtime/linux/autoconf-unwind-stack-trace.c +new file mode 100644 +index 0000000..2ec399e +--- /dev/null ++++ b/runtime/linux/autoconf-unwind-stack-trace.c +@@ -0,0 +1,16 @@ ++#include ++#include ++ ++void unwind_stack_trace (void) ++{ ++ struct unwind_state state; ++ unwind_start (&state, current, 0, 0); ++ while (! unwind_done (&state)) ++ { ++ unsigned long addr = unwind_get_return_address (&state); ++ if (addr == 0) ++ break; ++ unwind_next_frame (&state); ++ } ++} ++ +diff --git a/runtime/stack.c b/runtime/stack.c +index c9d2c0c..43f98ef 100644 +--- a/runtime/stack.c ++++ b/runtime/stack.c +@@ -43,7 +43,11 @@ + #include + #endif + +-static void _stp_stack_print_fallback(unsigned long, int, int, int); ++#if defined(STAPCONF_KERNEL_UNWIND_STACK) ++#include ++#endif ++ ++static void _stp_stack_print_fallback(unsigned long, struct pt_regs*, int, int, int); + + #ifdef STP_USE_DWARF_UNWINDER + #ifdef STAPCONF_LINUX_UACCESS_H +@@ -128,7 +132,7 @@ static const struct stacktrace_ops print_stack_ops = { + }; + + /* Used for kernel backtrace printing when other mechanisms fail. */ +-static void _stp_stack_print_fallback(unsigned long stack, ++static void _stp_stack_print_fallback(unsigned long stack, struct pt_regs *regs, + int sym_flags, int levels, int skip) + { + struct print_stack_data print_data; +@@ -136,20 +140,55 @@ static void _stp_stack_print_fallback(unsigned long stack, + print_data.levels = levels; + print_data.skip = skip; + #if defined(STAPCONF_KERNEL_STACKTRACE) ++ dbug_unwind(1, "fallback kernel stacktrace\n"); + dump_trace(current, NULL, (long *)stack, 0, &print_stack_ops, + &print_data); + #else + /* STAPCONF_KERNEL_STACKTRACE_NO_BP */ ++ dbug_unwind(1, "fallback kernel stacktrace (no bp)\n"); + dump_trace(current, NULL, (long *)stack, &print_stack_ops, + &print_data); + #endif + } + #else +-static void _stp_stack_print_fallback(unsigned long s, int v, int l, int k) { ++#if defined(STAPCONF_KERNEL_UNWIND_STACK) ++static void _stp_stack_print_fallback(unsigned long sp, struct pt_regs *regs, ++ int sym_flags, ++ int levels, int skip) { ++ struct unwind_state state; ++ unwind_start (&state, current, regs, (unsigned long *) sp); ++ dbug_unwind(1, "fallback kernel stacktrace (unwind)\n"); ++ while (levels > 0 && ! unwind_done (&state)) ++ { ++ if (skip == 0) ++ { ++ unsigned long addr = unwind_get_return_address (&state); ++ /* When we have frame pointers, the unwind addresses can be ++ (mostly) trusted, otherwise it is all guesswork. */ ++#ifdef CONFIG_FRAME_POINTER ++ _stp_print_addr(addr, sym_flags, NULL); ++#else ++ _stp_print_addr(addr, sym_flags | _STP_SYM_INEXACT, NULL); ++#endif ++ if (addr == 0) ++ break; ++ levels--; ++ } ++ else ++ { ++ dbug_unwind(1, "skipping frame\n"); ++ skip--; ++ } ++ unwind_next_frame(&state); ++ } ++} ++#else /* no new unwind */ ++static void _stp_stack_print_fallback(unsigned long s, struct pt_regs *r, int v, int l, int k) { + /* Don't guess, just give up. */ ++ dbug_unwind(1, "no fallback kernel stacktrace (giving up)\n"); + _stp_print_addr(0, v | _STP_SYM_INEXACT, NULL); + } +- ++#endif /* new unwind */ + #endif /* defined(STAPCONF_KERNEL_STACKTRACE) || defined(STAPCONF_KERNEL_STACKTRACE_NO_BP) */ + + +@@ -382,6 +421,7 @@ static void _stp_stack_kernel_print(struct context *c, int sym_flags) + if (l == 0) { + remaining = MAXBACKTRACE - n; + _stp_stack_print_fallback(UNW_SP(&c->uwcontext_kernel.info), ++ &c->uwcontext_kernel.info.regs, + sym_flags, remaining, 0); + break; + } else { +@@ -408,7 +448,7 @@ static void _stp_stack_kernel_print(struct context *c, int sym_flags) + sp = 0; + skip = 5; /* yes, that many framework frames. */ + #endif +- _stp_stack_print_fallback(sp, sym_flags, ++ _stp_stack_print_fallback(sp, NULL, sym_flags, + MAXBACKTRACE, skip); + #else + if (sym_flags & _STP_SYM_SYMBOL) +diff --git a/runtime/unwind.c b/runtime/unwind.c +index ec7cd58..3a2d991 100644 +--- a/runtime/unwind.c ++++ b/runtime/unwind.c +@@ -235,7 +235,7 @@ static int parse_fde_cie(const u32 *fde, const u32 *cie, + + #define REG_STATE state->reg[state->stackDepth] + +-static int advance_loc(unsigned long delta, struct unwind_state *state) ++static int advance_loc(unsigned long delta, struct uw_state *state) + { + state->loc += delta * state->codeAlign; + dbug_unwind(1, "state->loc=%lx\n", state->loc); +@@ -244,7 +244,7 @@ static int advance_loc(unsigned long delta, struct unwind_state *state) + + /* Set Same or Nowhere rule for register. */ + static void set_no_state_rule(uleb128_t reg, enum item_location where, +- struct unwind_state *state) ++ struct uw_state *state) + { + dbug_unwind(1, "reg=%lx, where=%d\n", reg, where); + if (reg < ARRAY_SIZE(REG_STATE.regs)) { +@@ -254,7 +254,7 @@ static void set_no_state_rule(uleb128_t reg, enum item_location where, + + /* Memory or Value rule */ + static void set_offset_rule(uleb128_t reg, enum item_location where, +- sleb128_t svalue, struct unwind_state *state) ++ sleb128_t svalue, struct uw_state *state) + { + dbug_unwind(1, "reg=%lx, where=%d, svalue=%lx\n", reg, where, svalue); + if (reg < ARRAY_SIZE(REG_STATE.regs)) { +@@ -265,7 +265,7 @@ static void set_offset_rule(uleb128_t reg, enum item_location where, + + /* Register rule. */ + static void set_register_rule(uleb128_t reg, uleb128_t value, +- struct unwind_state *state) ++ struct uw_state *state) + { + dbug_unwind(1, "reg=%lx, value=%lx\n", reg, value); + if (reg < ARRAY_SIZE(REG_STATE.regs)) { +@@ -277,7 +277,7 @@ static void set_register_rule(uleb128_t reg, uleb128_t value, + /* Expr or ValExpr rule. */ + static void set_expr_rule(uleb128_t reg, enum item_location where, + const u8 **expr, const u8 *end, +- struct unwind_state *state) ++ struct uw_state *state) + { + const u8 *const start = *expr; + uleb128_t len = get_uleb128(expr, end); +@@ -296,7 +296,7 @@ static void set_expr_rule(uleb128_t reg, enum item_location where, + #define MAX_CFI 512 + + static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, +- signed ptrType, int user, struct unwind_state *state, int compat_task) ++ signed ptrType, int user, struct uw_state *state, int compat_task) + { + union { + const u8 *p8; +@@ -1169,7 +1169,7 @@ static int unwind_frame(struct unwind_context *context, + unsigned i; + signed ptrType = -1, call_frame = 1; + uleb128_t retAddrReg = 0; +- struct unwind_state *state = &context->state; ++ struct uw_state *state = &context->state; + unsigned long addr; + + if (unlikely(table_len == 0)) { +diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h +index 9d66732..b3ff786 100644 +--- a/runtime/unwind/unwind.h ++++ b/runtime/unwind/unwind.h +@@ -492,7 +492,7 @@ struct unwind_reg_state { + unsigned cfa_is_expr:1; + }; + +-struct unwind_state { ++struct uw_state { + uleb128_t loc; + uleb128_t codeAlign; + sleb128_t dataAlign; +@@ -503,7 +503,7 @@ struct unwind_state { + + struct unwind_context { + struct unwind_frame_info info; +- struct unwind_state state; ++ struct uw_state state; + }; + + static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 }; + +commit 17ee540dd61113fe4f557f191db3480db875cca1 +Author: Mark Wielaard +Date: Wed Apr 18 15:00:24 2018 +0200 + + Make kernel DWARF unwinder work with ksalr. + + The .debug_frame loaded from disk is already relocated against the + expected load offset of the kernel, but the actual static (load) + address might be different (with kaslr). So adjust the startLoc + for that difference when reading any address from the unwind table. + +diff --git a/runtime/unwind.c b/runtime/unwind.c +index 3a2d991..4c360d2 100644 +--- a/runtime/unwind.c ++++ b/runtime/unwind.c +@@ -724,10 +724,15 @@ adjustStartLoc (unsigned long startLoc, + dbug_unwind(2, "adjustStartLoc=%lx, ptrType=%s, m=%s, s=%s eh=%d\n", + startLoc, _stp_eh_enc_name(ptrType), m->path, s->name, is_ehframe); + if (startLoc == 0 +- || strcmp (m->name, "kernel") == 0 + || (strcmp (s->name, ".absolute") == 0 && !is_ehframe)) + return startLoc; + ++ /* The .debug_frame loaded from disk is already relocated against the ++ expected load offset of the kernel, but the actual static (load) ++ address might be different (with kaslr). */ ++ if (strcmp (m->name, "kernel") == 0) ++ return startLoc - s->sec_load_offset + s->static_addr; ++ + /* eh_frame data has been loaded in the kernel, so readjust offset. */ + if (is_ehframe) { + dbug_unwind(2, "eh_frame=%lx, eh_frame_addr=%lx\n", (unsigned long) m->eh_frame, m->eh_frame_addr); diff --git a/SPECS/systemtap.spec b/SPECS/systemtap.spec index e350aa2..041f42c 100644 --- a/SPECS/systemtap.spec +++ b/SPECS/systemtap.spec @@ -79,13 +79,17 @@ Name: systemtap Version: 3.2 -Release: 4%{?dist} +Release: 8%{?dist} # for version, see also configure.ac Patch10: rhbz1504009.patch Patch11: rhbz1506230.patch Patch12: rhbz1490862.patch Patch13: rhbz1527809.patch +Patch14: rhbz1558350.patch +Patch15: rhbz1567356.patch +Patch16: rhbz1566422.patch +Patch17: rhbz1563052.patch # Packaging abstract: # @@ -492,6 +496,10 @@ cd .. %patch11 -p1 %patch12 -p1 %patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 %build @@ -1172,6 +1180,18 @@ done # PRERELEASE %changelog +* Tue Apr 24 2018 Frank Ch. Eigler - 3.2-8 +- rhbz1563052 (stp_deref string truncation off-by-one error) + +* Tue Apr 24 2018 Frank Ch. Eigler - 3.2-7 +- rhbz1566422 (module build-id checking broken on unload) + +* Tue Apr 24 2018 Frank Ch. Eigler - 3.2-6 +- rhbz1567356 (backtraces broken w/ kaslr) + +* Tue Apr 24 2018 Frank Ch. Eigler - 3.2-5 +- rhbz1558350 (nfsd.proc.create typo fix) + * Mon Jan 29 2018 Frank Ch. Eigler - 3.2-4 - rhbz1527809 (staprun detach with SIGQUIT)