tracing: do not allow modifying the ftrace events via the event files
[deliverable/linux.git] / kernel / trace / trace_events.c
CommitLineData
b77e38aa
SR
1/*
2 * event tracer
3 *
4 * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
5 *
981d081e
SR
6 * - Added format output of fields of the trace point.
7 * This was based off of work by Tom Zanussi <tzanussi@gmail.com>.
8 *
b77e38aa
SR
9 */
10
11#include <linux/debugfs.h>
12#include <linux/uaccess.h>
13#include <linux/module.h>
14#include <linux/ctype.h>
15
91729ef9 16#include "trace_output.h"
b77e38aa 17
b628b3e6
SR
18#define TRACE_SYSTEM "TRACE_SYSTEM"
19
11a241a3
SR
20static DEFINE_MUTEX(event_mutex);
21
1473e441
SR
22#define events_for_each(event) \
23 for (event = __start_ftrace_events; \
24 (unsigned long)event < (unsigned long)__stop_ftrace_events; \
25 event++)
26
b77e38aa
SR
27void event_trace_printk(unsigned long ip, const char *fmt, ...)
28{
29 va_list ap;
30
31 va_start(ap, fmt);
32 tracing_record_cmdline(current);
33 trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap);
34 va_end(ap);
35}
36
37static void ftrace_clear_events(void)
38{
39 struct ftrace_event_call *call = (void *)__start_ftrace_events;
40
41
42 while ((unsigned long)call < (unsigned long)__stop_ftrace_events) {
43
44 if (call->enabled) {
45 call->enabled = 0;
46 call->unregfunc();
47 }
48 call++;
49 }
50}
51
fd994989
SR
52static void ftrace_event_enable_disable(struct ftrace_event_call *call,
53 int enable)
54{
55
56 switch (enable) {
57 case 0:
58 if (call->enabled) {
59 call->enabled = 0;
60 call->unregfunc();
61 }
fd994989
SR
62 break;
63 case 1:
da4d0302 64 if (!call->enabled) {
fd994989
SR
65 call->enabled = 1;
66 call->regfunc();
67 }
fd994989
SR
68 break;
69 }
70}
71
b77e38aa
SR
72static int ftrace_set_clr_event(char *buf, int set)
73{
1473e441 74 struct ftrace_event_call *call = __start_ftrace_events;
b628b3e6
SR
75 char *event = NULL, *sub = NULL, *match;
76 int ret = -EINVAL;
77
78 /*
79 * The buf format can be <subsystem>:<event-name>
80 * *:<event-name> means any event by that name.
81 * :<event-name> is the same.
82 *
83 * <subsystem>:* means all events in that subsystem
84 * <subsystem>: means the same.
85 *
86 * <name> (no ':') means all events in a subsystem with
87 * the name <name> or any event that matches <name>
88 */
89
90 match = strsep(&buf, ":");
91 if (buf) {
92 sub = match;
93 event = buf;
94 match = NULL;
95
96 if (!strlen(sub) || strcmp(sub, "*") == 0)
97 sub = NULL;
98 if (!strlen(event) || strcmp(event, "*") == 0)
99 event = NULL;
100 }
b77e38aa 101
11a241a3 102 mutex_lock(&event_mutex);
1473e441 103 events_for_each(call) {
b77e38aa 104
40e26815 105 if (!call->name || !call->regfunc)
1473e441
SR
106 continue;
107
b628b3e6
SR
108 if (match &&
109 strcmp(match, call->name) != 0 &&
110 strcmp(match, call->system) != 0)
111 continue;
112
113 if (sub && strcmp(sub, call->system) != 0)
114 continue;
115
116 if (event && strcmp(event, call->name) != 0)
b77e38aa 117 continue;
b77e38aa 118
fd994989
SR
119 ftrace_event_enable_disable(call, set);
120
b628b3e6 121 ret = 0;
b77e38aa 122 }
11a241a3
SR
123 mutex_unlock(&event_mutex);
124
b628b3e6 125 return ret;
b77e38aa
SR
126}
127
128/* 128 should be much more than enough */
129#define EVENT_BUF_SIZE 127
130
131static ssize_t
132ftrace_event_write(struct file *file, const char __user *ubuf,
133 size_t cnt, loff_t *ppos)
134{
135 size_t read = 0;
136 int i, set = 1;
137 ssize_t ret;
138 char *buf;
139 char ch;
140
141 if (!cnt || cnt < 0)
142 return 0;
143
144 ret = get_user(ch, ubuf++);
145 if (ret)
146 return ret;
147 read++;
148 cnt--;
149
150 /* skip white space */
151 while (cnt && isspace(ch)) {
152 ret = get_user(ch, ubuf++);
153 if (ret)
154 return ret;
155 read++;
156 cnt--;
157 }
158
159 /* Only white space found? */
160 if (isspace(ch)) {
161 file->f_pos += read;
162 ret = read;
163 return ret;
164 }
165
166 buf = kmalloc(EVENT_BUF_SIZE+1, GFP_KERNEL);
167 if (!buf)
168 return -ENOMEM;
169
170 if (cnt > EVENT_BUF_SIZE)
171 cnt = EVENT_BUF_SIZE;
172
173 i = 0;
174 while (cnt && !isspace(ch)) {
175 if (!i && ch == '!')
176 set = 0;
177 else
178 buf[i++] = ch;
179
180 ret = get_user(ch, ubuf++);
181 if (ret)
182 goto out_free;
183 read++;
184 cnt--;
185 }
186 buf[i] = 0;
187
188 file->f_pos += read;
189
190 ret = ftrace_set_clr_event(buf, set);
191 if (ret)
192 goto out_free;
193
194 ret = read;
195
196 out_free:
197 kfree(buf);
198
199 return ret;
200}
201
202static void *
203t_next(struct seq_file *m, void *v, loff_t *pos)
204{
205 struct ftrace_event_call *call = m->private;
206 struct ftrace_event_call *next = call;
207
208 (*pos)++;
209
40e26815
SR
210 for (;;) {
211 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
212 return NULL;
213
214 /*
215 * The ftrace subsystem is for showing formats only.
216 * They can not be enabled or disabled via the event files.
217 */
218 if (call->regfunc)
219 break;
220
221 call++;
222 next = call;
223 }
b77e38aa
SR
224
225 m->private = ++next;
226
227 return call;
228}
229
230static void *t_start(struct seq_file *m, loff_t *pos)
231{
232 return t_next(m, NULL, pos);
233}
234
235static void *
236s_next(struct seq_file *m, void *v, loff_t *pos)
237{
238 struct ftrace_event_call *call = m->private;
239 struct ftrace_event_call *next;
240
241 (*pos)++;
242
243 retry:
244 if ((unsigned long)call >= (unsigned long)__stop_ftrace_events)
245 return NULL;
246
247 if (!call->enabled) {
248 call++;
249 goto retry;
250 }
251
252 next = call;
253 m->private = ++next;
254
255 return call;
256}
257
258static void *s_start(struct seq_file *m, loff_t *pos)
259{
260 return s_next(m, NULL, pos);
261}
262
263static int t_show(struct seq_file *m, void *v)
264{
265 struct ftrace_event_call *call = v;
266
b628b3e6
SR
267 if (strcmp(call->system, TRACE_SYSTEM) != 0)
268 seq_printf(m, "%s:", call->system);
b77e38aa
SR
269 seq_printf(m, "%s\n", call->name);
270
271 return 0;
272}
273
274static void t_stop(struct seq_file *m, void *p)
275{
276}
277
278static int
279ftrace_event_seq_open(struct inode *inode, struct file *file)
280{
281 int ret;
282 const struct seq_operations *seq_ops;
283
284 if ((file->f_mode & FMODE_WRITE) &&
285 !(file->f_flags & O_APPEND))
286 ftrace_clear_events();
287
288 seq_ops = inode->i_private;
289 ret = seq_open(file, seq_ops);
290 if (!ret) {
291 struct seq_file *m = file->private_data;
292
293 m->private = __start_ftrace_events;
294 }
295 return ret;
296}
297
1473e441
SR
298static ssize_t
299event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
300 loff_t *ppos)
301{
302 struct ftrace_event_call *call = filp->private_data;
303 char *buf;
304
da4d0302 305 if (call->enabled)
1473e441
SR
306 buf = "1\n";
307 else
308 buf = "0\n";
309
310 return simple_read_from_buffer(ubuf, cnt, ppos, buf, 2);
311}
312
313static ssize_t
314event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
315 loff_t *ppos)
316{
317 struct ftrace_event_call *call = filp->private_data;
318 char buf[64];
319 unsigned long val;
320 int ret;
321
322 if (cnt >= sizeof(buf))
323 return -EINVAL;
324
325 if (copy_from_user(&buf, ubuf, cnt))
326 return -EFAULT;
327
328 buf[cnt] = 0;
329
330 ret = strict_strtoul(buf, 10, &val);
331 if (ret < 0)
332 return ret;
333
334 switch (val) {
335 case 0:
1473e441 336 case 1:
11a241a3 337 mutex_lock(&event_mutex);
fd994989 338 ftrace_event_enable_disable(call, val);
11a241a3 339 mutex_unlock(&event_mutex);
1473e441
SR
340 break;
341
342 default:
343 return -EINVAL;
344 }
345
346 *ppos += cnt;
347
348 return cnt;
349}
350
91729ef9 351#undef FIELD
156b5f17 352#define FIELD(type, name) \
ce8eb2bf 353 #type, #name, offsetof(typeof(field), name), sizeof(field.name)
91729ef9
SR
354
355static int trace_write_header(struct trace_seq *s)
356{
357 struct trace_entry field;
358
359 /* struct trace_entry */
360 return trace_seq_printf(s,
ce8eb2bf
SR
361 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
362 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
363 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
364 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
365 "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n"
91729ef9
SR
366 "\n",
367 FIELD(unsigned char, type),
368 FIELD(unsigned char, flags),
369 FIELD(unsigned char, preempt_count),
370 FIELD(int, pid),
371 FIELD(int, tgid));
372}
da4d0302 373
981d081e
SR
374static ssize_t
375event_format_read(struct file *filp, char __user *ubuf, size_t cnt,
376 loff_t *ppos)
377{
378 struct ftrace_event_call *call = filp->private_data;
379 struct trace_seq *s;
380 char *buf;
381 int r;
382
383 s = kmalloc(sizeof(*s), GFP_KERNEL);
384 if (!s)
385 return -ENOMEM;
386
387 trace_seq_init(s);
388
389 if (*ppos)
390 return 0;
391
c5e4e192
SR
392 /* If any of the first writes fail, so will the show_format. */
393
394 trace_seq_printf(s, "name: %s\n", call->name);
395 trace_seq_printf(s, "ID: %d\n", call->id);
396 trace_seq_printf(s, "format:\n");
91729ef9
SR
397 trace_write_header(s);
398
981d081e
SR
399 r = call->show_format(s);
400 if (!r) {
401 /*
402 * ug! The format output is bigger than a PAGE!!
403 */
404 buf = "FORMAT TOO BIG\n";
405 r = simple_read_from_buffer(ubuf, cnt, ppos,
406 buf, strlen(buf));
407 goto out;
408 }
409
410 r = simple_read_from_buffer(ubuf, cnt, ppos,
411 s->buffer, s->len);
412 out:
413 kfree(s);
414 return r;
415}
416
b77e38aa
SR
417static const struct seq_operations show_event_seq_ops = {
418 .start = t_start,
419 .next = t_next,
420 .show = t_show,
421 .stop = t_stop,
422};
423
424static const struct seq_operations show_set_event_seq_ops = {
425 .start = s_start,
426 .next = s_next,
427 .show = t_show,
428 .stop = t_stop,
429};
430
b77e38aa
SR
431static const struct file_operations ftrace_set_event_fops = {
432 .open = ftrace_event_seq_open,
433 .read = seq_read,
434 .write = ftrace_event_write,
435 .llseek = seq_lseek,
436 .release = seq_release,
437};
438
1473e441
SR
439static const struct file_operations ftrace_enable_fops = {
440 .open = tracing_open_generic,
441 .read = event_enable_read,
442 .write = event_enable_write,
443};
444
981d081e
SR
445static const struct file_operations ftrace_event_format_fops = {
446 .open = tracing_open_generic,
447 .read = event_format_read,
448};
449
1473e441
SR
450static struct dentry *event_trace_events_dir(void)
451{
452 static struct dentry *d_tracer;
453 static struct dentry *d_events;
454
455 if (d_events)
456 return d_events;
457
458 d_tracer = tracing_init_dentry();
459 if (!d_tracer)
460 return NULL;
461
462 d_events = debugfs_create_dir("events", d_tracer);
463 if (!d_events)
464 pr_warning("Could not create debugfs "
465 "'events' directory\n");
466
467 return d_events;
468}
469
6ecc2d1c
SR
470struct event_subsystem {
471 struct list_head list;
472 const char *name;
473 struct dentry *entry;
474};
475
476static LIST_HEAD(event_subsystems);
477
478static struct dentry *
479event_subsystem_dir(const char *name, struct dentry *d_events)
480{
481 struct event_subsystem *system;
482
483 /* First see if we did not already create this dir */
484 list_for_each_entry(system, &event_subsystems, list) {
485 if (strcmp(system->name, name) == 0)
486 return system->entry;
487 }
488
489 /* need to create new entry */
490 system = kmalloc(sizeof(*system), GFP_KERNEL);
491 if (!system) {
492 pr_warning("No memory to create event subsystem %s\n",
493 name);
494 return d_events;
495 }
496
497 system->entry = debugfs_create_dir(name, d_events);
498 if (!system->entry) {
499 pr_warning("Could not create event subsystem %s\n",
500 name);
501 kfree(system);
502 return d_events;
503 }
504
505 system->name = name;
506 list_add(&system->list, &event_subsystems);
507
508 return system->entry;
509}
510
1473e441
SR
511static int
512event_create_dir(struct ftrace_event_call *call, struct dentry *d_events)
513{
514 struct dentry *entry;
fd994989 515 int ret;
1473e441 516
6ecc2d1c
SR
517 /*
518 * If the trace point header did not define TRACE_SYSTEM
519 * then the system would be called "TRACE_SYSTEM".
520 */
521 if (strcmp(call->system, "TRACE_SYSTEM") != 0)
522 d_events = event_subsystem_dir(call->system, d_events);
523
fd994989
SR
524 if (call->raw_init) {
525 ret = call->raw_init();
526 if (ret < 0) {
527 pr_warning("Could not initialize trace point"
528 " events/%s\n", call->name);
529 return ret;
530 }
531 }
532
1473e441
SR
533 call->dir = debugfs_create_dir(call->name, d_events);
534 if (!call->dir) {
535 pr_warning("Could not create debugfs "
536 "'%s' directory\n", call->name);
537 return -1;
538 }
539
770cb243
SR
540 if (call->regfunc) {
541 entry = debugfs_create_file("enable", 0644, call->dir, call,
542 &ftrace_enable_fops);
543 if (!entry)
544 pr_warning("Could not create debugfs "
545 "'%s/enable' entry\n", call->name);
546 }
1473e441 547
981d081e
SR
548 /* A trace may not want to export its format */
549 if (!call->show_format)
550 return 0;
551
552 entry = debugfs_create_file("format", 0444, call->dir, call,
553 &ftrace_event_format_fops);
554 if (!entry)
555 pr_warning("Could not create debugfs "
556 "'%s/format' entry\n", call->name);
fd994989 557
1473e441
SR
558 return 0;
559}
560
b77e38aa
SR
561static __init int event_trace_init(void)
562{
1473e441 563 struct ftrace_event_call *call = __start_ftrace_events;
b77e38aa
SR
564 struct dentry *d_tracer;
565 struct dentry *entry;
1473e441 566 struct dentry *d_events;
b77e38aa
SR
567
568 d_tracer = tracing_init_dentry();
569 if (!d_tracer)
570 return 0;
571
b77e38aa
SR
572 entry = debugfs_create_file("set_event", 0644, d_tracer,
573 (void *)&show_set_event_seq_ops,
574 &ftrace_set_event_fops);
575 if (!entry)
576 pr_warning("Could not create debugfs "
577 "'set_event' entry\n");
578
1473e441
SR
579 d_events = event_trace_events_dir();
580 if (!d_events)
581 return 0;
582
583 events_for_each(call) {
584 /* The linker may leave blanks */
585 if (!call->name)
586 continue;
587 event_create_dir(call, d_events);
588 }
589
b77e38aa
SR
590 return 0;
591}
592fs_initcall(event_trace_init);
This page took 0.056247 seconds and 5 git commands to generate.