]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
tracing: probe: Allocate traceprobe_parse_context from heap
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Wed, 23 Jul 2025 01:30:56 +0000 (10:30 +0900)
committerMasami Hiramatsu (Google) <mhiramat@kernel.org>
Wed, 23 Jul 2025 15:21:30 +0000 (00:21 +0900)
Instead of allocating traceprobe_parse_context on stack, allocate it
dynamically from heap (slab).

This change is likely intended to prevent potential stack overflow
issues, which can be a concern in the kernel environment where stack
space is limited.

Link: https://lore.kernel.org/all/175323425650.57270.280750740753792504.stgit@devnote2/
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202506240416.nZIhDXoO-lkp@intel.com/
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
kernel/trace/trace_eprobe.c
kernel/trace/trace_fprobe.c
kernel/trace/trace_kprobe.c
kernel/trace/trace_probe.h
kernel/trace/trace_uprobe.c

index 23e06712bead57bb07fc1abb1d42739a5a4fb532..7ba3a18be4c5623be74c93ce52bc9d0dac933fd3 100644 (file)
@@ -797,18 +797,20 @@ find_and_get_event(const char *system, const char *event_name)
 
 static int trace_eprobe_tp_update_arg(struct trace_eprobe *ep, const char *argv[], int i)
 {
-       struct traceprobe_parse_context ctx = {
-               .event = ep->event,
-               .flags = TPARG_FL_KERNEL | TPARG_FL_TEVENT,
-       };
+       struct traceprobe_parse_context *ctx __free(traceprobe_parse_context) = NULL;
        int ret;
 
-       ret = traceprobe_parse_probe_arg(&ep->tp, i, argv[i], &ctx);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+       ctx->event = ep->event;
+       ctx->flags = TPARG_FL_KERNEL | TPARG_FL_TEVENT;
+
+       ret = traceprobe_parse_probe_arg(&ep->tp, i, argv[i], ctx);
        /* Handle symbols "@" */
        if (!ret)
                ret = traceprobe_update_arg(&ep->tp.args[i]);
 
-       traceprobe_finish_parse(&ctx);
        return ret;
 }
 
index add08ffb04d7a053961afc8fd36d13c36dcc7bb1..610f8d53be8a214f58c3697c59506853f026e395 100644 (file)
@@ -1384,14 +1384,17 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
 
 static int trace_fprobe_create_cb(int argc, const char *argv[])
 {
-       struct traceprobe_parse_context ctx = {
-               .flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
-       };
+       struct traceprobe_parse_context *ctx __free(traceprobe_parse_context) = NULL;
        int ret;
 
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
+
        trace_probe_log_init("trace_fprobe", argc, argv);
-       ret = trace_fprobe_create_internal(argc, argv, &ctx);
-       traceprobe_finish_parse(&ctx);
+       ret = trace_fprobe_create_internal(argc, argv, ctx);
        trace_probe_log_clear();
        return ret;
 }
index cac128a5f7e008619033502a87746958eaa25e3e..d14b33e205f7f4aa198cac6553f96e96ce47b228 100644 (file)
@@ -1065,14 +1065,18 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
 
 static int trace_kprobe_create_cb(int argc, const char *argv[])
 {
-       struct traceprobe_parse_context ctx = { .flags = TPARG_FL_KERNEL };
+       struct traceprobe_parse_context *ctx __free(traceprobe_parse_context) = NULL;
        int ret;
 
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+       ctx->flags = TPARG_FL_KERNEL;
+
        trace_probe_log_init("trace_kprobe", argc, argv);
 
-       ret = trace_kprobe_create_internal(argc, argv, &ctx);
+       ret = trace_kprobe_create_internal(argc, argv, ctx);
 
-       traceprobe_finish_parse(&ctx);
        trace_probe_log_clear();
        return ret;
 }
index 7196048552793ef7d30ea558d1939d9f031bd4ba..842383fbc03b9c61a7eecf49177b1d48f87792fa 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/bitops.h>
 #include <linux/btf.h>
+#include <linux/cleanup.h>
 #include <linux/kprobes.h>
 #include <linux/limits.h>
 #include <linux/perf_event.h>
@@ -439,6 +440,14 @@ extern void traceprobe_free_probe_arg(struct probe_arg *arg);
  * this MUST be called for clean up the context and return a resource.
  */
 void traceprobe_finish_parse(struct traceprobe_parse_context *ctx);
+static inline void traceprobe_free_parse_ctx(struct traceprobe_parse_context *ctx)
+{
+       traceprobe_finish_parse(ctx);
+       kfree(ctx);
+}
+
+DEFINE_FREE(traceprobe_parse_context, struct traceprobe_parse_context *,
+       if (_T) traceprobe_free_parse_ctx(_T))
 
 extern int traceprobe_split_symbol_offset(char *symbol, long *offset);
 int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
index 3cc3404b09f0c51e52271f227c294a7645f270b4..872dce092e4636d6ecf90c4c66ffa48df5f53601 100644 (file)
@@ -695,13 +695,16 @@ static int __trace_uprobe_create(int argc, const char **argv)
 
        /* parse arguments */
        for (i = 0; i < argc; i++) {
-               struct traceprobe_parse_context ctx = {
-                       .flags = (is_return ? TPARG_FL_RETURN : 0) | TPARG_FL_USER,
-               };
+               struct traceprobe_parse_context *ctx __free(traceprobe_parse_context)
+                       = kzalloc(sizeof(*ctx), GFP_KERNEL);
 
+               if (!ctx) {
+                       ret = -ENOMEM;
+                       goto error;
+               }
+               ctx->flags = (is_return ? TPARG_FL_RETURN : 0) | TPARG_FL_USER;
                trace_probe_log_set_index(i + 2);
-               ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i], &ctx);
-               traceprobe_finish_parse(&ctx);
+               ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i], ctx);
                if (ret)
                        goto error;
        }