Skip to content

Commit 2b79eb7

Browse files
committed
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
2 parents 0df8218 + c96abae commit 2b79eb7

File tree

12 files changed

+117
-33
lines changed

12 files changed

+117
-33
lines changed

Documentation/trace/kprobetrace.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Synopsis of kprobe_events
5858
NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
5959
FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
6060
(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"
6262
and bitfield are supported.
6363

6464
(\*1) only for the probe on function entry (offs == 0).
@@ -82,6 +82,8 @@ Note that the array can be applied to memory type fetchargs, you can not
8282
apply it to registers/stack-entries etc. (for example, '$stack1:x8[8]' is
8383
wrong, but '+8($stack):x8[8]' is OK.)
8484

85+
Char type can be used to show the character value of traced arguments.
86+
8587
String type is a special type, which fetches a "null-terminated" string from
8688
kernel space. This means it will fail and store NULL if the string container
8789
has been paged out. "ustring" type is an alternative of string for user-space.

arch/x86/kernel/kprobes/opt.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr)
4646
/* This function only handles jump-optimized kprobe */
4747
if (kp && kprobe_optimized(kp)) {
4848
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))
5151
goto found;
5252
}
5353
}
@@ -353,7 +353,7 @@ int arch_check_optimized_kprobe(struct optimized_kprobe *op)
353353

354354
for (i = 1; i < op->optinsn.size; i++) {
355355
p = get_kprobe(op->kp.addr + i);
356-
if (p && !kprobe_disabled(p))
356+
if (p && !kprobe_disarmed(p))
357357
return -EEXIST;
358358
}
359359

include/linux/kprobes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@ extern void opt_pre_handler(struct kprobe *p, struct pt_regs *regs);
378378
DEFINE_INSN_CACHE_OPS(optinsn);
379379

380380
extern void wait_for_kprobe_optimizer(void);
381+
bool optprobe_queued_unopt(struct optimized_kprobe *op);
382+
bool kprobe_disarmed(struct kprobe *p);
381383
#else /* !CONFIG_OPTPROBES */
382384
static inline void wait_for_kprobe_optimizer(void) { }
383385
#endif /* CONFIG_OPTPROBES */

kernel/kprobes.c

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ static inline int kprobe_optready(struct kprobe *p)
458458
}
459459

460460
/* 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)
462462
{
463463
struct optimized_kprobe *op;
464464

@@ -555,17 +555,15 @@ static void do_unoptimize_kprobes(void)
555555
/* See comment in do_optimize_kprobes() */
556556
lockdep_assert_cpus_held();
557557

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);
561560

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 */
564562
list_for_each_entry_safe(op, tmp, &freeing_list, list) {
565563
/* Switching from detour code to origin */
566564
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))
569567
arch_disarm_kprobe(&op->kp);
570568
if (kprobe_unused(&op->kp)) {
571569
/*
@@ -662,7 +660,7 @@ void wait_for_kprobe_optimizer(void)
662660
mutex_unlock(&kprobe_mutex);
663661
}
664662

665-
static bool optprobe_queued_unopt(struct optimized_kprobe *op)
663+
bool optprobe_queued_unopt(struct optimized_kprobe *op)
666664
{
667665
struct optimized_kprobe *_op;
668666

@@ -797,14 +795,13 @@ static void kill_optimized_kprobe(struct kprobe *p)
797795
op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
798796

799797
if (kprobe_unused(p)) {
800-
/* Enqueue if it is unused */
801-
list_add(&op->list, &freeing_list);
802798
/*
803-
* Remove unused probes from the hash list. After waiting
804-
* for synchronization, this probe is reclaimed.
805-
* (reclaiming is done by do_free_cleaned_kprobes().)
799+
* Unused kprobe is on unoptimizing or freeing list. We move it
800+
* to freeing_list and let the kprobe_optimizer() remove it from
801+
* the kprobe hash list and free it.
806802
*/
807-
hlist_del_rcu(&op->kp.hlist);
803+
if (optprobe_queued_unopt(op))
804+
list_move(&op->list, &freeing_list);
808805
}
809806

810807
/* Don't touch the code, because it is already freed. */

kernel/trace/trace.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5646,7 +5646,7 @@ static const char readme_msg[] =
56465646
#ifdef CONFIG_HIST_TRIGGERS
56475647
"\t s:[synthetic/]<event> <field> [<field>]\n"
56485648
#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"
56505650
"\t -:[<group>/][<event>]\n"
56515651
#ifdef CONFIG_KPROBE_EVENTS
56525652
"\t place: [<module>:]<symbol>[+<offset>]|<memaddr>\n"
@@ -5663,7 +5663,7 @@ static const char readme_msg[] =
56635663
"\t $stack<index>, $stack, $retval, $comm,\n"
56645664
#endif
56655665
"\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"
56675667
"\t b<bit-width>@<bit-offset>/<container-size>, ustring,\n"
56685668
"\t symstr, <type>\\[<array-size>\\]\n"
56695669
#ifdef CONFIG_HIST_TRIGGERS

kernel/trace/trace_eprobe.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -923,17 +923,13 @@ static int trace_eprobe_parse_filter(struct trace_eprobe *ep, int argc, const ch
923923

924924
p = ep->filter_str;
925925
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]);
933930
p += ret;
934931
len -= ret;
935932
}
936-
p[-1] = '\0';
937933

938934
/*
939935
* Ensure the filter string can be parsed correctly. Note, this

kernel/trace/trace_probe.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ DEFINE_BASIC_PRINT_TYPE_FUNC(x8, u8, "0x%x")
5050
DEFINE_BASIC_PRINT_TYPE_FUNC(x16, u16, "0x%x")
5151
DEFINE_BASIC_PRINT_TYPE_FUNC(x32, u32, "0x%x")
5252
DEFINE_BASIC_PRINT_TYPE_FUNC(x64, u64, "0x%Lx")
53+
DEFINE_BASIC_PRINT_TYPE_FUNC(char, u8, "'%c'")
5354

5455
int PRINT_TYPE_FUNC_NAME(symbol)(struct trace_seq *s, void *data, void *ent)
5556
{
@@ -95,6 +96,7 @@ static const struct fetch_type probe_fetch_types[] = {
9596
ASSIGN_FETCH_TYPE_ALIAS(x16, u16, u16, 0),
9697
ASSIGN_FETCH_TYPE_ALIAS(x32, u32, u32, 0),
9798
ASSIGN_FETCH_TYPE_ALIAS(x64, u64, u64, 0),
99+
ASSIGN_FETCH_TYPE_ALIAS(char, u8, u8, 0),
98100
ASSIGN_FETCH_TYPE_ALIAS(symbol, ADDR_FETCH_TYPE, ADDR_FETCH_TYPE, 0),
99101

100102
ASSIGN_FETCH_TYPE_END

kernel/trace/trace_probe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ DECLARE_BASIC_PRINT_TYPE_FUNC(x16);
166166
DECLARE_BASIC_PRINT_TYPE_FUNC(x32);
167167
DECLARE_BASIC_PRINT_TYPE_FUNC(x64);
168168

169+
DECLARE_BASIC_PRINT_TYPE_FUNC(char);
169170
DECLARE_BASIC_PRINT_TYPE_FUNC(string);
170171
DECLARE_BASIC_PRINT_TYPE_FUNC(symbol);
171172

lib/test_kprobes.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
static u32 rand1, preh_val, posth_val;
1616
static u32 (*target)(u32 value);
17+
static u32 (*recursed_target)(u32 value);
1718
static u32 (*target2)(u32 value);
1819
static struct kunit *current_test;
1920

@@ -27,18 +28,27 @@ static noinline u32 kprobe_target(u32 value)
2728
return (value / div_factor);
2829
}
2930

31+
static noinline u32 kprobe_recursed_target(u32 value)
32+
{
33+
return (value / div_factor);
34+
}
35+
3036
static int kp_pre_handler(struct kprobe *p, struct pt_regs *regs)
3137
{
3238
KUNIT_EXPECT_FALSE(current_test, preemptible());
33-
preh_val = (rand1 / div_factor);
39+
40+
preh_val = recursed_target(rand1);
3441
return 0;
3542
}
3643

3744
static void kp_post_handler(struct kprobe *p, struct pt_regs *regs,
3845
unsigned long flags)
3946
{
47+
u32 expval = recursed_target(rand1);
48+
4049
KUNIT_EXPECT_FALSE(current_test, preemptible());
41-
KUNIT_EXPECT_EQ(current_test, preh_val, (rand1 / div_factor));
50+
KUNIT_EXPECT_EQ(current_test, preh_val, expval);
51+
4252
posth_val = preh_val + div_factor;
4353
}
4454

@@ -136,6 +146,29 @@ static void test_kprobes(struct kunit *test)
136146
unregister_kprobes(kps, 2);
137147
}
138148

149+
static struct kprobe kp_missed = {
150+
.symbol_name = "kprobe_recursed_target",
151+
.pre_handler = kp_pre_handler,
152+
.post_handler = kp_post_handler,
153+
};
154+
155+
static void test_kprobe_missed(struct kunit *test)
156+
{
157+
current_test = test;
158+
preh_val = 0;
159+
posth_val = 0;
160+
161+
KUNIT_EXPECT_EQ(test, 0, register_kprobe(&kp_missed));
162+
163+
recursed_target(rand1);
164+
165+
KUNIT_EXPECT_EQ(test, 2, kp_missed.nmissed);
166+
KUNIT_EXPECT_NE(test, 0, preh_val);
167+
KUNIT_EXPECT_NE(test, 0, posth_val);
168+
169+
unregister_kprobe(&kp_missed);
170+
}
171+
139172
#ifdef CONFIG_KRETPROBES
140173
static u32 krph_val;
141174

@@ -336,6 +369,7 @@ static int kprobes_test_init(struct kunit *test)
336369
{
337370
target = kprobe_target;
338371
target2 = kprobe_target2;
372+
recursed_target = kprobe_recursed_target;
339373
stacktrace_target = kprobe_stacktrace_target;
340374
internal_target = kprobe_stacktrace_internal_target;
341375
stacktrace_driver = kprobe_stacktrace_driver;
@@ -346,6 +380,7 @@ static int kprobes_test_init(struct kunit *test)
346380
static struct kunit_case kprobes_testcases[] = {
347381
KUNIT_CASE(test_kprobe),
348382
KUNIT_CASE(test_kprobes),
383+
KUNIT_CASE(test_kprobe_missed),
349384
#ifdef CONFIG_KRETPROBES
350385
KUNIT_CASE(test_kretprobe),
351386
KUNIT_CASE(test_kretprobes),

tools/testing/selftests/ftrace/test.d/dynevent/eprobes_syntax_errors.tc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ check_error 'e:foo/^bar.1 syscalls/sys_enter_openat' # BAD_EVENT_NAME
2222
check_error 'e:foo/bar syscalls/sys_enter_openat arg=^dfd' # BAD_FETCH_ARG
2323
check_error 'e:foo/bar syscalls/sys_enter_openat ^arg=$foo' # BAD_ATTACH_ARG
2424

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
2628

2729
exit 0

0 commit comments

Comments
 (0)