Skip to content

Commit

Permalink
Merge tag 'probes-v6.15' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Linus Torvalds committed Mar 28, 2025
2 parents dcf9f31 + bb9c602 commit a7e135f
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 4 deletions.
2 changes: 2 additions & 0 deletions kernel/trace/trace_eprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,8 @@ static int __trace_eprobe_create(int argc, const char *argv[])
}

if (argc - 2 > MAX_TRACE_ARGS) {
trace_probe_log_set_index(2);
trace_probe_log_err(0, TOO_MANY_ARGS);
ret = -E2BIG;
goto error;
}
Expand Down
5 changes: 4 additions & 1 deletion kernel/trace/trace_fprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1199,8 +1199,11 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
argc = new_argc;
argv = new_argv;
}
if (argc > MAX_TRACE_ARGS)
if (argc > MAX_TRACE_ARGS) {
trace_probe_log_set_index(2);
trace_probe_log_err(0, TOO_MANY_ARGS);
return -E2BIG;
}

ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
if (ret)
Expand Down
5 changes: 4 additions & 1 deletion kernel/trace/trace_kprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1007,8 +1007,11 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
argc = new_argc;
argv = new_argv;
}
if (argc > MAX_TRACE_ARGS)
if (argc > MAX_TRACE_ARGS) {
trace_probe_log_set_index(2);
trace_probe_log_err(0, TOO_MANY_ARGS);
return -E2BIG;
}

ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
if (ret)
Expand Down
28 changes: 28 additions & 0 deletions kernel/trace/trace_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,10 @@ static int check_prepare_btf_string_fetch(char *typename,

#ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API

/*
* Add the entry code to store the 'argnum'th parameter and return the offset
* in the entry data buffer where the data will be stored.
*/
static int __store_entry_arg(struct trace_probe *tp, int argnum)
{
struct probe_entry_arg *earg = tp->entry_arg;
Expand All @@ -793,6 +797,20 @@ static int __store_entry_arg(struct trace_probe *tp, int argnum)
tp->entry_arg = earg;
}

/*
* The entry code array is repeating the pair of
* [FETCH_OP_ARG(argnum)][FETCH_OP_ST_EDATA(offset of entry data buffer)]
* and the rest of entries are filled with [FETCH_OP_END].
*
* To reduce the redundant function parameter fetching, we scan the entry
* code array to find the FETCH_OP_ARG which already fetches the 'argnum'
* parameter. If it doesn't match, update 'offset' to find the last
* offset.
* If we find the FETCH_OP_END without matching FETCH_OP_ARG entry, we
* will save the entry with FETCH_OP_ARG and FETCH_OP_ST_EDATA, and
* return data offset so that caller can find the data offset in the entry
* data buffer.
*/
offset = 0;
for (i = 0; i < earg->size - 1; i++) {
switch (earg->code[i].op) {
Expand Down Expand Up @@ -826,6 +844,16 @@ int traceprobe_get_entry_data_size(struct trace_probe *tp)
if (!earg)
return 0;

/*
* earg->code[] array has an operation sequence which is run in
* the entry handler.
* The sequence stopped by FETCH_OP_END and each data stored in
* the entry data buffer by FETCH_OP_ST_EDATA. The FETCH_OP_ST_EDATA
* stores the data at the data buffer + its offset, and all data are
* "unsigned long" size. The offset must be increased when a data is
* stored. Thus we need to find the last FETCH_OP_ST_EDATA in the
* code array.
*/
for (i = 0; i < earg->size; i++) {
switch (earg->code[i].op) {
case FETCH_OP_END:
Expand Down
1 change: 1 addition & 0 deletions kernel/trace/trace_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,7 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
C(BAD_BTF_TID, "Failed to get BTF type info."),\
C(BAD_TYPE4STR, "This type does not fit for string."),\
C(NEED_STRING_TYPE, "$comm and immediate-string only accepts string type"),\
C(TOO_MANY_ARGS, "Too many arguments are specified"), \
C(TOO_MANY_EARGS, "Too many entry arguments specified"),

#undef C
Expand Down
9 changes: 7 additions & 2 deletions kernel/trace/trace_uprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,14 @@ static int __trace_uprobe_create(int argc, const char **argv)

if (argc < 2)
return -ECANCELED;
if (argc - 2 > MAX_TRACE_ARGS)

trace_probe_log_init("trace_uprobe", argc, argv);

if (argc - 2 > MAX_TRACE_ARGS) {
trace_probe_log_set_index(2);
trace_probe_log_err(0, TOO_MANY_ARGS);
return -E2BIG;
}

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

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

*arg++ = '\0';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
echo 0 > events/enable
echo > dynamic_events

SUBSYSTEM=kmem
TRACEPOINT1=kmem_cache_alloc
TRACEPOINT2=kmem_cache_free

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

echo > dynamic_events

# auto naming check
echo "t $TRACEPOINT1" >> dynamic_events

test -d events/tracepoints/$TRACEPOINT1

echo > dynamic_events

# SUBSYSTEM is not supported
echo "t $SUBSYSTEM/$TRACEPOINT1" >> dynamic_events && exit_fail ||:
echo "t $SUBSYSTEM:$TRACEPOINT1" >> dynamic_events && exit_fail ||:
echo "t:myevent3 $SUBSYSTEM/$TRACEPOINT1" >> dynamic_events && exit_fail ||:
echo "t:myevent3 $SUBSYSTEM:$TRACEPOINT1" >> dynamic_events && exit_fail ||:

clear_trace
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# description: Checking dynamic events limitations
# requires: dynamic_events "imm-value":README

# Max arguments limitation
MAX_ARGS=128
EXCEED_ARGS=$((MAX_ARGS + 1))

check_max_args() { # event_header
TEST_STRING=$1
# Acceptable
for i in `seq 1 $MAX_ARGS`; do
TEST_STRING="$TEST_STRING \\$i"
done
echo "$TEST_STRING" >> dynamic_events
echo > dynamic_events
# Error
TEST_STRING="$TEST_STRING \\$EXCEED_ARGS"
! echo "$TEST_STRING" >> dynamic_events
return 0
}

# Kprobe max args limitation
if grep -q "kprobe_events" README; then
check_max_args "p vfs_read"
fi

# Fprobe max args limitation
if grep -q "f[:[<group>/][<event>]] <func-name>[%return] [<args>]" README; then
check_max_args "f vfs_read"
fi

# Tprobe max args limitation
if grep -q "t[:[<group>/][<event>]] <tracepoint> [<args>]" README; then
check_max_args "t kfree"
fi

# Uprobe max args limitation
if grep -q "uprobe_events" README; then
check_max_args "p /bin/sh:10"
fi
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ check_error 'f:^foo.1/bar vfs_read' # BAD_GROUP_NAME
check_error 'f:^ vfs_read' # NO_EVENT_NAME
check_error 'f:foo/^12345678901234567890123456789012345678901234567890123456789012345 vfs_read' # EVENT_TOO_LONG
check_error 'f:foo/^bar.1 vfs_read' # BAD_EVENT_NAME
check_error 't kmem^/kfree' # BAD_TP_NAME

check_error 'f vfs_read ^$stack10000' # BAD_STACK_NUM

Expand Down

0 comments on commit a7e135f

Please sign in to comment.