Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'probes-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull kprobes updates from Masami Hiramatsu:

- Skip negative return code check for snprintf in eprobe

- Add recursive call test cases for kprobe unit test

- Add 'char' type to probe events to show it as the character instead
of value

- Update kselftest kprobe-event testcase to ignore '__pfx_' symbols

- Fix kselftest to check filter on eprobe event correctly

- Add filter on eprobe to the README file in tracefs

- Fix optprobes to check whether there is 'under unoptimizing' optprobe
when optimizing another kprobe correctly

- Fix optprobe to check whether there is 'under unoptimizing' optprobe
when fetching the original instruction correctly

- Fix optprobe to free 'forcibly unoptimized' optprobe correctly

* tag 'probes-v6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracing/eprobe: no need to check for negative ret value for snprintf
test_kprobes: Add recursed kprobe test case
tracing/probe: add a char type to show the character value of traced arguments
selftests/ftrace: Fix probepoint testcase to ignore __pfx_* symbols
selftests/ftrace: Fix eprobe syntax test case to check filter support
tracing/eprobe: Fix to add filter on eprobe description in README file
x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe range
x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
kprobes: Fix to handle forcibly unoptimized kprobes on freeing_list

+117 -33
+3 -1
Documentation/trace/kprobetrace.rst
··· 58 58 NAME=FETCHARG : Set NAME as the argument name of FETCHARG. 59 59 FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types 60 60 (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types 61 - (x8/x16/x32/x64), "string", "ustring", "symbol", "symstr" 61 + (x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr" 62 62 and bitfield are supported. 63 63 64 64 (\*1) only for the probe on function entry (offs == 0). ··· 81 81 Note that the array can be applied to memory type fetchargs, you can not 82 82 apply it to registers/stack-entries etc. (for example, '$stack1:x8[8]' is 83 83 wrong, but '+8($stack):x8[8]' is OK.) 84 + 85 + Char type can be used to show the character value of traced arguments. 84 86 85 87 String type is a special type, which fetches a "null-terminated" string from 86 88 kernel space. This means it will fail and store NULL if the string container
+3 -3
arch/x86/kernel/kprobes/opt.c
··· 46 46 /* This function only handles jump-optimized kprobe */ 47 47 if (kp && kprobe_optimized(kp)) { 48 48 op = container_of(kp, struct optimized_kprobe, kp); 49 - /* If op->list is not empty, op is under optimizing */ 50 - if (list_empty(&op->list)) 49 + /* If op is optimized or under unoptimizing */ 50 + if (list_empty(&op->list) || optprobe_queued_unopt(op)) 51 51 goto found; 52 52 } 53 53 } ··· 353 353 354 354 for (i = 1; i < op->optinsn.size; i++) { 355 355 p = get_kprobe(op->kp.addr + i); 356 - if (p && !kprobe_disabled(p)) 356 + if (p && !kprobe_disarmed(p)) 357 357 return -EEXIST; 358 358 } 359 359
+2
include/linux/kprobes.h
··· 378 378 DEFINE_INSN_CACHE_OPS(optinsn); 379 379 380 380 extern void wait_for_kprobe_optimizer(void); 381 + bool optprobe_queued_unopt(struct optimized_kprobe *op); 382 + bool kprobe_disarmed(struct kprobe *p); 381 383 #else /* !CONFIG_OPTPROBES */ 382 384 static inline void wait_for_kprobe_optimizer(void) { } 383 385 #endif /* CONFIG_OPTPROBES */
+12 -15
kernel/kprobes.c
··· 458 458 } 459 459 460 460 /* Return true if the kprobe is disarmed. Note: p must be on hash list */ 461 - static inline bool kprobe_disarmed(struct kprobe *p) 461 + bool kprobe_disarmed(struct kprobe *p) 462 462 { 463 463 struct optimized_kprobe *op; 464 464 ··· 555 555 /* See comment in do_optimize_kprobes() */ 556 556 lockdep_assert_cpus_held(); 557 557 558 - /* Unoptimization must be done anytime */ 559 - if (list_empty(&unoptimizing_list)) 560 - return; 558 + if (!list_empty(&unoptimizing_list)) 559 + arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list); 561 560 562 - arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list); 563 - /* Loop on 'freeing_list' for disarming */ 561 + /* Loop on 'freeing_list' for disarming and removing from kprobe hash list */ 564 562 list_for_each_entry_safe(op, tmp, &freeing_list, list) { 565 563 /* Switching from detour code to origin */ 566 564 op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; 567 - /* Disarm probes if marked disabled */ 568 - if (kprobe_disabled(&op->kp)) 565 + /* Disarm probes if marked disabled and not gone */ 566 + if (kprobe_disabled(&op->kp) && !kprobe_gone(&op->kp)) 569 567 arch_disarm_kprobe(&op->kp); 570 568 if (kprobe_unused(&op->kp)) { 571 569 /* ··· 660 662 mutex_unlock(&kprobe_mutex); 661 663 } 662 664 663 - static bool optprobe_queued_unopt(struct optimized_kprobe *op) 665 + bool optprobe_queued_unopt(struct optimized_kprobe *op) 664 666 { 665 667 struct optimized_kprobe *_op; 666 668 ··· 795 797 op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED; 796 798 797 799 if (kprobe_unused(p)) { 798 - /* Enqueue if it is unused */ 799 - list_add(&op->list, &freeing_list); 800 800 /* 801 - * Remove unused probes from the hash list. After waiting 802 - * for synchronization, this probe is reclaimed. 803 - * (reclaiming is done by do_free_cleaned_kprobes().) 801 + * Unused kprobe is on unoptimizing or freeing list. We move it 802 + * to freeing_list and let the kprobe_optimizer() remove it from 803 + * the kprobe hash list and free it. 804 804 */ 805 - hlist_del_rcu(&op->kp.hlist); 805 + if (optprobe_queued_unopt(op)) 806 + list_move(&op->list, &freeing_list); 806 807 } 807 808 808 809 /* Don't touch the code, because it is already freed. */
+2 -2
kernel/trace/trace.c
··· 5646 5646 #ifdef CONFIG_HIST_TRIGGERS 5647 5647 "\t s:[synthetic/]<event> <field> [<field>]\n" 5648 5648 #endif 5649 - "\t e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]\n" 5649 + "\t e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>] [if <filter>]\n" 5650 5650 "\t -:[<group>/][<event>]\n" 5651 5651 #ifdef CONFIG_KPROBE_EVENTS 5652 5652 "\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n" ··· 5663 5663 "\t $stack<index>, $stack, $retval, $comm,\n" 5664 5664 #endif 5665 5665 "\t +|-[u]<offset>(<fetcharg>), \\imm-value, \\\"imm-string\"\n" 5666 - "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, string, symbol,\n" 5666 + "\t type: s8/16/32/64, u8/16/32/64, x8/16/32/64, char, string, symbol,\n" 5667 5667 "\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n" 5668 5668 "\t symstr, <type>\\[<array-size>\\]\n" 5669 5669 #ifdef CONFIG_HIST_TRIGGERS
+4 -8
kernel/trace/trace_eprobe.c
··· 923 923 924 924 p = ep->filter_str; 925 925 for (i = 0; i < argc; i++) { 926 - ret = snprintf(p, len, "%s ", argv[i]); 927 - if (ret < 0) 928 - goto error; 929 - if (ret > len) { 930 - ret = -E2BIG; 931 - goto error; 932 - } 926 + if (i) 927 + ret = snprintf(p, len, " %s", argv[i]); 928 + else 929 + ret = snprintf(p, len, "%s", argv[i]); 933 930 p += ret; 934 931 len -= ret; 935 932 } 936 - p[-1] = '\0'; 937 933 938 934 /* 939 935 * Ensure the filter string can be parsed correctly. Note, this
+2
kernel/trace/trace_probe.c
··· 50 50 DEFINE_BASIC_PRINT_TYPE_FUNC(x16, u16, "0x%x") 51 51 DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x") 52 52 DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx") 53 + DEFINE_BASIC_PRINT_TYPE_FUNC(char, u8, "'%c'") 53 54 54 55 int PRINT_TYPE_FUNC_NAME(symbol)(struct trace_seq *s, void *data, void *ent) 55 56 { ··· 96 95 ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0), 97 96 ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0), 98 97 ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0), 98 + ASSIGN_FETCH_TYPE_ALIAS(char, u8, u8, 0), 99 99 ASSIGN_FETCH_TYPE_ALIAS(symbol, ADDR_FETCH_TYPE, ADDR_FETCH_TYPE, 0), 100 100 101 101 ASSIGN_FETCH_TYPE_END
+1
kernel/trace/trace_probe.h
··· 166 166 DECLARE_BASIC_PRINT_TYPE_FUNC(x32); 167 167 DECLARE_BASIC_PRINT_TYPE_FUNC(x64); 168 168 169 + DECLARE_BASIC_PRINT_TYPE_FUNC(char); 169 170 DECLARE_BASIC_PRINT_TYPE_FUNC(string); 170 171 DECLARE_BASIC_PRINT_TYPE_FUNC(symbol); 171 172
+37 -2
lib/test_kprobes.c
··· 14 14 15 15 static u32 rand1, preh_val, posth_val; 16 16 static u32 (*target)(u32 value); 17 + static u32 (*recursed_target)(u32 value); 17 18 static u32 (*target2)(u32 value); 18 19 static struct kunit *current_test; 19 20 ··· 28 27 return (value / div_factor); 29 28 } 30 29 30 + static noinline u32 kprobe_recursed_target(u32 value) 31 + { 32 + return (value / div_factor); 33 + } 34 + 31 35 static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs) 32 36 { 33 37 KUNIT_EXPECT_FALSE(current_test, preemptible()); 34 - preh_val = (rand1 / div_factor); 38 + 39 + preh_val = recursed_target(rand1); 35 40 return 0; 36 41 } 37 42 38 43 static void kp_post_handler(struct kprobe *p, struct pt_regs *regs, 39 44 unsigned long flags) 40 45 { 46 + u32 expval = recursed_target(rand1); 47 + 41 48 KUNIT_EXPECT_FALSE(current_test, preemptible()); 42 - KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor)); 49 + KUNIT_EXPECT_EQ(current_test, preh_val, expval); 50 + 43 51 posth_val = preh_val + div_factor; 44 52 } 45 53 ··· 144 134 KUNIT_EXPECT_NE(test, 0, preh_val); 145 135 KUNIT_EXPECT_NE(test, 0, posth_val); 146 136 unregister_kprobes(kps, 2); 137 + } 138 + 139 + static struct kprobe kp_missed = { 140 + .symbol_name = "kprobe_recursed_target", 141 + .pre_handler = kp_pre_handler, 142 + .post_handler = kp_post_handler, 143 + }; 144 + 145 + static void test_kprobe_missed(struct kunit *test) 146 + { 147 + current_test = test; 148 + preh_val = 0; 149 + posth_val = 0; 150 + 151 + KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp_missed)); 152 + 153 + recursed_target(rand1); 154 + 155 + KUNIT_EXPECT_EQ(test, 2, kp_missed.nmissed); 156 + KUNIT_EXPECT_NE(test, 0, preh_val); 157 + KUNIT_EXPECT_NE(test, 0, posth_val); 158 + 159 + unregister_kprobe(&kp_missed); 147 160 } 148 161 149 162 #ifdef CONFIG_KRETPROBES ··· 369 336 { 370 337 target = kprobe_target; 371 338 target2 = kprobe_target2; 339 + recursed_target = kprobe_recursed_target; 372 340 stacktrace_target = kprobe_stacktrace_target; 373 341 internal_target = kprobe_stacktrace_internal_target; 374 342 stacktrace_driver = kprobe_stacktrace_driver; ··· 380 346 static struct kunit_case kprobes_testcases[] = { 381 347 KUNIT_CASE(test_kprobe), 382 348 KUNIT_CASE(test_kprobes), 349 + KUNIT_CASE(test_kprobe_missed), 383 350 #ifdef CONFIG_KRETPROBES 384 351 KUNIT_CASE(test_kretprobe), 385 352 KUNIT_CASE(test_kretprobes),
+3 -1
tools/testing/selftests/ftrace/test.d/dynevent/eprobes_syntax_errors.tc
··· 22 22 check_error 'e:foo/bar syscalls/sys_enter_openat arg=^dfd' # BAD_FETCH_ARG 23 23 check_error 'e:foo/bar syscalls/sys_enter_openat ^arg=$foo' # BAD_ATTACH_ARG 24 24 25 - check_error 'e:foo/bar syscalls/sys_enter_openat if ^' # NO_EP_FILTER 25 + if grep -q '<attached-group>\.<attached-event>.*\[if <filter>\]' README; then 26 + check_error 'e:foo/bar syscalls/sys_enter_openat if ^' # NO_EP_FILTER 27 + fi 26 28 27 29 exit 0
+47
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_char.tc
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # description: Kprobe event char type argument 4 + # requires: kprobe_events 5 + 6 + case `uname -m` in 7 + x86_64) 8 + ARG1=%di 9 + ;; 10 + i[3456]86) 11 + ARG1=%ax 12 + ;; 13 + aarch64) 14 + ARG1=%x0 15 + ;; 16 + arm*) 17 + ARG1=%r0 18 + ;; 19 + ppc64*) 20 + ARG1=%r3 21 + ;; 22 + ppc*) 23 + ARG1=%r3 24 + ;; 25 + s390*) 26 + ARG1=%r2 27 + ;; 28 + mips*) 29 + ARG1=%r4 30 + ;; 31 + *) 32 + echo "Please implement other architecture here" 33 + exit_untested 34 + esac 35 + 36 + : "Test get argument (1)" 37 + echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):char" > kprobe_events 38 + echo 1 > events/kprobes/testprobe/enable 39 + echo "p:test $FUNCTION_FORK" >> kprobe_events 40 + grep -qe "testprobe.* arg1='t'" trace 41 + 42 + echo 0 > events/kprobes/testprobe/enable 43 + : "Test get argument (2)" 44 + echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):char arg2=+0(${ARG1}):char[4]" > kprobe_events 45 + echo 1 > events/kprobes/testprobe/enable 46 + echo "p:test $FUNCTION_FORK" >> kprobe_events 47 + grep -qe "testprobe.* arg1='t' arg2={'t','e','s','t'}" trace
+1 -1
tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc
··· 21 21 22 22 # We have to decode symbol addresses to get correct offsets. 23 23 # If the offset is not an instruction boundary, it cause -EILSEQ. 24 - set_offs `grep -A1 -B1 ${TARGET_FUNC} /proc/kallsyms | cut -f 1 -d " " | xargs` 24 + set_offs `grep -v __pfx_ /proc/kallsyms | grep -A1 -B1 ${TARGET_FUNC} | cut -f 1 -d " " | xargs` 25 25 26 26 UINT_TEST=no 27 27 # printf "%x" -1 returns (unsigned long)-1.