Skip to content

Commit a7e135f

Browse files
committed
Merge tag 'probes-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace
Pull probes updates from Masami Hiramatsu: - probe-events: Add comments about entry data storing code to clarify where and how the entry data is stored for function return events. - probe-events: Log error for exceeding the number of arguments to help user to identify error reason via tracefs/error_log file. - Improve the ftracetest selftests: - Expand the tprobe event test to check if it can correctly find the wrong format tracepoint name. - Add new syntax error test to check whether error_log correctly indicates a wrong character in the tracepoint name. - Add a new dynamic events argument limitation test case which checks max number of probe arguments. * tag 'probes-v6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: tracing: probe-events: Add comments about entry data storing code selftests/ftrace: Add dynamic events argument limitation test case selftests/ftrace: Add new syntax error test selftests/ftrace: Expand the tprobe event test to check wrong format tracing: probe-events: Log error for exceeding the number of arguments
2 parents dcf9f31 + bb9c602 commit a7e135f

File tree

9 files changed

+103
-4
lines changed

9 files changed

+103
-4
lines changed

kernel/trace/trace_eprobe.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,8 @@ static int __trace_eprobe_create(int argc, const char *argv[])
913913
}
914914

915915
if (argc - 2 > MAX_TRACE_ARGS) {
916+
trace_probe_log_set_index(2);
917+
trace_probe_log_err(0, TOO_MANY_ARGS);
916918
ret = -E2BIG;
917919
goto error;
918920
}

kernel/trace/trace_fprobe.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1199,8 +1199,11 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
11991199
argc = new_argc;
12001200
argv = new_argv;
12011201
}
1202-
if (argc > MAX_TRACE_ARGS)
1202+
if (argc > MAX_TRACE_ARGS) {
1203+
trace_probe_log_set_index(2);
1204+
trace_probe_log_err(0, TOO_MANY_ARGS);
12031205
return -E2BIG;
1206+
}
12041207

12051208
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
12061209
if (ret)

kernel/trace/trace_kprobe.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1007,8 +1007,11 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
10071007
argc = new_argc;
10081008
argv = new_argv;
10091009
}
1010-
if (argc > MAX_TRACE_ARGS)
1010+
if (argc > MAX_TRACE_ARGS) {
1011+
trace_probe_log_set_index(2);
1012+
trace_probe_log_err(0, TOO_MANY_ARGS);
10111013
return -E2BIG;
1014+
}
10121015

10131016
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
10141017
if (ret)

kernel/trace/trace_probe.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,10 @@ static int check_prepare_btf_string_fetch(char *typename,
770770

771771
#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
772772

773+
/*
774+
* Add the entry code to store the 'argnum'th parameter and return the offset
775+
* in the entry data buffer where the data will be stored.
776+
*/
773777
static int __store_entry_arg(struct trace_probe *tp, int argnum)
774778
{
775779
struct probe_entry_arg *earg = tp->entry_arg;
@@ -793,6 +797,20 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum)
793797
tp->entry_arg = earg;
794798
}
795799

800+
/*
801+
* The entry code array is repeating the pair of
802+
* [FETCH_OP_ARG(argnum)][FETCH_OP_ST_EDATA(offset of entry data buffer)]
803+
* and the rest of entries are filled with [FETCH_OP_END].
804+
*
805+
* To reduce the redundant function parameter fetching, we scan the entry
806+
* code array to find the FETCH_OP_ARG which already fetches the 'argnum'
807+
* parameter. If it doesn't match, update 'offset' to find the last
808+
* offset.
809+
* If we find the FETCH_OP_END without matching FETCH_OP_ARG entry, we
810+
* will save the entry with FETCH_OP_ARG and FETCH_OP_ST_EDATA, and
811+
* return data offset so that caller can find the data offset in the entry
812+
* data buffer.
813+
*/
796814
offset = 0;
797815
for (i = 0; i < earg->size - 1; i++) {
798816
switch (earg->code[i].op) {
@@ -826,6 +844,16 @@ int traceprobe_get_entry_data_size(struct trace_probe *tp)
826844
if (!earg)
827845
return 0;
828846

847+
/*
848+
* earg->code[] array has an operation sequence which is run in
849+
* the entry handler.
850+
* The sequence stopped by FETCH_OP_END and each data stored in
851+
* the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
852+
* stores the data at the data buffer + its offset, and all data are
853+
* "unsigned long" size. The offset must be increased when a data is
854+
* stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
855+
* code array.
856+
*/
829857
for (i = 0; i < earg->size; i++) {
830858
switch (earg->code[i].op) {
831859
case FETCH_OP_END:

kernel/trace/trace_probe.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
545545
C(BAD_BTF_TID, "Failed to get BTF type info."),\
546546
C(BAD_TYPE4STR, "This type does not fit for string."),\
547547
C(NEED_STRING_TYPE, "$comm and immediate-string only accepts string type"),\
548+
C(TOO_MANY_ARGS, "Too many arguments are specified"), \
548549
C(TOO_MANY_EARGS, "Too many entry arguments specified"),
549550

550551
#undef C

kernel/trace/trace_uprobe.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,14 @@ static int __trace_uprobe_create(int argc, const char **argv)
562562

563563
if (argc < 2)
564564
return -ECANCELED;
565-
if (argc - 2 > MAX_TRACE_ARGS)
565+
566+
trace_probe_log_init("trace_uprobe", argc, argv);
567+
568+
if (argc - 2 > MAX_TRACE_ARGS) {
569+
trace_probe_log_set_index(2);
570+
trace_probe_log_err(0, TOO_MANY_ARGS);
566571
return -E2BIG;
572+
}
567573

568574
if (argv[0][1] == ':')
569575
event = &argv[0][2];
@@ -582,7 +588,6 @@ static int __trace_uprobe_create(int argc, const char **argv)
582588
return -ECANCELED;
583589
}
584590

585-
trace_probe_log_init("trace_uprobe", argc, argv);
586591
trace_probe_log_set_index(1); /* filename is the 2nd argument */
587592

588593
*arg++ = '\0';

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
echo 0 > events/enable
77
echo > dynamic_events
88

9+
SUBSYSTEM=kmem
910
TRACEPOINT1=kmem_cache_alloc
1011
TRACEPOINT2=kmem_cache_free
1112

@@ -24,4 +25,17 @@ grep -q myevent1 dynamic_events
2425

2526
echo > dynamic_events
2627

28+
# auto naming check
29+
echo "t $TRACEPOINT1" >> dynamic_events
30+
31+
test -d events/tracepoints/$TRACEPOINT1
32+
33+
echo > dynamic_events
34+
35+
# SUBSYSTEM is not supported
36+
echo "t $SUBSYSTEM/$TRACEPOINT1" >> dynamic_events && exit_fail ||:
37+
echo "t $SUBSYSTEM:$TRACEPOINT1" >> dynamic_events && exit_fail ||:
38+
echo "t:myevent3 $SUBSYSTEM/$TRACEPOINT1" >> dynamic_events && exit_fail ||:
39+
echo "t:myevent3 $SUBSYSTEM:$TRACEPOINT1" >> dynamic_events && exit_fail ||:
40+
2741
clear_trace
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: GPL-2.0
3+
# description: Checking dynamic events limitations
4+
# requires: dynamic_events "imm-value":README
5+
6+
# Max arguments limitation
7+
MAX_ARGS=128
8+
EXCEED_ARGS=$((MAX_ARGS + 1))
9+
10+
check_max_args() { # event_header
11+
TEST_STRING=$1
12+
# Acceptable
13+
for i in `seq 1 $MAX_ARGS`; do
14+
TEST_STRING="$TEST_STRING \\$i"
15+
done
16+
echo "$TEST_STRING" >> dynamic_events
17+
echo > dynamic_events
18+
# Error
19+
TEST_STRING="$TEST_STRING \\$EXCEED_ARGS"
20+
! echo "$TEST_STRING" >> dynamic_events
21+
return 0
22+
}
23+
24+
# Kprobe max args limitation
25+
if grep -q "kprobe_events" README; then
26+
check_max_args "p vfs_read"
27+
fi
28+
29+
# Fprobe max args limitation
30+
if grep -q "f[:[<group>/][<event>]] <func-name>[%return] [<args>]" README; then
31+
check_max_args "f vfs_read"
32+
fi
33+
34+
# Tprobe max args limitation
35+
if grep -q "t[:[<group>/][<event>]] <tracepoint> [<args>]" README; then
36+
check_max_args "t kfree"
37+
fi
38+
39+
# Uprobe max args limitation
40+
if grep -q "uprobe_events" README; then
41+
check_max_args "p /bin/sh:10"
42+
fi

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ check_error 'f:^foo.1/bar vfs_read' # BAD_GROUP_NAME
2727
check_error 'f:^ vfs_read' # NO_EVENT_NAME
2828
check_error 'f:foo/^12345678901234567890123456789012345678901234567890123456789012345 vfs_read' # EVENT_TOO_LONG
2929
check_error 'f:foo/^bar.1 vfs_read' # BAD_EVENT_NAME
30+
check_error 't kmem^/kfree' # BAD_TP_NAME
3031

3132
check_error 'f vfs_read ^$stack10000' # BAD_STACK_NUM
3233

0 commit comments

Comments
 (0)