From eadc0725ab8d38c05148fce49f8d5c6a0e01f062 Mon Sep 17 00:00:00 2001 From: Mykyta Yatsenko Date: Mon, 18 May 2026 08:23:16 -0700 Subject: tracing: Expose tracepoint BTF ids via tracefs Add events///btf_ids, a per-template file that exposes the BTF ids resolve_btfids fills in for each tracepoint: btf_obj_id BTF object owning the ids below raw_btf_id FUNC_PROTO of __bpf_trace_ (named args), consumed by raw_tp / tp_btf BPF programs tp_btf_id trace_event_raw_ ring-buffer record, consumed by classic BPF_PROG_TYPE_TRACEPOINT programs DECLARE_EVENT_CLASS now emits a 2-entry BTF_ID_LIST (FUNC __bpf_trace_* and STRUCT trace_event_raw_*) and stores the pointer in trace_event_class. Per-syscall events under syscalls/ share the handcrafted classes event_class_syscall_{enter,exit} instead of going through DECLARE_EVENT_CLASS. Wire those classes to the BTF id lists generated for sys_enter / sys_exit so all ~700 per-syscall events expose the shared dispatcher prototype and record. The per-syscall events do not own their own tracepoint (they share sys_enter/sys_exit), so raw_btf_id is reported as 0 on those events; the meaningful raw_btf_id is exposed on raw_syscalls/sys_{enter,exit}/btf_ids where raw_tp / tp_btf programs can actually attach. Link: https://patch.msgid.link/20260518-generic_tracepoint-v2-2-b755a5cf67bb@meta.com Signed-off-by: Mykyta Yatsenko Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 80 ++++++++++++++++++++++++++++++++++++++++++- kernel/trace/trace_syscalls.c | 17 +++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 956692856fa8..e0449e648871 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -2202,6 +2203,61 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) } #endif +#ifdef CONFIG_BPF_EVENTS +static ssize_t +event_btf_ids_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) +{ + struct trace_event_file *file; + struct trace_event_call *call; + const struct btf_type *t; + struct module *mod = NULL; + u32 raw_id = 0, tp_id = 0, obj_id = 0; + const u32 *ids; + struct btf *btf; + char buf[128]; + int len; + + /* Module unload could free call->class and ids[] mid-read. */ + scoped_guard(mutex, &event_mutex) { + file = event_file_file(filp); + if (!file) + return -ENODEV; + + call = file->event_call; + ids = call->class->btf_ids; + if (!ids) + return -ENOENT; + if (!(call->flags & TRACE_EVENT_FL_DYNAMIC)) + mod = (struct module *)call->module; + + btf = btf_get_module_btf(mod); + if (IS_ERR_OR_NULL(btf)) + return -ENOENT; + + /* Module-local ids in ids[] need base+local relocation. */ + tp_id = btf_relocate_id(btf, ids[1]); + + /* + * Without FL_TRACEPOINT the dispatcher is shared (e.g. all + * per-syscall events fan out from __bpf_trace_sys_enter), so + * raw_btf_id has no per-event attach point — report 0. + */ + if (call->flags & TRACE_EVENT_FL_TRACEPOINT) { + t = btf_type_by_id(btf, btf_relocate_id(btf, ids[0])); + raw_id = t ? t->type : 0; + } + obj_id = btf_obj_id(btf); + btf_put(btf); + } + + len = scnprintf(buf, sizeof(buf), + "btf_obj_id: %u\nraw_btf_id: %u\ntp_btf_id: %u\n", + obj_id, raw_id, tp_id); + + return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); +} +#endif + static ssize_t event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) @@ -2702,6 +2758,13 @@ static const struct file_operations ftrace_event_id_fops = { }; #endif +#ifdef CONFIG_BPF_EVENTS +static const struct file_operations ftrace_event_btf_ids_fops = { + .read = event_btf_ids_read, + .llseek = default_llseek, +}; +#endif + static const struct file_operations ftrace_event_filter_fops = { .open = tracing_open_file_tr, .read = event_filter_read, @@ -3095,6 +3158,14 @@ static int event_callback(const char *name, umode_t *mode, void **data, } #endif +#ifdef CONFIG_BPF_EVENTS + if (call->class->btf_ids && strcmp(name, "btf_ids") == 0) { + *mode = TRACE_MODE_READ; + *fops = &ftrace_event_btf_ids_fops; + return 1; + } +#endif + #ifdef CONFIG_HIST_TRIGGERS if (strcmp(name, "hist") == 0) { *mode = TRACE_MODE_READ; @@ -3149,7 +3220,14 @@ event_create_dir(struct eventfs_inode *parent, struct trace_event_file *file) .callback = event_callback, }, #endif -#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS)) +#ifdef CONFIG_BPF_EVENTS + { + .name = "btf_ids", + .callback = event_callback, + }, +#endif +#define NR_RO_EVENT_ENTRIES (1 + IS_ENABLED(CONFIG_PERF_EVENTS) + \ + IS_ENABLED(CONFIG_BPF_EVENTS)) /* Readonly files must be above this line and counted by NR_RO_EVENT_ENTRIES. */ { .name = "enable", diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 8a4f3c75e39f..48ef1a93e576 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -1303,12 +1303,26 @@ struct trace_event_functions exit_syscall_print_funcs = { .trace = print_syscall_exit, }; +#ifdef CONFIG_BPF_EVENTS +/* + * BTF id lists generated by DECLARE_EVENT_CLASS for the sys_enter and + * sys_exit tracepoints. The auto-generated event_class_sys_{enter,exit} + * is unused (per-syscall events share the handcrafted classes below), + * but the id lists themselves are global and reusable. + */ +extern u32 __bpf_trace_btf_ids_sys_enter[]; +extern u32 __bpf_trace_btf_ids_sys_exit[]; +#endif + struct trace_event_class __refdata event_class_syscall_enter = { .system = "syscalls", .reg = syscall_enter_register, .fields_array = syscall_enter_fields_array, .get_fields = syscall_get_enter_fields, .raw_init = init_syscall_trace, +#ifdef CONFIG_BPF_EVENTS + .btf_ids = __bpf_trace_btf_ids_sys_enter, +#endif }; struct trace_event_class __refdata event_class_syscall_exit = { @@ -1321,6 +1335,9 @@ struct trace_event_class __refdata event_class_syscall_exit = { }, .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields), .raw_init = init_syscall_trace, +#ifdef CONFIG_BPF_EVENTS + .btf_ids = __bpf_trace_btf_ids_sys_exit, +#endif }; unsigned long __init __weak arch_syscall_addr(int nr) -- cgit v1.2.3 From 8432a8772bea4e0c142118421b89eaee3d5b2332 Mon Sep 17 00:00:00 2001 From: Yu Peng Date: Wed, 27 May 2026 10:34:50 +0800 Subject: tracing: Point constant hist field type to string literal The HIST_FIELD_FL_CONST path uses the fixed "u64" type string. Point hist_field->type directly to the string literal, matching the HIST_FIELD_FL_HITCOUNT path. The release path already uses kfree_const(), so no duplication is needed. Link: https://patch.msgid.link/20260527023450.2137639-1-pengyu@kylinos.cn Signed-off-by: Yu Peng Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 58d28cd1afa3..a335006923ec 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1984,9 +1984,7 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data, if (flags & HIST_FIELD_FL_CONST) { hist_field->fn_num = HIST_FIELD_FN_CONST; hist_field->size = sizeof(u64); - hist_field->type = kstrdup("u64", GFP_KERNEL); - if (!hist_field->type) - goto free; + hist_field->type = "u64"; goto out; } -- cgit v1.2.3 From b11d9af16d526a9e56382d6b0a3f09e2c2298981 Mon Sep 17 00:00:00 2001 From: David Laight Date: Sat, 6 Jun 2026 21:26:28 +0100 Subject: kernel/trace/trace_printk: Use kstrdup() instead of kmalloc() and strcpy() Link: https://patch.msgid.link/20260606202633.5018-34-david.laight.linux@gmail.com Signed-off-by: David Laight Reviewed-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_printk.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 3ea17af60169..98171a2398e4 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c @@ -71,10 +71,9 @@ void hold_module_trace_bprintk_format(const char **start, const char **end) fmt = NULL; tb_fmt = kmalloc_obj(*tb_fmt); if (tb_fmt) { - fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL); + fmt = kstrdup(*iter, GFP_KERNEL); if (fmt) { list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); - strcpy(fmt, *iter); tb_fmt->fmt = fmt; } else kfree(tb_fmt); -- cgit v1.2.3 From 988995c0552b6213b6bf16cea57258d4842c1488 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Thu, 11 Jun 2026 13:59:43 +0800 Subject: tracing: Use __free() for expr_str() buffer expr_str() allocates a temporary expression buffer and manually frees it on some error paths. Convert the buffer to __free(kfree) and return it with return_ptr() on success. This keeps ownership handling separate from the later ERR_PTR() conversion and string-bound change. Link: https://patch.msgid.link/20260611055945.22348-2-pengpeng@iscas.ac.cn Signed-off-by: Pengpeng Hou Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index a335006923ec..40ae7379cbf5 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1759,7 +1759,7 @@ static void expr_field_str(struct hist_field *field, char *expr) static char *expr_str(struct hist_field *field, unsigned int level) { - char *expr; + char *expr __free(kfree) = NULL; if (level > 1) return NULL; @@ -1770,7 +1770,7 @@ static char *expr_str(struct hist_field *field, unsigned int level) if (!field->operands[0]) { expr_field_str(field, expr); - return expr; + return_ptr(expr); } if (field->operator == FIELD_OP_UNARY_MINUS) { @@ -1778,16 +1778,15 @@ static char *expr_str(struct hist_field *field, unsigned int level) strcat(expr, "-("); subexpr = expr_str(field->operands[0], ++level); - if (!subexpr) { - kfree(expr); + if (!subexpr) return NULL; - } + strcat(expr, subexpr); strcat(expr, ")"); kfree(subexpr); - return expr; + return_ptr(expr); } expr_field_str(field->operands[0], expr); @@ -1806,13 +1805,12 @@ static char *expr_str(struct hist_field *field, unsigned int level) strcat(expr, "*"); break; default: - kfree(expr); return NULL; } expr_field_str(field->operands[1], expr); - return expr; + return_ptr(expr); } /* -- cgit v1.2.3 From a5ca27e8ff1c10e949af7cfe474d6d1a08fb5601 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Thu, 11 Jun 2026 13:59:44 +0800 Subject: tracing: Return ERR_PTR() from expr_str() expr_str() currently reports all failure cases as NULL, so callers cannot distinguish invalid recursion depth from allocation failure or later string construction errors. Return ERR_PTR()-encoded errors from expr_str() and make parse_unary() and parse_expr() propagate them. Clear expr->name before destroying the hist field so the error pointer is not freed as a string. Link: https://patch.msgid.link/20260611055945.22348-3-pengpeng@iscas.ac.cn Signed-off-by: Pengpeng Hou Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 40ae7379cbf5..dee2710da66e 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1762,11 +1762,11 @@ static char *expr_str(struct hist_field *field, unsigned int level) char *expr __free(kfree) = NULL; if (level > 1) - return NULL; + return ERR_PTR(-EINVAL); expr = kzalloc(MAX_FILTER_STR_VAL, GFP_KERNEL); if (!expr) - return NULL; + return ERR_PTR(-ENOMEM); if (!field->operands[0]) { expr_field_str(field, expr); @@ -1778,8 +1778,8 @@ static char *expr_str(struct hist_field *field, unsigned int level) strcat(expr, "-("); subexpr = expr_str(field->operands[0], ++level); - if (!subexpr) - return NULL; + if (IS_ERR(subexpr)) + return subexpr; strcat(expr, subexpr); strcat(expr, ")"); @@ -1805,7 +1805,7 @@ static char *expr_str(struct hist_field *field, unsigned int level) strcat(expr, "*"); break; default: - return NULL; + return ERR_PTR(-EINVAL); } expr_field_str(field->operands[1], expr); @@ -2622,6 +2622,11 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data, expr->is_signed = operand1->is_signed; expr->operator = FIELD_OP_UNARY_MINUS; expr->name = expr_str(expr, 0); + if (IS_ERR(expr->name)) { + ret = PTR_ERR(expr->name); + expr->name = NULL; + goto free; + } expr->type = kstrdup_const(operand1->type, GFP_KERNEL); if (!expr->type) { ret = -ENOMEM; @@ -2834,6 +2839,11 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data, destroy_hist_field(operand1, 0); expr->name = expr_str(expr, 0); + if (IS_ERR(expr->name)) { + ret = PTR_ERR(expr->name); + expr->name = NULL; + goto free_expr; + } } else { /* The operand sizes should be the same, so just pick one */ expr->size = operand1->size; @@ -2847,6 +2857,11 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data, } expr->name = expr_str(expr, 0); + if (IS_ERR(expr->name)) { + ret = PTR_ERR(expr->name); + expr->name = NULL; + goto free_expr; + } } return expr; -- cgit v1.2.3 From 935601a4276f28105498609f7f98aa66e86e9c96 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Thu, 11 Jun 2026 13:59:45 +0800 Subject: tracing: Bound histogram expression strings with seq_buf expr_str() allocates a fixed MAX_FILTER_STR_VAL buffer and then builds expression names with a series of raw strcat() appends. Nested operands, constants, field flags, and generated field names can push the rendered string past that fixed limit before the name is attached to the hist field. Build expression strings with seq_buf and return -E2BIG when the rendered name would exceed MAX_FILTER_STR_VAL. This keeps the existing tracing-side limit while replacing the raw append logic with bounded construction. Link: https://patch.msgid.link/20260611055945.22348-4-pengpeng@iscas.ac.cn Signed-off-by: Pengpeng Hou Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_hist.c | 57 +++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 24 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index dee2710da66e..893bd8b0e48a 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -94,7 +94,6 @@ typedef u64 (*hist_field_fn_t) (struct hist_field *field, #define HIST_FIELD_OPERANDS_MAX 2 #define HIST_FIELDS_MAX (TRACING_MAP_FIELDS_MAX + TRACING_MAP_VARS_MAX) #define HIST_ACTIONS_MAX 8 -#define HIST_CONST_DIGITS_MAX 21 #define HIST_DIV_SHIFT 20 /* For optimizing division by constants */ enum field_op_id { @@ -1733,33 +1732,36 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) return flags_str; } -static void expr_field_str(struct hist_field *field, char *expr) +static bool expr_field_str(struct hist_field *field, struct seq_buf *s) { + const char *field_name; + if (field->flags & HIST_FIELD_FL_VAR_REF) { if (!field->system) - strcat(expr, "$"); - } else if (field->flags & HIST_FIELD_FL_CONST) { - char str[HIST_CONST_DIGITS_MAX]; + seq_buf_putc(s, '$'); + } else if (field->flags & HIST_FIELD_FL_CONST) + seq_buf_printf(s, "%llu", field->constant); - snprintf(str, HIST_CONST_DIGITS_MAX, "%llu", field->constant); - strcat(expr, str); - } + field_name = hist_field_name(field, 0); + if (!field_name) + return false; - strcat(expr, hist_field_name(field, 0)); + seq_buf_puts(s, field_name); if (field->flags && !(field->flags & HIST_FIELD_FL_VAR_REF)) { const char *flags_str = get_hist_field_flags(field); - if (flags_str) { - strcat(expr, "."); - strcat(expr, flags_str); - } + if (flags_str) + seq_buf_printf(s, ".%s", flags_str); } + + return !seq_buf_has_overflowed(s); } static char *expr_str(struct hist_field *field, unsigned int level) { char *expr __free(kfree) = NULL; + struct seq_buf s; if (level > 1) return ERR_PTR(-EINVAL); @@ -1768,47 +1770,54 @@ static char *expr_str(struct hist_field *field, unsigned int level) if (!expr) return ERR_PTR(-ENOMEM); + seq_buf_init(&s, expr, MAX_FILTER_STR_VAL); + if (!field->operands[0]) { - expr_field_str(field, expr); + if (!expr_field_str(field, &s)) + return ERR_PTR(-E2BIG); + return_ptr(expr); } if (field->operator == FIELD_OP_UNARY_MINUS) { char *subexpr; - strcat(expr, "-("); subexpr = expr_str(field->operands[0], ++level); if (IS_ERR(subexpr)) return subexpr; - strcat(expr, subexpr); - strcat(expr, ")"); - + seq_buf_printf(&s, "-(%s)", subexpr); kfree(subexpr); + if (seq_buf_has_overflowed(&s)) + return ERR_PTR(-E2BIG); + return_ptr(expr); } - expr_field_str(field->operands[0], expr); + if (!expr_field_str(field->operands[0], &s)) + return ERR_PTR(-E2BIG); switch (field->operator) { case FIELD_OP_MINUS: - strcat(expr, "-"); + seq_buf_putc(&s, '-'); break; case FIELD_OP_PLUS: - strcat(expr, "+"); + seq_buf_putc(&s, '+'); break; case FIELD_OP_DIV: - strcat(expr, "/"); + seq_buf_putc(&s, '/'); break; case FIELD_OP_MULT: - strcat(expr, "*"); + seq_buf_putc(&s, '*'); break; default: return ERR_PTR(-EINVAL); } - expr_field_str(field->operands[1], expr); + if (seq_buf_has_overflowed(&s) || + !expr_field_str(field->operands[1], &s)) + return ERR_PTR(-E2BIG); return_ptr(expr); } -- cgit v1.2.3 From 6e6179ad9485dc8395a979ec60d131c90c7e5fb0 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 22 Jun 2026 16:37:18 +0200 Subject: tracing/user_events: Use seq_putc() in two functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single characters should be put into a sequence. Thus use the corresponding function “seq_putc” for selected calls. The source code was transformed by using the Coccinelle software. Link: https://patch.msgid.link/6bcaa4da-05c6-4097-90f5-3969f8a1dfbc@web.de Signed-off-by: Markus Elfring Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_user.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index 8c82ecb735f4..b3f409d1b19f 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -1838,7 +1838,7 @@ static int user_event_show(struct seq_file *m, struct dyn_event *ev) list_for_each_entry_reverse(field, head, link) { if (depth == 0) - seq_puts(m, " "); + seq_putc(m, ' '); else seq_puts(m, "; "); @@ -1850,7 +1850,7 @@ static int user_event_show(struct seq_file *m, struct dyn_event *ev) depth++; } - seq_puts(m, "\n"); + seq_putc(m, '\n'); return 0; } @@ -2819,13 +2819,13 @@ static int user_seq_show(struct seq_file *m, void *p) busy++; } - seq_puts(m, "\n"); + seq_putc(m, '\n'); active++; } mutex_unlock(&group->reg_mutex); - seq_puts(m, "\n"); + seq_putc(m, '\n'); seq_printf(m, "Active: %d\n", active); seq_printf(m, "Busy: %d\n", busy); -- cgit v1.2.3 From 0ac2611f1030a960d2ff76dd0561c2549adfd06c Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 22 Jun 2026 16:42:07 +0200 Subject: tracing/user_events: Replace a seq_printf() call by seq_puts() in user_seq_show() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A single string should be put into a sequence within a loop. Thus use the corresponding function “seq_puts” for one selected call. The source code was transformed by using the Coccinelle software. Link: https://patch.msgid.link/1cf327f0-49a6-477f-a06f-2b22a167db24@web.de Signed-off-by: Markus Elfring Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c index b3f409d1b19f..2bbc89d4a266 100644 --- a/kernel/trace/trace_events_user.c +++ b/kernel/trace/trace_events_user.c @@ -2806,7 +2806,7 @@ static int user_seq_show(struct seq_file *m, void *p) hash_for_each(group->register_table, i, user, node) { status = user->status; - seq_printf(m, "%s", EVENT_TP_NAME(user)); + seq_puts(m, EVENT_TP_NAME(user)); if (status != 0) { seq_puts(m, " # Used by"); -- cgit v1.2.3 From 73301fb81a17dbf198a5bf6cdaefa3611232b88e Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 26 Jun 2026 09:24:18 +0200 Subject: fgraph: Use trace_seq_putc() in print_graph_return() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A single closing curly bracket should be put into a trace sequence buffer. Thus use the corresponding function “trace_seq_putc”. The source code was transformed by using the Coccinelle software. Link: https://patch.msgid.link/d215fa89-9a62-4067-86ec-833290f35c80@web.de Signed-off-by: Markus Elfring Signed-off-by: Steven Rostedt --- kernel/trace/trace_functions_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 0d2d3a2ea7dd..ff7cb1a76b95 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -1349,7 +1349,7 @@ print_graph_return(struct ftrace_graph_ret_entry *retentry, struct trace_seq *s, * that if the funcgraph-tail option is enabled. */ if (func_match && !(flags & TRACE_GRAPH_PRINT_TAIL)) - trace_seq_puts(s, "}"); + trace_seq_putc(s, '}'); else trace_seq_printf(s, "} /* %ps */", (void *)func); } -- cgit v1.2.3 From 693dc27c5286cb0fd0d8cf18c3ee924b22154e92 Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Sun, 28 Jun 2026 13:10:22 +0000 Subject: tracing: Reject invalid preemptirq_delay_test CPU affinity preemptirq_delay_test accepts cpu_affinity as a module parameter and, when it is non-negative, writes that CPU directly into a temporary cpumask from the worker thread. Values outside nr_cpu_ids can set a bit outside the allocated cpumask before the test reports a normal affinity error. Validate the requested CPU in preemptirq_delay_run() before setting it in the temporary cpumask. Invalid affinity requests are reported by the test thread and skipped before cpumask_set_cpu() can touch an out-of-range bit. Link: https://patch.msgid.link/20260628131021.2208632.6a5c6c959813.preemptirq-delay-test-invalid-cpu-affinity@trailofbits.com Assisted-by: Codex:gpt-5.5-cyber-preview Signed-off-by: Samuel Moelius Signed-off-by: Steven Rostedt --- kernel/trace/preemptirq_delay_test.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'kernel/trace') diff --git a/kernel/trace/preemptirq_delay_test.c b/kernel/trace/preemptirq_delay_test.c index acb0c971a408..69e5238737ed 100644 --- a/kernel/trace/preemptirq_delay_test.c +++ b/kernel/trace/preemptirq_delay_test.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -123,6 +124,13 @@ static int preemptirq_delay_run(void *data) return -ENOMEM; if (cpu_affinity > -1) { + unsigned int cpu = cpu_affinity; + + if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) { + pr_err("cpu_affinity:%d, invalid CPU\n", cpu_affinity); + goto out; + } + cpumask_clear(cpu_mask); cpumask_set_cpu(cpu_affinity, cpu_mask); if (set_cpus_allowed_ptr(current, cpu_mask)) @@ -132,6 +140,7 @@ static int preemptirq_delay_run(void *data) for (i = 0; i < s; i++) (testfuncs[i])(i); +out: complete(&done); set_current_state(TASK_INTERRUPTIBLE); -- cgit v1.2.3 From b5cc230af5e536ff752f8bd5c30e23612936d5c3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 30 Jun 2026 18:48:36 -0400 Subject: tracing: Warn when an event dereferences a pointer in TP_printk() Currently on boot up and when modules are loaded, the trace event infrastructure will examine the TP_printk's of every event looking to see if it dereferences pointers on the ring buffer via printk formats like "%pB" and such. What it doesn't do is check if the arguments themselves do a dereference from a pointer. This was brought with a fix[1] to the fsl_edma event that had in the arguments of the TP_printk(): "__entry->edma->membase" The __entry->edma is a pointer saved in the ring buffer. The dereference from TP_printk() happens when the user reads the "trace" file which can be seconds, minutes, hours, days, weeks, or even months later! There is no guarantee that the __entry->edma pointer will still be pointing to what it was when it was recorded, and could crash the kernel when a user reads the event. Add logic to the test_event_printk() that also checks for this case and warn if the event dereferences a pointer from the ring buffer. [1] https://lore.kernel.org/all/20260630200022.1826420-1-martin@kaiser.cx/ Link: https://patch.msgid.link/20260630184836.74d477b6@gandalf.local.home Signed-off-by: Steven Rostedt Reviewed-by: Martin Kaiser Reviewed-by: Vinod Koul Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index e0449e648871..714285e23a2e 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -401,6 +401,31 @@ static bool process_string(const char *fmt, int len, struct trace_event_call *ca return true; } +static void test_double_dereference(const char *str, int len, + struct trace_event_call *call) +{ + const char *ptr; + const char *end = str + len; + + ptr = strstr(str, "REC->"); + + while (ptr && ptr < end) { + + ptr += 5; + for (; ptr < end; ptr++) { + if (ptr[0] == '-' && ptr[1] == '>') { + WARN_ONCE(1, "Event %s has double dereference in TP_printk: %.*s\n", + trace_event_name(call), len, str); + return; + } + if (!isalnum(*ptr) && *ptr != '_') + break; + } + + ptr = strstr(ptr, "REC->"); + } +} + static void handle_dereference_arg(const char *arg_str, u64 string_flags, int len, u64 *dereference_flags, int arg, struct trace_event_call *call) @@ -460,12 +485,6 @@ static void test_event_printk(struct trace_event_call *call) if (in_quote) { arg = 0; first = false; - /* - * If there was no %p* uses - * the fmt is OK. - */ - if (!dereference_flags) - return; } } if (in_quote) { @@ -577,6 +596,8 @@ static void test_event_printk(struct trace_event_call *call) continue; } + test_double_dereference(fmt + start_arg, e - start_arg, call); + if (dereference_flags & (1ULL << arg)) { handle_dereference_arg(fmt + start_arg, string_flags, e - start_arg, @@ -590,6 +611,8 @@ static void test_event_printk(struct trace_event_call *call) } } + test_double_dereference(fmt + start_arg, i - start_arg, call); + if (dereference_flags & (1ULL << arg)) { handle_dereference_arg(fmt + start_arg, string_flags, i - start_arg, -- cgit v1.2.3 From dca6a22aee1b9fb2fe26823bc3b302e8eba8d05c Mon Sep 17 00:00:00 2001 From: Po-Sheng Lin Date: Mon, 6 Jul 2026 01:36:48 +0800 Subject: tracing: Use strscpy() instead of strcpy() in trace_sched_switch Replace strcpy() with strscpy() in __trace_find_cmdline() for consistency with the existing strscpy() call in the same function, and to avoid potential buffer overflow as flagged by the Kernel Self Protection Project. Link: https://patch.msgid.link/20260705173648.5418-1-posheng.lin.tw@gmail.com Signed-off-by: Po-Sheng Lin Signed-off-by: Steven Rostedt --- kernel/trace/trace_sched_switch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c index e9f0ff962660..1bd351c1fbfb 100644 --- a/kernel/trace/trace_sched_switch.c +++ b/kernel/trace/trace_sched_switch.c @@ -286,12 +286,12 @@ static void __trace_find_cmdline(int pid, char comm[]) int tpid; if (!pid) { - strcpy(comm, ""); + strscpy(comm, "", TASK_COMM_LEN); return; } if (WARN_ON_ONCE(pid < 0)) { - strcpy(comm, ""); + strscpy(comm, "", TASK_COMM_LEN); return; } @@ -304,7 +304,7 @@ static void __trace_find_cmdline(int pid, char comm[]) return; } } - strcpy(comm, "<...>"); + strscpy(comm, "<...>", TASK_COMM_LEN); } void trace_find_cmdline(int pid, char comm[]) -- cgit v1.2.3 From efdcfd9b4f4f07aa70663ee02a79dbdf980bf582 Mon Sep 17 00:00:00 2001 From: Woradorn Laodhanadhaworn Date: Mon, 13 Jul 2026 11:52:49 +0700 Subject: tracing: Use seq_buf for string concatenation In preparation for removing the strlcat API[1], replace the string concatenation logic with a struct seq_buf, which tracks the current position and the remaining space internally. Use seq_buf_str() to NUL-terminate before passing to early_enable_events(). Link: https://github.com/KSPP/linux/issues/370 [1] Link: https://patch.msgid.link/20260713045249.69942-1-woradorn.laon@gmail.com Signed-off-by: Woradorn Laodhanadhaworn [ Moved placement of #include ] Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 714285e23a2e..a8590d2394e3 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -4604,13 +4605,20 @@ extern struct trace_event_call *__start_ftrace_events[]; extern struct trace_event_call *__stop_ftrace_events[]; static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata; +static struct seq_buf bootup_event_seq __initdata = { + .buffer = bootup_event_buf, + .size = sizeof(bootup_event_buf), +}; static __init int setup_trace_event(char *str) { - if (bootup_event_buf[0] != '\0') - strlcat(bootup_event_buf, ",", COMMAND_LINE_SIZE); + if (seq_buf_used(&bootup_event_seq) > 0) + seq_buf_puts(&bootup_event_seq, ","); + + seq_buf_puts(&bootup_event_seq, str); - strlcat(bootup_event_buf, str, COMMAND_LINE_SIZE); + if (seq_buf_has_overflowed(&bootup_event_seq)) + return -ENOMEM; trace_set_ring_buffer_expanded(NULL); disable_tracing_selftest("running event tracing"); @@ -4869,6 +4877,7 @@ static __init int event_trace_enable(void) */ __trace_early_add_events(tr); + seq_buf_str(&bootup_event_seq); early_enable_events(tr, bootup_event_buf, false); trace_printk_start_comm(); @@ -4897,6 +4906,7 @@ static __init int event_trace_enable_again(void) if (!tr) return -ENODEV; + seq_buf_str(&bootup_event_seq); early_enable_events(tr, bootup_event_buf, true); return 0; -- cgit v1.2.3 From d5b201ed4feb7a11da242a97669424efeb724031 Mon Sep 17 00:00:00 2001 From: Mykyta Yatsenko Date: Thu, 30 Jul 2026 17:17:39 -0700 Subject: tracing: Make per-template BTF id lists file-local DECLARE_EVENT_CLASS emitted __bpf_trace_btf_ids_ through BTF_ID_LIST_GLOBAL, i.e. a global symbol named after the event class. The class name is not unique across the kernel, so the symbol multiply-defines whenever two translation units instantiate the same class. Switch to the file-local BTF_ID_LIST: the list is reached only through the event_class_.btf_ids pointer, initialised in the same unit, so tracefs readers never reference the symbol by name and resolve_btfids still fills the now-local .BTF_ids entries. The handcrafted syscall classes are the one cross-unit consumer: give them their own local BTF_ID_LIST rather than importing the generated sys_{enter,exit} lists. Link: https://patch.msgid.link/20260730-b4-fix_btf_tracefs-v2-1-6b66da8dc103@meta.com Fixes: eadc0725ab8d3 ("tracing: Expose tracepoint BTF ids via tracefs") Reported-by: Mark Brown Closes: https://lore.kernel.org/all/ff58b01c-3f5e-4d55-be82-609d2faaf12e@sirena.org.uk/ Signed-off-by: Mykyta Yatsenko Acked-by: Andrii Nakryiko Signed-off-by: Steven Rostedt --- kernel/trace/trace_syscalls.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 48ef1a93e576..e35744049e3f 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "trace_output.h" @@ -1303,15 +1304,15 @@ struct trace_event_functions exit_syscall_print_funcs = { .trace = print_syscall_exit, }; -#ifdef CONFIG_BPF_EVENTS -/* - * BTF id lists generated by DECLARE_EVENT_CLASS for the sys_enter and - * sys_exit tracepoints. The auto-generated event_class_sys_{enter,exit} - * is unused (per-syscall events share the handcrafted classes below), - * but the id lists themselves are global and reusable. - */ -extern u32 __bpf_trace_btf_ids_sys_enter[]; -extern u32 __bpf_trace_btf_ids_sys_exit[]; +#if defined(CONFIG_BPF_EVENTS) && defined(CONFIG_DEBUG_INFO_BTF) +/* BTF id lists for the shared sys_enter/sys_exit dispatcher tracepoints. */ +BTF_ID_LIST(syscall_enter_btf_ids) +BTF_ID(func, __bpf_trace_sys_enter) +BTF_ID(struct, trace_event_raw_sys_enter) + +BTF_ID_LIST(syscall_exit_btf_ids) +BTF_ID(func, __bpf_trace_sys_exit) +BTF_ID(struct, trace_event_raw_sys_exit) #endif struct trace_event_class __refdata event_class_syscall_enter = { @@ -1320,8 +1321,8 @@ struct trace_event_class __refdata event_class_syscall_enter = { .fields_array = syscall_enter_fields_array, .get_fields = syscall_get_enter_fields, .raw_init = init_syscall_trace, -#ifdef CONFIG_BPF_EVENTS - .btf_ids = __bpf_trace_btf_ids_sys_enter, +#if defined(CONFIG_BPF_EVENTS) && defined(CONFIG_DEBUG_INFO_BTF) + .btf_ids = syscall_enter_btf_ids, #endif }; @@ -1335,8 +1336,8 @@ struct trace_event_class __refdata event_class_syscall_exit = { }, .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields), .raw_init = init_syscall_trace, -#ifdef CONFIG_BPF_EVENTS - .btf_ids = __bpf_trace_btf_ids_sys_exit, +#if defined(CONFIG_BPF_EVENTS) && defined(CONFIG_DEBUG_INFO_BTF) + .btf_ids = syscall_exit_btf_ids, #endif }; -- cgit v1.2.3 From faa0e9064a16b8a9bfac63139b0d8cd18946f247 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Tue, 28 Jul 2026 21:50:10 +0900 Subject: tracing/mmiotrace: Use trace_assign_type() in mmio_print_mark() In mmio_print_mark(), a raw C cast (struct print_entry *)entry is used to obtain the print_entry pointer. Use the standard trace_assign_type() macro instead, matching the usage in mmio_print_rw() and mmio_print_map(). Link: https://patch.msgid.link/178524301013.56416.9116249028160618790.stgit@devnote2 Assisted-by: Antigravity:gemini-3.6-flash Signed-off-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_mmiotrace.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c index b88b8d9923ad..ebdba4f8d64f 100644 --- a/kernel/trace/trace_mmiotrace.c +++ b/kernel/trace/trace_mmiotrace.c @@ -243,13 +243,16 @@ static enum print_line_t mmio_print_map(struct trace_iterator *iter) static enum print_line_t mmio_print_mark(struct trace_iterator *iter) { struct trace_entry *entry = iter->ent; - struct print_entry *print = (struct print_entry *)entry; - const char *msg = print->buf; + struct print_entry *print; + const char *msg; struct trace_seq *s = &iter->seq; unsigned long long t = ns2usecs(iter->ts); unsigned long usec_rem = do_div(t, USEC_PER_SEC); unsigned secs = (unsigned long)t; + trace_assign_type(print, entry); + msg = print->buf; + /* The trailing newline must be in the message. */ trace_seq_printf(s, "MARK %u.%06lu %s", secs, usec_rem, msg); -- cgit v1.2.3 From 0456323ddd676446ac79aacd69c3443e64197843 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 6 Aug 2026 22:52:56 +0100 Subject: tracing: Report every TP_printk double dereference WARN_ONCE() splats once per call site, so only the first offending event registered is ever reported. The tree currently has six: ice_{rx,tx}_dim_template, two hfi1 txq events, mtu3_ep and edma_log_io. Whichever registers first hides the rest, and each has to be found again on the next boot. Add a pr_warn() next to the WARN_ONCE() so every offender is listed, the same way test_event_printk() already pairs WARN_ON_ONCE() with pr_warn() for unsafe %p* dereferences. The WARN_ONCE() stays so the condition still fails tests and panics under panic_on_warn. Link: https://patch.msgid.link/20260806215256.1680267-1-devnexen@gmail.com Suggested-by: Steven Rostedt Signed-off-by: David Carlier Signed-off-by: Steven Rostedt --- kernel/trace/trace_events.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index a8590d2394e3..ce902482ec7c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -415,6 +415,8 @@ static void test_double_dereference(const char *str, int len, ptr += 5; for (; ptr < end; ptr++) { if (ptr[0] == '-' && ptr[1] == '>') { + pr_warn("TRACE EVENT ERROR: Event %s has double dereference in TP_printk: %.*s\n", + trace_event_name(call), len, str); WARN_ONCE(1, "Event %s has double dereference in TP_printk: %.*s\n", trace_event_name(call), len, str); return; -- cgit v1.2.3 From a8aaf7445bfcdb6e61ee4b8e4946d684c1b4a228 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Fri, 7 Aug 2026 11:35:58 -0400 Subject: tracing: Cleanup event_enable_trigger_parse() by using __free() The enable_data variable gets freed on most error paths in event_enable_trigger_parse(). Use free() to free it and just before returning normally, call retain_and_null_ptr(enable_data) just before a successful exit to keep it from being freed. On success, the enable_data is assigned to the trigger_data->private_data field. Also add a comment to why event_trigger_free(trigger_data) is being called before a successful exit. Link: https://patch.msgid.link/20260807113558.0ff14e96@gandalf.local.home Reviewed-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt --- kernel/trace/trace_events_trigger.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index ad83419cb420..149300cc5e8a 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -1753,7 +1753,7 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, char *glob, char *cmd, char *param_and_filter) { struct trace_event_file *event_enable_file; - struct enable_trigger_data *enable_data; + struct enable_trigger_data *enable_data __free(kfree) = NULL; struct event_trigger_data *trigger_data; struct trace_array *tr = file->tr; char *param, *filter; @@ -1803,17 +1803,13 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, enable_data->file = event_enable_file; trigger_data = trigger_data_alloc(cmd_ops, cmd, param, enable_data); - if (!trigger_data) { - kfree(enable_data); + if (!trigger_data) return ret; - } if (remove) { event_trigger_unregister(cmd_ops, file, glob+1, trigger_data); kfree(trigger_data); - kfree(enable_data); - ret = 0; - return ret; + return 0; } /* Up the trigger_data count to make sure nothing frees it on failure */ @@ -1842,7 +1838,12 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, if (ret) goto out_disable; + /* It's now safe to free the reference taken earlier */ event_trigger_free(trigger_data); + + /* The enabled_data is assigned to trigger_data->private_data */ + retain_and_null_ptr(enable_data); + return ret; out_disable: trace_event_enable_disable(event_enable_file, 0, 1); @@ -1851,7 +1852,6 @@ int event_enable_trigger_parse(struct event_command *cmd_ops, out_free: event_trigger_reset_filter(cmd_ops, trigger_data); event_trigger_free(trigger_data); - kfree(enable_data); return ret; } -- cgit v1.2.3 From ae70b04ab9c7f6162a8c0fdd18a62a945c133142 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 13 Aug 2026 20:42:26 -0400 Subject: tracing: Have trace_event_update_all() only handle module that is loading The function trace_event_update_all() does a scan of events looking to replace enums with their values in the strings that get exported to the event format files. It's run at boot up on all events and again when a module loads. The issue is that when a module loads, it still runs on *all* events. There's no reason to process every event when a module loads as the previous events have already been processed. Only execute on the events that are loaded with the module. Link: https://patch.msgid.link/20260813204226.29563591@gandalf.local.home Fixes: 3673b8e4ce723 ("tracing: Allow for modules to convert their enums to values") Signed-off-by: Steven Rostedt --- kernel/trace/trace.c | 2 +- kernel/trace/trace.h | 4 ++-- kernel/trace/trace_events.c | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'kernel/trace') diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 01a5e87af299..575912e4c310 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -4669,7 +4669,7 @@ trace_event_update_with_eval_map(struct module *mod, map = start; - trace_event_update_all(map, len); + trace_event_update_all(map, len, mod); if (len <= 0) return; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index bf77331f56a4..74a7a50d1e78 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -2285,13 +2285,13 @@ static inline const char *get_syscall_name(int syscall) #ifdef CONFIG_EVENT_TRACING void trace_event_init(void); -void trace_event_update_all(struct trace_eval_map **map, int len); +void trace_event_update_all(struct trace_eval_map **map, int len, struct module *mod); /* Used from boot time tracer */ extern int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set); extern int trigger_process_regex(struct trace_event_file *file, char *buff); #else static inline void __init trace_event_init(void) { } -static inline void trace_event_update_all(struct trace_eval_map **map, int len) { } +static inline void trace_event_update_all(struct trace_eval_map **map, int len, struct module *mod) { } #endif #ifdef CONFIG_TRACER_SNAPSHOT diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index ce902482ec7c..7313eb1361c9 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -3661,7 +3661,7 @@ static void update_event_fields(struct trace_event_call *call, } /* Update all events for replacing eval and sanitizing */ -void trace_event_update_all(struct trace_eval_map **map, int len) +void trace_event_update_all(struct trace_eval_map **map, int len, struct module *mod) { struct trace_event_call *call, *p; const char *last_system = NULL; @@ -3672,6 +3672,10 @@ void trace_event_update_all(struct trace_eval_map **map, int len) down_write(&trace_event_sem); list_for_each_entry_safe(call, p, &ftrace_events, list) { + + if (mod && call->module != mod) + continue; + /* events are usually grouped together with systems */ if (!last_system || call->class->system != last_system) { first = true; -- cgit v1.2.3