summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/btf.c4
-rw-r--r--kernel/trace/preemptirq_delay_test.c9
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace.h4
-rw-r--r--kernel/trace/trace_events.c139
-rw-r--r--kernel/trace/trace_events_hist.c96
-rw-r--r--kernel/trace/trace_events_trigger.c16
-rw-r--r--kernel/trace/trace_events_user.c10
-rw-r--r--kernel/trace/trace_functions_graph.c2
-rw-r--r--kernel/trace/trace_mmiotrace.c7
-rw-r--r--kernel/trace/trace_printk.c3
-rw-r--r--kernel/trace/trace_sched_switch.c6
-rw-r--r--kernel/trace/trace_syscalls.c18
13 files changed, 241 insertions, 75 deletions
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7e25051dc1ea..f56437e626c9 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6467,7 +6467,7 @@ err_out:
* split BTF ids will need to be mapped to actual base/split ids for
* BTF now that it has been relocated.
*/
-static __u32 btf_relocate_id(const struct btf *btf, __u32 id)
+__u32 btf_relocate_id(const struct btf *btf, __u32 id)
{
if (!btf->base_btf || !btf->base_id_map)
return id;
@@ -8623,7 +8623,7 @@ struct module *btf_try_get_module(const struct btf *btf)
/* Returns struct btf corresponding to the struct module.
* This function can return NULL or ERR_PTR.
*/
-static struct btf *btf_get_module_btf(const struct module *module)
+struct btf *btf_get_module_btf(const struct module *module)
{
#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
struct btf_module *btf_mod, *tmp;
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 <linux/trace_clock.h>
+#include <linux/cpumask.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
@@ -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);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 395238b2b715..89dc1c0ebb90 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 3650d84d4f16..7ce862c92a85 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -14,6 +14,7 @@
#include <linux/workqueue.h>
#include <linux/security.h>
#include <linux/spinlock.h>
+#include <linux/seq_buf.h>
#include <linux/kthread.h>
#include <linux/tracefs.h>
#include <linux/uaccess.h>
@@ -22,6 +23,7 @@
#include <linux/sort.h>
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/btf.h>
#include <trace/events/sched.h>
#include <trace/syscall.h>
@@ -400,6 +402,33 @@ 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] == '>') {
+ 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;
+ }
+ 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)
@@ -459,12 +488,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) {
@@ -576,6 +599,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,
@@ -589,6 +614,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,
@@ -2202,6 +2229,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 +2784,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 +3184,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 +3246,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",
@@ -3557,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;
@@ -3569,6 +3673,10 @@ void trace_event_update_all(struct trace_eval_map **map, int len)
mutex_lock(&event_mutex);
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;
@@ -4505,13 +4613,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");
@@ -4770,6 +4885,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();
@@ -4798,6 +4914,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;
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 58d28cd1afa3..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,86 +1732,94 @@ 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;
+ char *expr __free(kfree) = NULL;
+ struct seq_buf s;
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);
+
+ seq_buf_init(&s, expr, MAX_FILTER_STR_VAL);
if (!field->operands[0]) {
- expr_field_str(field, expr);
- return 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 (!subexpr) {
- kfree(expr);
- return NULL;
- }
- strcat(expr, subexpr);
- strcat(expr, ")");
+ if (IS_ERR(subexpr))
+ return subexpr;
+ seq_buf_printf(&s, "-(%s)", subexpr);
kfree(subexpr);
- return expr;
+ 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:
- kfree(expr);
- return NULL;
+ 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 expr;
+ return_ptr(expr);
}
/*
@@ -1984,9 +1991,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;
}
@@ -2626,6 +2631,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;
@@ -2838,6 +2848,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;
@@ -2851,6 +2866,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;
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;
}
diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
index 8c82ecb735f4..2bbc89d4a266 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;
}
@@ -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");
@@ -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);
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);
}
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index df8692c2dea8..77120d467e11 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -244,13 +244,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);
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);
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, "<idle>");
+ strscpy(comm, "<idle>", TASK_COMM_LEN);
return;
}
if (WARN_ON_ONCE(pid < 0)) {
- strcpy(comm, "<XXX>");
+ strscpy(comm, "<XXX>", 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[])
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 8a4f3c75e39f..e35744049e3f 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -9,6 +9,7 @@
#include <linux/ftrace.h>
#include <linux/perf_event.h>
#include <linux/xarray.h>
+#include <linux/btf_ids.h>
#include <asm/syscall.h>
#include "trace_output.h"
@@ -1303,12 +1304,26 @@ struct trace_event_functions exit_syscall_print_funcs = {
.trace = print_syscall_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 = {
.system = "syscalls",
.reg = syscall_enter_register,
.fields_array = syscall_enter_fields_array,
.get_fields = syscall_get_enter_fields,
.raw_init = init_syscall_trace,
+#if defined(CONFIG_BPF_EVENTS) && defined(CONFIG_DEBUG_INFO_BTF)
+ .btf_ids = syscall_enter_btf_ids,
+#endif
};
struct trace_event_class __refdata event_class_syscall_exit = {
@@ -1321,6 +1336,9 @@ struct trace_event_class __refdata event_class_syscall_exit = {
},
.fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
.raw_init = init_syscall_trace,
+#if defined(CONFIG_BPF_EVENTS) && defined(CONFIG_DEBUG_INFO_BTF)
+ .btf_ids = syscall_exit_btf_ids,
+#endif
};
unsigned long __init __weak arch_syscall_addr(int nr)