* [PATCH v2 1/6] tracing: probe: Allocate traceprobe_parse_context from heap
2025-07-20 6:21 [PATCH v2 0/6] tracing: probes: Use heap instead of stack for temporary buffers Masami Hiramatsu (Google)
@ 2025-07-20 6:21 ` Masami Hiramatsu (Google)
2025-07-21 17:19 ` Steven Rostedt
2025-07-20 6:21 ` [PATCH v2 2/6] tracing: fprobe-event: Allocate string buffers " Masami Hiramatsu (Google)
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-07-20 6:21 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
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.
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>
---
Changes in v2:
- Sort #include alphabetically.
- Just NULL check for freeing traceprobe_parse_context.
- Do not change the semantics of traceprobe_parse_context for uprobe
event. (alloc/free in loop)
---
kernel/trace/trace_eprobe.c | 14 ++++++++------
kernel/trace/trace_fprobe.c | 13 ++++++++-----
kernel/trace/trace_kprobe.c | 10 +++++++---
kernel/trace/trace_probe.h | 26 ++++++++++++++++++--------
kernel/trace/trace_uprobe.c | 13 ++++++++-----
5 files changed, 49 insertions(+), 27 deletions(-)
diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c
index 916555f0de81..1e18a8619b40 100644
--- a/kernel/trace/trace_eprobe.c
+++ b/kernel/trace/trace_eprobe.c
@@ -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;
}
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index dbf9d413125a..264cf7fc9a1d 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -1383,14 +1383,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;
}
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 3e5c47b6d7b2..15d7a381a128 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -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;
}
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 854e5668f5ee..842383fbc03b 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -10,20 +10,22 @@
* Author: Srikar Dronamraju
*/
+#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>
+#include <linux/ptrace.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/smp.h>
-#include <linux/tracefs.h>
-#include <linux/types.h>
#include <linux/string.h>
-#include <linux/ptrace.h>
-#include <linux/perf_event.h>
-#include <linux/kprobes.h>
#include <linux/stringify.h>
-#include <linux/limits.h>
+#include <linux/tracefs.h>
+#include <linux/types.h>
#include <linux/uaccess.h>
-#include <linux/bitops.h>
-#include <linux/btf.h>
+
#include <asm/bitsperlong.h>
#include "trace.h"
@@ -438,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,
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index f95a2c3d5b1b..797ac1250956 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -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;
}
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/6] tracing: probe: Allocate traceprobe_parse_context from heap
2025-07-20 6:21 ` [PATCH v2 1/6] tracing: probe: Allocate traceprobe_parse_context from heap Masami Hiramatsu (Google)
@ 2025-07-21 17:19 ` Steven Rostedt
2025-07-21 22:35 ` Masami Hiramatsu
0 siblings, 1 reply; 10+ messages in thread
From: Steven Rostedt @ 2025-07-21 17:19 UTC (permalink / raw)
To: Masami Hiramatsu (Google)
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
On Sun, 20 Jul 2025 15:21:47 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
>
> +#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>
> +#include <linux/ptrace.h>
> #include <linux/seq_file.h>
> #include <linux/slab.h>
> #include <linux/smp.h>
> -#include <linux/tracefs.h>
> -#include <linux/types.h>
> #include <linux/string.h>
> -#include <linux/ptrace.h>
> -#include <linux/perf_event.h>
> -#include <linux/kprobes.h>
> #include <linux/stringify.h>
> -#include <linux/limits.h>
> +#include <linux/tracefs.h>
> +#include <linux/types.h>
> #include <linux/uaccess.h>
> -#include <linux/bitops.h>
> -#include <linux/btf.h>
> +
A re-sort should be a separate patch, as I can't tell what changed in
the header for this patch.
-- Steve
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/6] tracing: probe: Allocate traceprobe_parse_context from heap
2025-07-21 17:19 ` Steven Rostedt
@ 2025-07-21 22:35 ` Masami Hiramatsu
0 siblings, 0 replies; 10+ messages in thread
From: Masami Hiramatsu @ 2025-07-21 22:35 UTC (permalink / raw)
To: Steven Rostedt; +Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
On Mon, 21 Jul 2025 13:19:07 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> On Sun, 20 Jul 2025 15:21:47 +0900
> "Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:
>
> >
> > +#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>
> > +#include <linux/ptrace.h>
> > #include <linux/seq_file.h>
> > #include <linux/slab.h>
> > #include <linux/smp.h>
> > -#include <linux/tracefs.h>
> > -#include <linux/types.h>
> > #include <linux/string.h>
> > -#include <linux/ptrace.h>
> > -#include <linux/perf_event.h>
> > -#include <linux/kprobes.h>
> > #include <linux/stringify.h>
> > -#include <linux/limits.h>
> > +#include <linux/tracefs.h>
> > +#include <linux/types.h>
> > #include <linux/uaccess.h>
> > -#include <linux/bitops.h>
> > -#include <linux/btf.h>
> > +
>
> A re-sort should be a separate patch, as I can't tell what changed in
> the header for this patch.
OK, let me make it a separate patch.
Thanks!
>
> -- Steve
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 2/6] tracing: fprobe-event: Allocate string buffers from heap
2025-07-20 6:21 [PATCH v2 0/6] tracing: probes: Use heap instead of stack for temporary buffers Masami Hiramatsu (Google)
2025-07-20 6:21 ` [PATCH v2 1/6] tracing: probe: Allocate traceprobe_parse_context from heap Masami Hiramatsu (Google)
@ 2025-07-20 6:21 ` Masami Hiramatsu (Google)
2025-07-20 6:22 ` [PATCH v2 3/6] tracing: kprobe-event: " Masami Hiramatsu (Google)
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-07-20 6:21 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Allocate temporary string buffers for fprobe-event from heap
instead of stack. This fixes the stack frame exceed limit error.
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>
---
kernel/trace/trace_fprobe.c | 39 ++++++++++++++++++++++++++-------------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index 264cf7fc9a1d..fd1036e27309 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -1234,18 +1234,18 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
* FETCHARG:TYPE : use TYPE instead of unsigned long.
*/
struct trace_fprobe *tf __free(free_trace_fprobe) = NULL;
- struct module *mod __free(module_put) = NULL;
- int i, new_argc = 0, ret = 0;
- bool is_return = false;
- char *symbol __free(kfree) = NULL;
const char *event = NULL, *group = FPROBE_EVENT_SYSTEM;
+ struct module *mod __free(module_put) = NULL;
const char **new_argv __free(kfree) = NULL;
- char buf[MAX_EVENT_NAME_LEN];
- char gbuf[MAX_EVENT_NAME_LEN];
- char sbuf[KSYM_NAME_LEN];
- char abuf[MAX_BTF_ARGS_LEN];
+ char *symbol __free(kfree) = NULL;
+ char *ebuf __free(kfree) = NULL;
+ char *gbuf __free(kfree) = NULL;
+ char *sbuf __free(kfree) = NULL;
+ char *abuf __free(kfree) = NULL;
char *dbuf __free(kfree) = NULL;
+ int i, new_argc = 0, ret = 0;
bool is_tracepoint = false;
+ bool is_return = false;
if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2)
return -ECANCELED;
@@ -1273,6 +1273,9 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
trace_probe_log_set_index(0);
if (event) {
+ gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!gbuf)
+ return -ENOMEM;
ret = traceprobe_parse_event_name(&event, &group, gbuf,
event - argv[0]);
if (ret)
@@ -1280,15 +1283,18 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
}
if (!event) {
+ ebuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!ebuf)
+ return -ENOMEM;
/* Make a new event name */
if (is_tracepoint)
- snprintf(buf, MAX_EVENT_NAME_LEN, "%s%s",
+ snprintf(ebuf, MAX_EVENT_NAME_LEN, "%s%s",
isdigit(*symbol) ? "_" : "", symbol);
else
- snprintf(buf, MAX_EVENT_NAME_LEN, "%s__%s", symbol,
+ snprintf(ebuf, MAX_EVENT_NAME_LEN, "%s__%s", symbol,
is_return ? "exit" : "entry");
- sanitize_event_name(buf);
- event = buf;
+ sanitize_event_name(ebuf);
+ event = ebuf;
}
if (is_return)
@@ -1304,13 +1310,20 @@ static int trace_fprobe_create_internal(int argc, const char *argv[],
ctx->flags |= TPARG_FL_TPOINT;
mod = NULL;
tpoint = find_tracepoint(symbol, &mod);
- if (tpoint)
+ if (tpoint) {
+ sbuf = kmalloc(KSYM_NAME_LEN, GFP_KERNEL);
+ if (!sbuf)
+ return -ENOMEM;
ctx->funcname = kallsyms_lookup((unsigned long)tpoint->probestub,
NULL, NULL, NULL, sbuf);
+ }
}
if (!ctx->funcname)
ctx->funcname = symbol;
+ abuf = kmalloc(MAX_BTF_ARGS_LEN, GFP_KERNEL);
+ if (!abuf)
+ return -ENOMEM;
argc -= 2; argv += 2;
new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,
abuf, MAX_BTF_ARGS_LEN, ctx);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 3/6] tracing: kprobe-event: Allocate string buffers from heap
2025-07-20 6:21 [PATCH v2 0/6] tracing: probes: Use heap instead of stack for temporary buffers Masami Hiramatsu (Google)
2025-07-20 6:21 ` [PATCH v2 1/6] tracing: probe: Allocate traceprobe_parse_context from heap Masami Hiramatsu (Google)
2025-07-20 6:21 ` [PATCH v2 2/6] tracing: fprobe-event: Allocate string buffers " Masami Hiramatsu (Google)
@ 2025-07-20 6:22 ` Masami Hiramatsu (Google)
2025-07-20 6:22 ` [PATCH v2 4/6] tracing: eprobe-event: " Masami Hiramatsu (Google)
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-07-20 6:22 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Allocate temporary string buffers for parsing kprobe-events
from heap instead of stack.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
kernel/trace/trace_kprobe.c | 39 +++++++++++++++++++++++++--------------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 15d7a381a128..793af6000f16 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -861,20 +861,20 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
* FETCHARG:TYPE : use TYPE instead of unsigned long.
*/
struct trace_kprobe *tk __free(free_trace_kprobe) = NULL;
+ const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
+ const char **new_argv __free(kfree) = NULL;
int i, len, new_argc = 0, ret = 0;
- bool is_return = false;
char *symbol __free(kfree) = NULL;
- char *tmp = NULL;
- const char **new_argv __free(kfree) = NULL;
- const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
+ char *ebuf __free(kfree) = NULL;
+ char *gbuf __free(kfree) = NULL;
+ char *abuf __free(kfree) = NULL;
+ char *dbuf __free(kfree) = NULL;
enum probe_print_type ptype;
+ bool is_return = false;
int maxactive = 0;
- long offset = 0;
void *addr = NULL;
- char buf[MAX_EVENT_NAME_LEN];
- char gbuf[MAX_EVENT_NAME_LEN];
- char abuf[MAX_BTF_ARGS_LEN];
- char *dbuf __free(kfree) = NULL;
+ char *tmp = NULL;
+ long offset = 0;
switch (argv[0][0]) {
case 'r':
@@ -893,6 +893,8 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
event++;
if (isdigit(argv[0][1])) {
+ char *buf __free(kfree) = NULL;
+
if (!is_return) {
trace_probe_log_err(1, BAD_MAXACT_TYPE);
return -EINVAL;
@@ -905,7 +907,7 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
trace_probe_log_err(1, BAD_MAXACT);
return -EINVAL;
}
- memcpy(buf, &argv[0][1], len);
+ buf = kmemdup(&argv[0][1], len + 1, GFP_KERNEL);
buf[len] = '\0';
ret = kstrtouint(buf, 0, &maxactive);
if (ret || !maxactive) {
@@ -973,6 +975,9 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
trace_probe_log_set_index(0);
if (event) {
+ gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!gbuf)
+ return -ENOMEM;
ret = traceprobe_parse_event_name(&event, &group, gbuf,
event - argv[0]);
if (ret)
@@ -981,16 +986,22 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
if (!event) {
/* Make a new event name */
+ ebuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!ebuf)
+ return -ENOMEM;
if (symbol)
- snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld",
+ snprintf(ebuf, MAX_EVENT_NAME_LEN, "%c_%s_%ld",
is_return ? 'r' : 'p', symbol, offset);
else
- snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p",
+ snprintf(ebuf, MAX_EVENT_NAME_LEN, "%c_0x%p",
is_return ? 'r' : 'p', addr);
- sanitize_event_name(buf);
- event = buf;
+ sanitize_event_name(ebuf);
+ event = ebuf;
}
+ abuf = kmalloc(MAX_BTF_ARGS_LEN, GFP_KERNEL);
+ if (!abuf)
+ return -ENOMEM;
argc -= 2; argv += 2;
ctx->funcname = symbol;
new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 4/6] tracing: eprobe-event: Allocate string buffers from heap
2025-07-20 6:21 [PATCH v2 0/6] tracing: probes: Use heap instead of stack for temporary buffers Masami Hiramatsu (Google)
` (2 preceding siblings ...)
2025-07-20 6:22 ` [PATCH v2 3/6] tracing: kprobe-event: " Masami Hiramatsu (Google)
@ 2025-07-20 6:22 ` Masami Hiramatsu (Google)
2025-07-21 17:23 ` Steven Rostedt
2025-07-20 6:22 ` [PATCH v2 5/6] tracing: uprobe-event: " Masami Hiramatsu (Google)
2025-07-20 6:22 ` [PATCH v2 6/6] tracing: probes: Add a kerneldoc for traceprobe_parse_event_name() Masami Hiramatsu (Google)
5 siblings, 1 reply; 10+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-07-20 6:22 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Allocate temporary string buffers for parsing eprobe-events
from heap instead of stack.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v2:
- Use new label for returning -ENOMEM.
- Sort #include alphabetically.
---
kernel/trace/trace_eprobe.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c
index 1e18a8619b40..f16a0ab0b001 100644
--- a/kernel/trace/trace_eprobe.c
+++ b/kernel/trace/trace_eprobe.c
@@ -9,14 +9,15 @@
* Copyright (C) 2021, VMware Inc, Tzvetomir Stoyanov tz.stoyanov@gmail.com>
*
*/
+#include <linux/cleanup.h>
+#include <linux/ftrace.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/ftrace.h>
#include "trace_dynevent.h"
#include "trace_probe.h"
-#include "trace_probe_tmpl.h"
#include "trace_probe_kernel.h"
+#include "trace_probe_tmpl.h"
#define EPROBE_EVENT_SYSTEM "eprobes"
@@ -871,10 +872,10 @@ static int __trace_eprobe_create(int argc, const char *argv[])
const char *event = NULL, *group = EPROBE_EVENT_SYSTEM;
const char *sys_event = NULL, *sys_name = NULL;
struct trace_event_call *event_call;
+ char *buf1 __free(kfree) = NULL;
+ char *buf2 __free(kfree) = NULL;
+ char *gbuf __free(kfree) = NULL;
struct trace_eprobe *ep = NULL;
- char buf1[MAX_EVENT_NAME_LEN];
- char buf2[MAX_EVENT_NAME_LEN];
- char gbuf[MAX_EVENT_NAME_LEN];
int ret = 0, filter_idx = 0;
int i, filter_cnt;
@@ -885,6 +886,9 @@ static int __trace_eprobe_create(int argc, const char *argv[])
event = strchr(&argv[0][1], ':');
if (event) {
+ gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!gbuf)
+ goto mem_error;
event++;
ret = traceprobe_parse_event_name(&event, &group, gbuf,
event - argv[0]);
@@ -894,6 +898,11 @@ static int __trace_eprobe_create(int argc, const char *argv[])
trace_probe_log_set_index(1);
sys_event = argv[1];
+
+ buf2 = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!buf2)
+ goto mem_error;
+
ret = traceprobe_parse_event_name(&sys_event, &sys_name, buf2, 0);
if (ret || !sys_event || !sys_name) {
trace_probe_log_err(0, NO_EVENT_INFO);
@@ -901,7 +910,9 @@ static int __trace_eprobe_create(int argc, const char *argv[])
}
if (!event) {
- strscpy(buf1, sys_event, MAX_EVENT_NAME_LEN);
+ buf1 = kstrdup(sys_event, GFP_KERNEL);
+ if (!buf1)
+ goto mem_error;
event = buf1;
}
@@ -974,6 +985,9 @@ static int __trace_eprobe_create(int argc, const char *argv[])
trace_probe_log_clear();
return ret;
+mem_error:
+ ret = -ENOMEM;
+ goto error;
parse_error:
ret = -EINVAL;
error:
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 5/6] tracing: uprobe-event: Allocate string buffers from heap
2025-07-20 6:21 [PATCH v2 0/6] tracing: probes: Use heap instead of stack for temporary buffers Masami Hiramatsu (Google)
` (3 preceding siblings ...)
2025-07-20 6:22 ` [PATCH v2 4/6] tracing: eprobe-event: " Masami Hiramatsu (Google)
@ 2025-07-20 6:22 ` Masami Hiramatsu (Google)
2025-07-20 6:22 ` [PATCH v2 6/6] tracing: probes: Add a kerneldoc for traceprobe_parse_event_name() Masami Hiramatsu (Google)
5 siblings, 0 replies; 10+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-07-20 6:22 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Allocate temporary string buffers for parsing uprobe-events
from heap instead of stack.
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v2:
- Sort #include alphabetically.
- Add fail_mem label for handling ENOMEM error.
---
kernel/trace/trace_uprobe.c | 40 +++++++++++++++++++++++++---------------
1 file changed, 25 insertions(+), 15 deletions(-)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 797ac1250956..8b0bcc0d8f41 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -8,17 +8,19 @@
#define pr_fmt(fmt) "trace_uprobe: " fmt
#include <linux/bpf-cgroup.h>
-#include <linux/security.h>
+#include <linux/cleanup.h>
#include <linux/ctype.h>
+#include <linux/filter.h>
#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/uprobes.h>
#include <linux/namei.h>
-#include <linux/string.h>
-#include <linux/rculist.h>
-#include <linux/filter.h>
#include <linux/percpu.h>
+#include <linux/rculist.h>
+#include <linux/security.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/uprobes.h>
+#include "trace.h"
#include "trace_dynevent.h"
#include "trace_probe.h"
#include "trace_probe_tmpl.h"
@@ -537,15 +539,15 @@ static int register_trace_uprobe(struct trace_uprobe *tu)
*/
static int __trace_uprobe_create(int argc, const char **argv)
{
- struct trace_uprobe *tu;
const char *event = NULL, *group = UPROBE_EVENT_SYSTEM;
char *arg, *filename, *rctr, *rctr_end, *tmp;
- char buf[MAX_EVENT_NAME_LEN];
- char gbuf[MAX_EVENT_NAME_LEN];
- enum probe_print_type ptype;
- struct path path;
unsigned long offset, ref_ctr_offset;
+ char *gbuf __free(kfree) = NULL;
+ char *buf __free(kfree) = NULL;
+ enum probe_print_type ptype;
+ struct trace_uprobe *tu;
bool is_return = false;
+ struct path path;
int i, ret;
ref_ctr_offset = 0;
@@ -653,6 +655,10 @@ static int __trace_uprobe_create(int argc, const char **argv)
/* setup a probe */
trace_probe_log_set_index(0);
if (event) {
+ gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!gbuf)
+ goto fail_mem;
+
ret = traceprobe_parse_event_name(&event, &group, gbuf,
event - argv[0]);
if (ret)
@@ -664,15 +670,16 @@ static int __trace_uprobe_create(int argc, const char **argv)
char *ptr;
tail = kstrdup(kbasename(filename), GFP_KERNEL);
- if (!tail) {
- ret = -ENOMEM;
- goto fail_address_parse;
- }
+ if (!tail)
+ goto fail_mem;
ptr = strpbrk(tail, ".-_");
if (ptr)
*ptr = '\0';
+ buf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
+ if (!buf)
+ goto fail_mem;
snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail, offset);
event = buf;
kfree(tail);
@@ -724,6 +731,9 @@ static int __trace_uprobe_create(int argc, const char **argv)
trace_probe_log_clear();
return ret;
+fail_mem:
+ ret = -ENOMEM;
+
fail_address_parse:
trace_probe_log_clear();
path_put(&path);
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 6/6] tracing: probes: Add a kerneldoc for traceprobe_parse_event_name()
2025-07-20 6:21 [PATCH v2 0/6] tracing: probes: Use heap instead of stack for temporary buffers Masami Hiramatsu (Google)
` (4 preceding siblings ...)
2025-07-20 6:22 ` [PATCH v2 5/6] tracing: uprobe-event: " Masami Hiramatsu (Google)
@ 2025-07-20 6:22 ` Masami Hiramatsu (Google)
5 siblings, 0 replies; 10+ messages in thread
From: Masami Hiramatsu (Google) @ 2025-07-20 6:22 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu
Cc: Mathieu Desnoyers, linux-kernel, linux-trace-kernel
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Since traceprobe_parse_event_name() is a bit complicated, add a
kerneldoc for explaining the behavior.
Suggested-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
kernel/trace/trace_probe.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c
index abfab8957a6c..72bf430a3804 100644
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -247,7 +247,22 @@ int traceprobe_split_symbol_offset(char *symbol, long *offset)
return 0;
}
-/* @buf must has MAX_EVENT_NAME_LEN size */
+/**
+ * traceprobe_parse_event_name - Parse a string into group and event names
+ * @pevent: A pointer to the string to be parsed. On return, this is updated
+ * to point to the event name part of the string.
+ * @pgroup: A pointer to the group name. This is updated to point to the parsed
+ * group name, which is stored in @buf.
+ * @buf: A buffer to store the parsed group name.
+ * @offset: The offset of the string in the original user command, for logging.
+ *
+ * Description: This parses a string with the format `[GROUP/][EVENT]` or
+ * `[GROUP.][EVENT]` (either GROUP or EVENT or both must be specified).
+ * The parsed group name is stored in @buf.
+ * The caller must ensure @buf is at least MAX_EVENT_NAME_LEN bytes.
+ *
+ * Return: 0 on success, or -EINVAL on failure.
+ */
int traceprobe_parse_event_name(const char **pevent, const char **pgroup,
char *buf, int offset)
{
^ permalink raw reply related [flat|nested] 10+ messages in thread