tracing: kprobe-event: Allocate string buffers from heap

Allocate temporary string buffers for parsing kprobe-events
from heap instead of stack.

Link: https://lore.kernel.org/all/175323427627.57270.5105357260879695051.stgit@devnote2/

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
Masami Hiramatsu (Google) 2025-07-23 10:31:16 +09:00
parent d643eaa708
commit 33b4e38baa

View file

@ -861,20 +861,20 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
* FETCHARG:TYPE : use TYPE instead of unsigned long. * FETCHARG:TYPE : use TYPE instead of unsigned long.
*/ */
struct trace_kprobe *tk __free(free_trace_kprobe) = NULL; struct trace_kprobe *tk __free(free_trace_kprobe) = 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; const char *event = NULL, *group = KPROBE_EVENT_SYSTEM;
enum probe_print_type ptype; const char **new_argv __free(kfree) = NULL;
int maxactive = 0; int i, len, new_argc = 0, ret = 0;
long offset = 0; char *symbol __free(kfree) = NULL;
void *addr = NULL; char *ebuf __free(kfree) = NULL;
char buf[MAX_EVENT_NAME_LEN]; char *gbuf __free(kfree) = NULL;
char gbuf[MAX_EVENT_NAME_LEN]; char *abuf __free(kfree) = NULL;
char abuf[MAX_BTF_ARGS_LEN];
char *dbuf __free(kfree) = NULL; char *dbuf __free(kfree) = NULL;
enum probe_print_type ptype;
bool is_return = false;
int maxactive = 0;
void *addr = NULL;
char *tmp = NULL;
long offset = 0;
switch (argv[0][0]) { switch (argv[0][0]) {
case 'r': case 'r':
@ -893,6 +893,8 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
event++; event++;
if (isdigit(argv[0][1])) { if (isdigit(argv[0][1])) {
char *buf __free(kfree) = NULL;
if (!is_return) { if (!is_return) {
trace_probe_log_err(1, BAD_MAXACT_TYPE); trace_probe_log_err(1, BAD_MAXACT_TYPE);
return -EINVAL; return -EINVAL;
@ -905,7 +907,7 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
trace_probe_log_err(1, BAD_MAXACT); trace_probe_log_err(1, BAD_MAXACT);
return -EINVAL; return -EINVAL;
} }
memcpy(buf, &argv[0][1], len); buf = kmemdup(&argv[0][1], len + 1, GFP_KERNEL);
buf[len] = '\0'; buf[len] = '\0';
ret = kstrtouint(buf, 0, &maxactive); ret = kstrtouint(buf, 0, &maxactive);
if (ret || !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); trace_probe_log_set_index(0);
if (event) { if (event) {
gbuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
if (!gbuf)
return -ENOMEM;
ret = traceprobe_parse_event_name(&event, &group, gbuf, ret = traceprobe_parse_event_name(&event, &group, gbuf,
event - argv[0]); event - argv[0]);
if (ret) if (ret)
@ -981,16 +986,22 @@ static int trace_kprobe_create_internal(int argc, const char *argv[],
if (!event) { if (!event) {
/* Make a new event name */ /* Make a new event name */
ebuf = kmalloc(MAX_EVENT_NAME_LEN, GFP_KERNEL);
if (!ebuf)
return -ENOMEM;
if (symbol) 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); is_return ? 'r' : 'p', symbol, offset);
else else
snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p", snprintf(ebuf, MAX_EVENT_NAME_LEN, "%c_0x%p",
is_return ? 'r' : 'p', addr); is_return ? 'r' : 'p', addr);
sanitize_event_name(buf); sanitize_event_name(ebuf);
event = buf; event = ebuf;
} }
abuf = kmalloc(MAX_BTF_ARGS_LEN, GFP_KERNEL);
if (!abuf)
return -ENOMEM;
argc -= 2; argv += 2; argc -= 2; argv += 2;
ctx->funcname = symbol; ctx->funcname = symbol;
new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc, new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,