1 // SPDX-License-Identifier: GPL-2.0
3 * trace_events_inject - trace event injection
8 #include <linux/module.h>
9 #include <linux/ctype.h>
10 #include <linux/mutex.h>
11 #include <linux/slab.h>
12 #include <linux/rculist.h>
17 trace_inject_entry(struct trace_event_file *file, void *rec, int len)
19 struct trace_event_buffer fbuffer;
23 rcu_read_lock_sched();
24 entry = trace_event_buffer_reserve(&fbuffer, file, len);
26 memcpy(entry, rec, len);
28 trace_event_buffer_commit(&fbuffer);
30 rcu_read_unlock_sched();
36 parse_field(char *str, struct trace_event_call *call,
37 struct ftrace_event_field **pf, u64 *pv)
39 struct ftrace_event_field *field;
47 /* First find the field to associate to */
48 while (isspace(str[i]))
51 while (isalnum(str[i]) || str[i] == '_')
57 field_name = kmemdup_nul(str + s, len, GFP_KERNEL);
60 field = trace_find_event_field(call, field_name);
66 while (isspace(str[i]))
71 while (isspace(str[i]))
74 if (isdigit(str[i]) || str[i] == '-') {
78 /* Make sure the field is not a string */
79 if (is_string_field(field))
85 /* We allow 0xDEADBEEF */
86 while (isalnum(str[i]))
90 if (c != '\0' && !isspace(c))
93 /* Make sure it is a value */
95 ret = kstrtoll(num, 0, &val);
97 ret = kstrtoull(num, 0, &val);
104 } else if (str[i] == '\'' || str[i] == '"') {
107 /* Make sure the field is OK for strings */
108 if (!is_string_field(field))
111 for (i++; str[i]; i++) {
112 if (str[i] == '\\' && str[i + 1]) {
125 if (len >= MAX_FILTER_STR_VAL)
128 *pv = (unsigned long)(str + s);
130 /* go past the last quote */
138 static int trace_get_entry_size(struct trace_event_call *call)
140 struct ftrace_event_field *field;
141 struct list_head *head;
144 head = trace_get_fields(call);
145 list_for_each_entry(field, head, link) {
146 if (field->size + field->offset > size)
147 size = field->size + field->offset;
153 static void *trace_alloc_entry(struct trace_event_call *call, int *size)
155 int entry_size = trace_get_entry_size(call);
156 struct ftrace_event_field *field;
157 struct list_head *head;
160 /* We need an extra '\0' at the end. */
161 entry = kzalloc(entry_size + 1, GFP_KERNEL);
165 head = trace_get_fields(call);
166 list_for_each_entry(field, head, link) {
167 if (!is_string_field(field))
169 if (field->filter_type == FILTER_STATIC_STRING)
171 if (field->filter_type == FILTER_DYN_STRING) {
173 int str_loc = entry_size & 0xffff;
175 str_item = (u32 *)(entry + field->offset);
176 *str_item = str_loc; /* string length is 0. */
180 paddr = (char **)(entry + field->offset);
185 *size = entry_size + 1;
189 #define INJECT_STRING "STATIC STRING CAN NOT BE INJECTED"
191 /* Caller is responsible to free the *pentry. */
192 static int parse_entry(char *str, struct trace_event_call *call, void **pentry)
194 struct ftrace_event_field *field;
195 unsigned long irq_flags;
201 entry = trace_alloc_entry(call, &entry_size);
206 local_save_flags(irq_flags);
207 tracing_generic_entry_update(entry, call->event.type, irq_flags,
210 while ((len = parse_field(str, call, &field, &val)) > 0) {
211 if (is_function_field(field))
214 if (is_string_field(field)) {
215 char *addr = (char *)(unsigned long) val;
217 if (field->filter_type == FILTER_STATIC_STRING) {
218 strlcpy(entry + field->offset, addr, field->size);
219 } else if (field->filter_type == FILTER_DYN_STRING) {
220 int str_len = strlen(addr) + 1;
221 int str_loc = entry_size & 0xffff;
224 entry_size += str_len;
225 *pentry = krealloc(entry, entry_size, GFP_KERNEL);
232 strlcpy(entry + (entry_size - str_len), addr, str_len);
233 str_item = (u32 *)(entry + field->offset);
234 *str_item = (str_len << 16) | str_loc;
238 paddr = (char **)(entry + field->offset);
239 *paddr = INJECT_STRING;
242 switch (field->size) {
246 memcpy(entry + field->offset, &tmp, 1);
252 memcpy(entry + field->offset, &tmp, 2);
258 memcpy(entry + field->offset, &tmp, 4);
262 memcpy(entry + field->offset, &val, 8);
279 event_inject_write(struct file *filp, const char __user *ubuf, size_t cnt,
282 struct trace_event_call *call;
283 struct trace_event_file *file;
284 int err = -ENODEV, size;
288 if (cnt >= PAGE_SIZE)
291 buf = memdup_user_nul(ubuf, cnt);
296 mutex_lock(&event_mutex);
297 file = event_file_data(filp);
299 call = file->event_call;
300 size = parse_entry(buf, call, &entry);
304 err = trace_inject_entry(file, entry, size);
306 mutex_unlock(&event_mutex);
319 event_inject_read(struct file *file, char __user *buf, size_t size,
325 const struct file_operations event_inject_fops = {
326 .open = tracing_open_generic,
327 .read = event_inject_read,
328 .write = event_inject_write,