History

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/

Mikel Rychliski committed 2 years ago

Commit 73f35081 parent aff18714 files · +19 −4Browse files

Unified · Split

4 files
  1. kernel/trace/trace_eprobe.c +6 −1
  2. kernel/trace/trace_fprobe.c +5 −1
  3. kernel/trace/trace_kprobe.c +5 −1
  4. kernel/trace/trace_uprobe.c +3 −1
kernel/trace/trace_eprobe.c+6−1
@@ -912,6 +912,11 @@ static int __trace_eprobe_create(int argc, const char *argv[]) · 911 unmodified lines
912 }912 }
913 }913 }
914 914
915 if (argc - 2 > MAX_TRACE_ARGS) {
916 ret = -E2BIG;
917 goto error;
918 }
919
915 mutex_lock(&event_mutex);920 mutex_lock(&event_mutex);
916 event_call = find_and_get_event(sys_name, sys_event);921 event_call = find_and_get_event(sys_name, sys_event);
917 ep = alloc_event_probe(group, event, event_call, argc - 2);922 ep = alloc_event_probe(group, event, event_call, argc - 2);
@@ -937,7 +942,7 @@ static int __trace_eprobe_create(int argc, const char *argv[]) · 19 unmodified lines
937 942
938 argc -= 2; argv += 2;943 argc -= 2; argv += 2;
939 /* parse arguments */944 /* parse arguments */
940 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {945 for (i = 0; i < argc; i++) {
941 trace_probe_log_set_index(i + 2);946 trace_probe_log_set_index(i + 2);
942 ret = trace_eprobe_tp_update_arg(ep, argv, i);947 ret = trace_eprobe_tp_update_arg(ep, argv, i);
943 if (ret)948 if (ret)
kernel/trace/trace_fprobe.c+5−1
@@ -1187,6 +1187,10 @@ static int __trace_fprobe_create(int argc, const char *argv[]) · 1186 unmodified lines
1187 argc = new_argc;1187 argc = new_argc;
1188 argv = new_argv;1188 argv = new_argv;
1189 }1189 }
1190 if (argc > MAX_TRACE_ARGS) {
1191 ret = -E2BIG;
1192 goto out;
1193 }
1190 1194
1191 ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);1195 ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
1192 if (ret)1196 if (ret)
@@ -1203,7 +1207,7 @@ static int __trace_fprobe_create(int argc, const char *argv[]) · 10 unmodified lines
1203 }1207 }
1204 1208
1205 /* parse arguments */1209 /* parse arguments */
1206 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {1210 for (i = 0; i < argc; i++) {
1207 trace_probe_log_set_index(i + 2);1211 trace_probe_log_set_index(i + 2);
1208 ctx.offset = 0;1212 ctx.offset = 0;
1209 ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx);1213 ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx);
kernel/trace/trace_kprobe.c+5−1
@@ -1013,6 +1013,10 @@ static int __trace_kprobe_create(int argc, const char *argv[]) · 1012 unmodified lines
1013 argc = new_argc;1013 argc = new_argc;
1014 argv = new_argv;1014 argv = new_argv;
1015 }1015 }
1016 if (argc > MAX_TRACE_ARGS) {
1017 ret = -E2BIG;
1018 goto out;
1019 }
1016 1020
1017 ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);1021 ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
1018 if (ret)1022 if (ret)
@@ -1029,7 +1033,7 @@ static int __trace_kprobe_create(int argc, const char *argv[]) · 10 unmodified lines
1029 }1033 }
1030 1034
1031 /* parse arguments */1035 /* parse arguments */
1032 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {1036 for (i = 0; i < argc; i++) {
1033 trace_probe_log_set_index(i + 2);1037 trace_probe_log_set_index(i + 2);
1034 ctx.offset = 0;1038 ctx.offset = 0;
1035 ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);1039 ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], &ctx);
kernel/trace/trace_uprobe.c+3−1
@@ -565,6 +565,8 @@ static int __trace_uprobe_create(int argc, const char **argv) · 564 unmodified lines
565 565
566 if (argc < 2)566 if (argc < 2)
567 return -ECANCELED;567 return -ECANCELED;
568 if (argc - 2 > MAX_TRACE_ARGS)
569 return -E2BIG;
568 570
569 if (argv[0][1] == ':')571 if (argv[0][1] == ':')
570 event = &argv[0][2];572 event = &argv[0][2];
@@ -690,7 +692,7 @@ static int __trace_uprobe_create(int argc, const char **argv) · 119 unmodified lines
690 tu->filename = filename;692 tu->filename = filename;
691 693
692 /* parse arguments */694 /* parse arguments */
693 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {695 for (i = 0; i < argc; i++) {
694 struct traceprobe_parse_context ctx = {696 struct traceprobe_parse_context ctx = {
695 .flags = (is_return ? TPARG_FL_RETURN : 0) | TPARG_FL_USER,697 .flags = (is_return ? TPARG_FL_RETURN : 0) | TPARG_FL_USER,
696 };698 };