Skip to content

Commit 73f3508

Browse files
mikelrmhiramat
authored andcommitted
tracing/probes: Fix MAX_TRACE_ARGS limit handling
When creating a trace_probe we would set nr_args prior to truncating the arguments to MAX_TRACE_ARGS. However, we would only initialize arguments up to the limit. This caused invalid memory access when attempting to set up probes with more than 128 fetchargs. BUG: kernel NULL pointer dereference, address: 0000000000000020 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: Oops: 0000 [#1] PREEMPT SMP PTI CPU: 0 UID: 0 PID: 1769 Comm: cat Not tainted 6.11.0-rc7+ #8 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-1.fc39 04/01/2014 RIP: 0010:__set_print_fmt+0x134/0x330 Resolve the issue by applying the MAX_TRACE_ARGS limit earlier. Return an error when there are too many arguments instead of silently truncating. Link: https://lore.kernel.org/all/20240930202656.292869-1-mikel@mikelr.com/ Fixes: 035ba76 ("tracing/probes: cleanup: Set trace_probe::nr_args at trace_probe_init") Signed-off-by: Mikel Rychliski <mikel@mikelr.com> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
1 parent aff1871 commit 73f3508

File tree

4 files changed

+19
-4
lines changed

4 files changed

+19
-4
lines changed

Diff for: kernel/trace/trace_eprobe.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,11 @@ static int __trace_eprobe_create(int argc, const char *argv[])
912912
}
913913
}
914914

915+
if (argc - 2 > MAX_TRACE_ARGS) {
916+
ret = -E2BIG;
917+
goto error;
918+
}
919+
915920
mutex_lock(&event_mutex);
916921
event_call = find_and_get_event(sys_name, sys_event);
917922
ep = alloc_event_probe(group, event, event_call, argc - 2);
@@ -937,7 +942,7 @@ static int __trace_eprobe_create(int argc, const char *argv[])
937942

938943
argc -= 2; argv += 2;
939944
/* parse arguments */
940-
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
945+
for (i = 0; i < argc; i++) {
941946
trace_probe_log_set_index(i + 2);
942947
ret = trace_eprobe_tp_update_arg(ep, argv, i);
943948
if (ret)

Diff for: kernel/trace/trace_fprobe.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -1187,6 +1187,10 @@ static int __trace_fprobe_create(int argc, const char *argv[])
11871187
argc = new_argc;
11881188
argv = new_argv;
11891189
}
1190+
if (argc > MAX_TRACE_ARGS) {
1191+
ret = -E2BIG;
1192+
goto out;
1193+
}
11901194

11911195
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
11921196
if (ret)
@@ -1203,7 +1207,7 @@ static int __trace_fprobe_create(int argc, const char *argv[])
12031207
}
12041208

12051209
/* parse arguments */
1206-
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
1210+
for (i = 0; i < argc; i++) {
12071211
trace_probe_log_set_index(i + 2);
12081212
ctx.offset = 0;
12091213
ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx);

Diff for: kernel/trace/trace_kprobe.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,10 @@ static int __trace_kprobe_create(int argc, const char *argv[])
10131013
argc = new_argc;
10141014
argv = new_argv;
10151015
}
1016+
if (argc > MAX_TRACE_ARGS) {
1017+
ret = -E2BIG;
1018+
goto out;
1019+
}
10161020

10171021
ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
10181022
if (ret)
@@ -1029,7 +1033,7 @@ static int __trace_kprobe_create(int argc, const char *argv[])
10291033
}
10301034

10311035
/* parse arguments */
1032-
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
1036+
for (i = 0; i < argc; i++) {
10331037
trace_probe_log_set_index(i + 2);
10341038
ctx.offset = 0;
10351039
ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);

Diff for: kernel/trace/trace_uprobe.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,8 @@ static int __trace_uprobe_create(int argc, const char **argv)
565565

566566
if (argc < 2)
567567
return -ECANCELED;
568+
if (argc - 2 > MAX_TRACE_ARGS)
569+
return -E2BIG;
568570

569571
if (argv[0][1] == ':')
570572
event = &argv[0][2];
@@ -690,7 +692,7 @@ static int __trace_uprobe_create(int argc, const char **argv)
690692
tu->filename = filename;
691693

692694
/* parse arguments */
693-
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
695+
for (i = 0; i < argc; i++) {
694696
struct traceprobe_parse_context ctx = {
695697
.flags = (is_return ? TPARG_FL_RETURN : 0) | TPARG_FL_USER,
696698
};

0 commit comments

Comments
 (0)