1
2
3
4
5
6
7
8#include <linux/module.h>
9#include <linux/kallsyms.h>
10#include <linux/security.h>
11#include <linux/mutex.h>
12#include <linux/slab.h>
13#include <linux/stacktrace.h>
14#include <linux/rculist.h>
15#include <linux/tracefs.h>
16
17
18#include <linux/trace_events.h>
19#include <trace/events/mmflags.h>
20
21#include "trace_synth.h"
22
23static int create_synth_event(int argc, const char **argv);
24static int synth_event_show(struct seq_file *m, struct dyn_event *ev);
25static int synth_event_release(struct dyn_event *ev);
26static bool synth_event_is_busy(struct dyn_event *ev);
27static bool synth_event_match(const char *system, const char *event,
28 int argc, const char **argv, struct dyn_event *ev);
29
30static struct dyn_event_operations synth_event_ops = {
31 .create = create_synth_event,
32 .show = synth_event_show,
33 .is_busy = synth_event_is_busy,
34 .free = synth_event_release,
35 .match = synth_event_match,
36};
37
38static bool is_synth_event(struct dyn_event *ev)
39{
40 return ev->ops == &synth_event_ops;
41}
42
43static struct synth_event *to_synth_event(struct dyn_event *ev)
44{
45 return container_of(ev, struct synth_event, devent);
46}
47
48static bool synth_event_is_busy(struct dyn_event *ev)
49{
50 struct synth_event *event = to_synth_event(ev);
51
52 return event->ref != 0;
53}
54
55static bool synth_event_match(const char *system, const char *event,
56 int argc, const char **argv, struct dyn_event *ev)
57{
58 struct synth_event *sev = to_synth_event(ev);
59
60 return strcmp(sev->name, event) == 0 &&
61 (!system || strcmp(system, SYNTH_SYSTEM) == 0);
62}
63
64struct synth_trace_event {
65 struct trace_entry ent;
66 u64 fields[];
67};
68
69static int synth_event_define_fields(struct trace_event_call *call)
70{
71 struct synth_trace_event trace;
72 int offset = offsetof(typeof(trace), fields);
73 struct synth_event *event = call->data;
74 unsigned int i, size, n_u64;
75 char *name, *type;
76 bool is_signed;
77 int ret = 0;
78
79 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
80 size = event->fields[i]->size;
81 is_signed = event->fields[i]->is_signed;
82 type = event->fields[i]->type;
83 name = event->fields[i]->name;
84 ret = trace_define_field(call, type, name, offset, size,
85 is_signed, FILTER_OTHER);
86 if (ret)
87 break;
88
89 event->fields[i]->offset = n_u64;
90
91 if (event->fields[i]->is_string) {
92 offset += STR_VAR_LEN_MAX;
93 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
94 } else {
95 offset += sizeof(u64);
96 n_u64++;
97 }
98 }
99
100 event->n_u64 = n_u64;
101
102 return ret;
103}
104
105static bool synth_field_signed(char *type)
106{
107 if (str_has_prefix(type, "u"))
108 return false;
109 if (strcmp(type, "gfp_t") == 0)
110 return false;
111
112 return true;
113}
114
115static int synth_field_is_string(char *type)
116{
117 if (strstr(type, "char[") != NULL)
118 return true;
119
120 return false;
121}
122
123static int synth_field_string_size(char *type)
124{
125 char buf[4], *end, *start;
126 unsigned int len;
127 int size, err;
128
129 start = strstr(type, "char[");
130 if (start == NULL)
131 return -EINVAL;
132 start += sizeof("char[") - 1;
133
134 end = strchr(type, ']');
135 if (!end || end < start)
136 return -EINVAL;
137
138 len = end - start;
139 if (len > 3)
140 return -EINVAL;
141
142 strncpy(buf, start, len);
143 buf[len] = '\0';
144
145 err = kstrtouint(buf, 0, &size);
146 if (err)
147 return err;
148
149 if (size > STR_VAR_LEN_MAX)
150 return -EINVAL;
151
152 return size;
153}
154
155static int synth_field_size(char *type)
156{
157 int size = 0;
158
159 if (strcmp(type, "s64") == 0)
160 size = sizeof(s64);
161 else if (strcmp(type, "u64") == 0)
162 size = sizeof(u64);
163 else if (strcmp(type, "s32") == 0)
164 size = sizeof(s32);
165 else if (strcmp(type, "u32") == 0)
166 size = sizeof(u32);
167 else if (strcmp(type, "s16") == 0)
168 size = sizeof(s16);
169 else if (strcmp(type, "u16") == 0)
170 size = sizeof(u16);
171 else if (strcmp(type, "s8") == 0)
172 size = sizeof(s8);
173 else if (strcmp(type, "u8") == 0)
174 size = sizeof(u8);
175 else if (strcmp(type, "char") == 0)
176 size = sizeof(char);
177 else if (strcmp(type, "unsigned char") == 0)
178 size = sizeof(unsigned char);
179 else if (strcmp(type, "int") == 0)
180 size = sizeof(int);
181 else if (strcmp(type, "unsigned int") == 0)
182 size = sizeof(unsigned int);
183 else if (strcmp(type, "long") == 0)
184 size = sizeof(long);
185 else if (strcmp(type, "unsigned long") == 0)
186 size = sizeof(unsigned long);
187 else if (strcmp(type, "pid_t") == 0)
188 size = sizeof(pid_t);
189 else if (strcmp(type, "gfp_t") == 0)
190 size = sizeof(gfp_t);
191 else if (synth_field_is_string(type))
192 size = synth_field_string_size(type);
193
194 return size;
195}
196
197static const char *synth_field_fmt(char *type)
198{
199 const char *fmt = "%llu";
200
201 if (strcmp(type, "s64") == 0)
202 fmt = "%lld";
203 else if (strcmp(type, "u64") == 0)
204 fmt = "%llu";
205 else if (strcmp(type, "s32") == 0)
206 fmt = "%d";
207 else if (strcmp(type, "u32") == 0)
208 fmt = "%u";
209 else if (strcmp(type, "s16") == 0)
210 fmt = "%d";
211 else if (strcmp(type, "u16") == 0)
212 fmt = "%u";
213 else if (strcmp(type, "s8") == 0)
214 fmt = "%d";
215 else if (strcmp(type, "u8") == 0)
216 fmt = "%u";
217 else if (strcmp(type, "char") == 0)
218 fmt = "%d";
219 else if (strcmp(type, "unsigned char") == 0)
220 fmt = "%u";
221 else if (strcmp(type, "int") == 0)
222 fmt = "%d";
223 else if (strcmp(type, "unsigned int") == 0)
224 fmt = "%u";
225 else if (strcmp(type, "long") == 0)
226 fmt = "%ld";
227 else if (strcmp(type, "unsigned long") == 0)
228 fmt = "%lu";
229 else if (strcmp(type, "pid_t") == 0)
230 fmt = "%d";
231 else if (strcmp(type, "gfp_t") == 0)
232 fmt = "%x";
233 else if (synth_field_is_string(type))
234 fmt = "%s";
235
236 return fmt;
237}
238
239static void print_synth_event_num_val(struct trace_seq *s,
240 char *print_fmt, char *name,
241 int size, u64 val, char *space)
242{
243 switch (size) {
244 case 1:
245 trace_seq_printf(s, print_fmt, name, (u8)val, space);
246 break;
247
248 case 2:
249 trace_seq_printf(s, print_fmt, name, (u16)val, space);
250 break;
251
252 case 4:
253 trace_seq_printf(s, print_fmt, name, (u32)val, space);
254 break;
255
256 default:
257 trace_seq_printf(s, print_fmt, name, val, space);
258 break;
259 }
260}
261
262static enum print_line_t print_synth_event(struct trace_iterator *iter,
263 int flags,
264 struct trace_event *event)
265{
266 struct trace_array *tr = iter->tr;
267 struct trace_seq *s = &iter->seq;
268 struct synth_trace_event *entry;
269 struct synth_event *se;
270 unsigned int i, n_u64;
271 char print_fmt[32];
272 const char *fmt;
273
274 entry = (struct synth_trace_event *)iter->ent;
275 se = container_of(event, struct synth_event, call.event);
276
277 trace_seq_printf(s, "%s: ", se->name);
278
279 for (i = 0, n_u64 = 0; i < se->n_fields; i++) {
280 if (trace_seq_has_overflowed(s))
281 goto end;
282
283 fmt = synth_field_fmt(se->fields[i]->type);
284
285
286 if (tr && tr->trace_flags & TRACE_ITER_VERBOSE)
287 trace_seq_printf(s, "%s ", fmt);
288
289 snprintf(print_fmt, sizeof(print_fmt), "%%s=%s%%s", fmt);
290
291
292 if (se->fields[i]->is_string) {
293 trace_seq_printf(s, print_fmt, se->fields[i]->name,
294 (char *)&entry->fields[n_u64],
295 i == se->n_fields - 1 ? "" : " ");
296 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
297 } else {
298 struct trace_print_flags __flags[] = {
299 __def_gfpflag_names, {-1, NULL} };
300 char *space = (i == se->n_fields - 1 ? "" : " ");
301
302 print_synth_event_num_val(s, print_fmt,
303 se->fields[i]->name,
304 se->fields[i]->size,
305 entry->fields[n_u64],
306 space);
307
308 if (strcmp(se->fields[i]->type, "gfp_t") == 0) {
309 trace_seq_puts(s, " (");
310 trace_print_flags_seq(s, "|",
311 entry->fields[n_u64],
312 __flags);
313 trace_seq_putc(s, ')');
314 }
315 n_u64++;
316 }
317 }
318end:
319 trace_seq_putc(s, '\n');
320
321 return trace_handle_return(s);
322}
323
324static struct trace_event_functions synth_event_funcs = {
325 .trace = print_synth_event
326};
327
328static notrace void trace_event_raw_event_synth(void *__data,
329 u64 *var_ref_vals,
330 unsigned int *var_ref_idx)
331{
332 struct trace_event_file *trace_file = __data;
333 struct synth_trace_event *entry;
334 struct trace_event_buffer fbuffer;
335 struct trace_buffer *buffer;
336 struct synth_event *event;
337 unsigned int i, n_u64, val_idx;
338 int fields_size = 0;
339
340 event = trace_file->event_call->data;
341
342 if (trace_trigger_soft_disabled(trace_file))
343 return;
344
345 fields_size = event->n_u64 * sizeof(u64);
346
347
348
349
350
351 buffer = trace_file->tr->array_buffer.buffer;
352 ring_buffer_nest_start(buffer);
353
354 entry = trace_event_buffer_reserve(&fbuffer, trace_file,
355 sizeof(*entry) + fields_size);
356 if (!entry)
357 goto out;
358
359 for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
360 val_idx = var_ref_idx[i];
361 if (event->fields[i]->is_string) {
362 char *str_val = (char *)(long)var_ref_vals[val_idx];
363 char *str_field = (char *)&entry->fields[n_u64];
364
365 strscpy(str_field, str_val, STR_VAR_LEN_MAX);
366 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
367 } else {
368 struct synth_field *field = event->fields[i];
369 u64 val = var_ref_vals[val_idx];
370
371 switch (field->size) {
372 case 1:
373 *(u8 *)&entry->fields[n_u64] = (u8)val;
374 break;
375
376 case 2:
377 *(u16 *)&entry->fields[n_u64] = (u16)val;
378 break;
379
380 case 4:
381 *(u32 *)&entry->fields[n_u64] = (u32)val;
382 break;
383
384 default:
385 entry->fields[n_u64] = val;
386 break;
387 }
388 n_u64++;
389 }
390 }
391
392 trace_event_buffer_commit(&fbuffer);
393out:
394 ring_buffer_nest_end(buffer);
395}
396
397static void free_synth_event_print_fmt(struct trace_event_call *call)
398{
399 if (call) {
400 kfree(call->print_fmt);
401 call->print_fmt = NULL;
402 }
403}
404
405static int __set_synth_event_print_fmt(struct synth_event *event,
406 char *buf, int len)
407{
408 const char *fmt;
409 int pos = 0;
410 int i;
411
412
413#define LEN_OR_ZERO (len ? len - pos : 0)
414
415 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
416 for (i = 0; i < event->n_fields; i++) {
417 fmt = synth_field_fmt(event->fields[i]->type);
418 pos += snprintf(buf + pos, LEN_OR_ZERO, "%s=%s%s",
419 event->fields[i]->name, fmt,
420 i == event->n_fields - 1 ? "" : ", ");
421 }
422 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
423
424 for (i = 0; i < event->n_fields; i++) {
425 pos += snprintf(buf + pos, LEN_OR_ZERO,
426 ", REC->%s", event->fields[i]->name);
427 }
428
429#undef LEN_OR_ZERO
430
431
432 return pos;
433}
434
435static int set_synth_event_print_fmt(struct trace_event_call *call)
436{
437 struct synth_event *event = call->data;
438 char *print_fmt;
439 int len;
440
441
442 len = __set_synth_event_print_fmt(event, NULL, 0);
443
444 print_fmt = kmalloc(len + 1, GFP_KERNEL);
445 if (!print_fmt)
446 return -ENOMEM;
447
448
449 __set_synth_event_print_fmt(event, print_fmt, len + 1);
450 call->print_fmt = print_fmt;
451
452 return 0;
453}
454
455static void free_synth_field(struct synth_field *field)
456{
457 kfree(field->type);
458 kfree(field->name);
459 kfree(field);
460}
461
462static struct synth_field *parse_synth_field(int argc, const char **argv,
463 int *consumed)
464{
465 struct synth_field *field;
466 const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
467 int len, ret = 0;
468
469 if (field_type[0] == ';')
470 field_type++;
471
472 if (!strcmp(field_type, "unsigned")) {
473 if (argc < 3)
474 return ERR_PTR(-EINVAL);
475 prefix = "unsigned ";
476 field_type = argv[1];
477 field_name = argv[2];
478 *consumed = 3;
479 } else {
480 field_name = argv[1];
481 *consumed = 2;
482 }
483
484 field = kzalloc(sizeof(*field), GFP_KERNEL);
485 if (!field)
486 return ERR_PTR(-ENOMEM);
487
488 len = strlen(field_name);
489 array = strchr(field_name, '[');
490 if (array)
491 len -= strlen(array);
492 else if (field_name[len - 1] == ';')
493 len--;
494
495 field->name = kmemdup_nul(field_name, len, GFP_KERNEL);
496 if (!field->name) {
497 ret = -ENOMEM;
498 goto free;
499 }
500
501 if (field_type[0] == ';')
502 field_type++;
503 len = strlen(field_type) + 1;
504 if (array)
505 len += strlen(array);
506 if (prefix)
507 len += strlen(prefix);
508
509 field->type = kzalloc(len, GFP_KERNEL);
510 if (!field->type) {
511 ret = -ENOMEM;
512 goto free;
513 }
514 if (prefix)
515 strcat(field->type, prefix);
516 strcat(field->type, field_type);
517 if (array) {
518 strcat(field->type, array);
519 if (field->type[len - 1] == ';')
520 field->type[len - 1] = '\0';
521 }
522
523 field->size = synth_field_size(field->type);
524 if (!field->size) {
525 ret = -EINVAL;
526 goto free;
527 }
528
529 if (synth_field_is_string(field->type))
530 field->is_string = true;
531
532 field->is_signed = synth_field_signed(field->type);
533
534 out:
535 return field;
536 free:
537 free_synth_field(field);
538 field = ERR_PTR(ret);
539 goto out;
540}
541
542static void free_synth_tracepoint(struct tracepoint *tp)
543{
544 if (!tp)
545 return;
546
547 kfree(tp->name);
548 kfree(tp);
549}
550
551static struct tracepoint *alloc_synth_tracepoint(char *name)
552{
553 struct tracepoint *tp;
554
555 tp = kzalloc(sizeof(*tp), GFP_KERNEL);
556 if (!tp)
557 return ERR_PTR(-ENOMEM);
558
559 tp->name = kstrdup(name, GFP_KERNEL);
560 if (!tp->name) {
561 kfree(tp);
562 return ERR_PTR(-ENOMEM);
563 }
564
565 return tp;
566}
567
568struct synth_event *find_synth_event(const char *name)
569{
570 struct dyn_event *pos;
571 struct synth_event *event;
572
573 for_each_dyn_event(pos) {
574 if (!is_synth_event(pos))
575 continue;
576 event = to_synth_event(pos);
577 if (strcmp(event->name, name) == 0)
578 return event;
579 }
580
581 return NULL;
582}
583
584static struct trace_event_fields synth_event_fields_array[] = {
585 { .type = TRACE_FUNCTION_TYPE,
586 .define_fields = synth_event_define_fields },
587 {}
588};
589
590static int register_synth_event(struct synth_event *event)
591{
592 struct trace_event_call *call = &event->call;
593 int ret = 0;
594
595 event->call.class = &event->class;
596 event->class.system = kstrdup(SYNTH_SYSTEM, GFP_KERNEL);
597 if (!event->class.system) {
598 ret = -ENOMEM;
599 goto out;
600 }
601
602 event->tp = alloc_synth_tracepoint(event->name);
603 if (IS_ERR(event->tp)) {
604 ret = PTR_ERR(event->tp);
605 event->tp = NULL;
606 goto out;
607 }
608
609 INIT_LIST_HEAD(&call->class->fields);
610 call->event.funcs = &synth_event_funcs;
611 call->class->fields_array = synth_event_fields_array;
612
613 ret = register_trace_event(&call->event);
614 if (!ret) {
615 ret = -ENODEV;
616 goto out;
617 }
618 call->flags = TRACE_EVENT_FL_TRACEPOINT;
619 call->class->reg = trace_event_reg;
620 call->class->probe = trace_event_raw_event_synth;
621 call->data = event;
622 call->tp = event->tp;
623
624 ret = trace_add_event_call(call);
625 if (ret) {
626 pr_warn("Failed to register synthetic event: %s\n",
627 trace_event_name(call));
628 goto err;
629 }
630
631 ret = set_synth_event_print_fmt(call);
632 if (ret < 0) {
633 trace_remove_event_call(call);
634 goto err;
635 }
636 out:
637 return ret;
638 err:
639 unregister_trace_event(&call->event);
640 goto out;
641}
642
643static int unregister_synth_event(struct synth_event *event)
644{
645 struct trace_event_call *call = &event->call;
646 int ret;
647
648 ret = trace_remove_event_call(call);
649
650 return ret;
651}
652
653static void free_synth_event(struct synth_event *event)
654{
655 unsigned int i;
656
657 if (!event)
658 return;
659
660 for (i = 0; i < event->n_fields; i++)
661 free_synth_field(event->fields[i]);
662
663 kfree(event->fields);
664 kfree(event->name);
665 kfree(event->class.system);
666 free_synth_tracepoint(event->tp);
667 free_synth_event_print_fmt(&event->call);
668 kfree(event);
669}
670
671static struct synth_event *alloc_synth_event(const char *name, int n_fields,
672 struct synth_field **fields)
673{
674 struct synth_event *event;
675 unsigned int i;
676
677 event = kzalloc(sizeof(*event), GFP_KERNEL);
678 if (!event) {
679 event = ERR_PTR(-ENOMEM);
680 goto out;
681 }
682
683 event->name = kstrdup(name, GFP_KERNEL);
684 if (!event->name) {
685 kfree(event);
686 event = ERR_PTR(-ENOMEM);
687 goto out;
688 }
689
690 event->fields = kcalloc(n_fields, sizeof(*event->fields), GFP_KERNEL);
691 if (!event->fields) {
692 free_synth_event(event);
693 event = ERR_PTR(-ENOMEM);
694 goto out;
695 }
696
697 dyn_event_init(&event->devent, &synth_event_ops);
698
699 for (i = 0; i < n_fields; i++)
700 event->fields[i] = fields[i];
701
702 event->n_fields = n_fields;
703 out:
704 return event;
705}
706
707static int synth_event_check_arg_fn(void *data)
708{
709 struct dynevent_arg_pair *arg_pair = data;
710 int size;
711
712 size = synth_field_size((char *)arg_pair->lhs);
713
714 return size ? 0 : -EINVAL;
715}
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731int synth_event_add_field(struct dynevent_cmd *cmd, const char *type,
732 const char *name)
733{
734 struct dynevent_arg_pair arg_pair;
735 int ret;
736
737 if (cmd->type != DYNEVENT_TYPE_SYNTH)
738 return -EINVAL;
739
740 if (!type || !name)
741 return -EINVAL;
742
743 dynevent_arg_pair_init(&arg_pair, 0, ';');
744
745 arg_pair.lhs = type;
746 arg_pair.rhs = name;
747
748 ret = dynevent_arg_pair_add(cmd, &arg_pair, synth_event_check_arg_fn);
749 if (ret)
750 return ret;
751
752 if (++cmd->n_fields > SYNTH_FIELDS_MAX)
753 ret = -EINVAL;
754
755 return ret;
756}
757EXPORT_SYMBOL_GPL(synth_event_add_field);
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775int synth_event_add_field_str(struct dynevent_cmd *cmd, const char *type_name)
776{
777 struct dynevent_arg arg;
778 int ret;
779
780 if (cmd->type != DYNEVENT_TYPE_SYNTH)
781 return -EINVAL;
782
783 if (!type_name)
784 return -EINVAL;
785
786 dynevent_arg_init(&arg, ';');
787
788 arg.str = type_name;
789
790 ret = dynevent_arg_add(cmd, &arg, NULL);
791 if (ret)
792 return ret;
793
794 if (++cmd->n_fields > SYNTH_FIELDS_MAX)
795 ret = -EINVAL;
796
797 return ret;
798}
799EXPORT_SYMBOL_GPL(synth_event_add_field_str);
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818int synth_event_add_fields(struct dynevent_cmd *cmd,
819 struct synth_field_desc *fields,
820 unsigned int n_fields)
821{
822 unsigned int i;
823 int ret = 0;
824
825 for (i = 0; i < n_fields; i++) {
826 if (fields[i].type == NULL || fields[i].name == NULL) {
827 ret = -EINVAL;
828 break;
829 }
830
831 ret = synth_event_add_field(cmd, fields[i].type, fields[i].name);
832 if (ret)
833 break;
834 }
835
836 return ret;
837}
838EXPORT_SYMBOL_GPL(synth_event_add_fields);
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868int __synth_event_gen_cmd_start(struct dynevent_cmd *cmd, const char *name,
869 struct module *mod, ...)
870{
871 struct dynevent_arg arg;
872 va_list args;
873 int ret;
874
875 cmd->event_name = name;
876 cmd->private_data = mod;
877
878 if (cmd->type != DYNEVENT_TYPE_SYNTH)
879 return -EINVAL;
880
881 dynevent_arg_init(&arg, 0);
882 arg.str = name;
883 ret = dynevent_arg_add(cmd, &arg, NULL);
884 if (ret)
885 return ret;
886
887 va_start(args, mod);
888 for (;;) {
889 const char *type, *name;
890
891 type = va_arg(args, const char *);
892 if (!type)
893 break;
894 name = va_arg(args, const char *);
895 if (!name)
896 break;
897
898 if (++cmd->n_fields > SYNTH_FIELDS_MAX) {
899 ret = -EINVAL;
900 break;
901 }
902
903 ret = synth_event_add_field(cmd, type, name);
904 if (ret)
905 break;
906 }
907 va_end(args);
908
909 return ret;
910}
911EXPORT_SYMBOL_GPL(__synth_event_gen_cmd_start);
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937int synth_event_gen_cmd_array_start(struct dynevent_cmd *cmd, const char *name,
938 struct module *mod,
939 struct synth_field_desc *fields,
940 unsigned int n_fields)
941{
942 struct dynevent_arg arg;
943 unsigned int i;
944 int ret = 0;
945
946 cmd->event_name = name;
947 cmd->private_data = mod;
948
949 if (cmd->type != DYNEVENT_TYPE_SYNTH)
950 return -EINVAL;
951
952 if (n_fields > SYNTH_FIELDS_MAX)
953 return -EINVAL;
954
955 dynevent_arg_init(&arg, 0);
956 arg.str = name;
957 ret = dynevent_arg_add(cmd, &arg, NULL);
958 if (ret)
959 return ret;
960
961 for (i = 0; i < n_fields; i++) {
962 if (fields[i].type == NULL || fields[i].name == NULL)
963 return -EINVAL;
964
965 ret = synth_event_add_field(cmd, fields[i].type, fields[i].name);
966 if (ret)
967 break;
968 }
969
970 return ret;
971}
972EXPORT_SYMBOL_GPL(synth_event_gen_cmd_array_start);
973
974static int __create_synth_event(int argc, const char *name, const char **argv)
975{
976 struct synth_field *field, *fields[SYNTH_FIELDS_MAX];
977 struct synth_event *event = NULL;
978 int i, consumed = 0, n_fields = 0, ret = 0;
979
980
981
982
983
984
985
986
987 if (name[0] == '\0' || argc < 1)
988 return -EINVAL;
989
990 mutex_lock(&event_mutex);
991
992 event = find_synth_event(name);
993 if (event) {
994 ret = -EEXIST;
995 goto out;
996 }
997
998 for (i = 0; i < argc - 1; i++) {
999 if (strcmp(argv[i], ";") == 0)
1000 continue;
1001 if (n_fields == SYNTH_FIELDS_MAX) {
1002 ret = -EINVAL;
1003 goto err;
1004 }
1005
1006 field = parse_synth_field(argc - i, &argv[i], &consumed);
1007 if (IS_ERR(field)) {
1008 ret = PTR_ERR(field);
1009 goto err;
1010 }
1011 fields[n_fields++] = field;
1012 i += consumed - 1;
1013 }
1014
1015 if (i < argc && strcmp(argv[i], ";") != 0) {
1016 ret = -EINVAL;
1017 goto err;
1018 }
1019
1020 event = alloc_synth_event(name, n_fields, fields);
1021 if (IS_ERR(event)) {
1022 ret = PTR_ERR(event);
1023 event = NULL;
1024 goto err;
1025 }
1026 ret = register_synth_event(event);
1027 if (!ret)
1028 dyn_event_add(&event->devent);
1029 else
1030 free_synth_event(event);
1031 out:
1032 mutex_unlock(&event_mutex);
1033
1034 return ret;
1035 err:
1036 for (i = 0; i < n_fields; i++)
1037 free_synth_field(fields[i]);
1038
1039 goto out;
1040}
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066int synth_event_create(const char *name, struct synth_field_desc *fields,
1067 unsigned int n_fields, struct module *mod)
1068{
1069 struct dynevent_cmd cmd;
1070 char *buf;
1071 int ret;
1072
1073 buf = kzalloc(MAX_DYNEVENT_CMD_LEN, GFP_KERNEL);
1074 if (!buf)
1075 return -ENOMEM;
1076
1077 synth_event_cmd_init(&cmd, buf, MAX_DYNEVENT_CMD_LEN);
1078
1079 ret = synth_event_gen_cmd_array_start(&cmd, name, mod,
1080 fields, n_fields);
1081 if (ret)
1082 goto out;
1083
1084 ret = synth_event_gen_cmd_end(&cmd);
1085 out:
1086 kfree(buf);
1087
1088 return ret;
1089}
1090EXPORT_SYMBOL_GPL(synth_event_create);
1091
1092static int destroy_synth_event(struct synth_event *se)
1093{
1094 int ret;
1095
1096 if (se->ref)
1097 ret = -EBUSY;
1098 else {
1099 ret = unregister_synth_event(se);
1100 if (!ret) {
1101 dyn_event_remove(&se->devent);
1102 free_synth_event(se);
1103 }
1104 }
1105
1106 return ret;
1107}
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117int synth_event_delete(const char *event_name)
1118{
1119 struct synth_event *se = NULL;
1120 struct module *mod = NULL;
1121 int ret = -ENOENT;
1122
1123 mutex_lock(&event_mutex);
1124 se = find_synth_event(event_name);
1125 if (se) {
1126 mod = se->mod;
1127 ret = destroy_synth_event(se);
1128 }
1129 mutex_unlock(&event_mutex);
1130
1131 if (mod) {
1132 mutex_lock(&trace_types_lock);
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 tracing_reset_all_online_cpus();
1144 mutex_unlock(&trace_types_lock);
1145 }
1146
1147 return ret;
1148}
1149EXPORT_SYMBOL_GPL(synth_event_delete);
1150
1151static int create_or_delete_synth_event(int argc, char **argv)
1152{
1153 const char *name = argv[0];
1154 int ret;
1155
1156
1157 if (name[0] == '!') {
1158 ret = synth_event_delete(name + 1);
1159 return ret;
1160 }
1161
1162 ret = __create_synth_event(argc - 1, name, (const char **)argv + 1);
1163 return ret == -ECANCELED ? -EINVAL : ret;
1164}
1165
1166static int synth_event_run_command(struct dynevent_cmd *cmd)
1167{
1168 struct synth_event *se;
1169 int ret;
1170
1171 ret = trace_run_command(cmd->seq.buffer, create_or_delete_synth_event);
1172 if (ret)
1173 return ret;
1174
1175 se = find_synth_event(cmd->event_name);
1176 if (WARN_ON(!se))
1177 return -ENOENT;
1178
1179 se->mod = cmd->private_data;
1180
1181 return ret;
1182}
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193void synth_event_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen)
1194{
1195 dynevent_cmd_init(cmd, buf, maxlen, DYNEVENT_TYPE_SYNTH,
1196 synth_event_run_command);
1197}
1198EXPORT_SYMBOL_GPL(synth_event_cmd_init);
1199
1200static inline int
1201__synth_event_trace_start(struct trace_event_file *file,
1202 struct synth_event_trace_state *trace_state)
1203{
1204 int entry_size, fields_size = 0;
1205 int ret = 0;
1206
1207 memset(trace_state, '\0', sizeof(*trace_state));
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 if (!(file->flags & EVENT_FILE_FL_ENABLED) ||
1219 trace_trigger_soft_disabled(file)) {
1220 trace_state->disabled = true;
1221 ret = -ENOENT;
1222 goto out;
1223 }
1224
1225 trace_state->event = file->event_call->data;
1226
1227 fields_size = trace_state->event->n_u64 * sizeof(u64);
1228
1229
1230
1231
1232
1233 trace_state->buffer = file->tr->array_buffer.buffer;
1234 ring_buffer_nest_start(trace_state->buffer);
1235
1236 entry_size = sizeof(*trace_state->entry) + fields_size;
1237 trace_state->entry = trace_event_buffer_reserve(&trace_state->fbuffer,
1238 file,
1239 entry_size);
1240 if (!trace_state->entry) {
1241 ring_buffer_nest_end(trace_state->buffer);
1242 ret = -EINVAL;
1243 }
1244out:
1245 return ret;
1246}
1247
1248static inline void
1249__synth_event_trace_end(struct synth_event_trace_state *trace_state)
1250{
1251 trace_event_buffer_commit(&trace_state->fbuffer);
1252
1253 ring_buffer_nest_end(trace_state->buffer);
1254}
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275int synth_event_trace(struct trace_event_file *file, unsigned int n_vals, ...)
1276{
1277 struct synth_event_trace_state state;
1278 unsigned int i, n_u64;
1279 va_list args;
1280 int ret;
1281
1282 ret = __synth_event_trace_start(file, &state);
1283 if (ret) {
1284 if (ret == -ENOENT)
1285 ret = 0;
1286 return ret;
1287 }
1288
1289 if (n_vals != state.event->n_fields) {
1290 ret = -EINVAL;
1291 goto out;
1292 }
1293
1294 va_start(args, n_vals);
1295 for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
1296 u64 val;
1297
1298 val = va_arg(args, u64);
1299
1300 if (state.event->fields[i]->is_string) {
1301 char *str_val = (char *)(long)val;
1302 char *str_field = (char *)&state.entry->fields[n_u64];
1303
1304 strscpy(str_field, str_val, STR_VAR_LEN_MAX);
1305 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
1306 } else {
1307 struct synth_field *field = state.event->fields[i];
1308
1309 switch (field->size) {
1310 case 1:
1311 *(u8 *)&state.entry->fields[n_u64] = (u8)val;
1312 break;
1313
1314 case 2:
1315 *(u16 *)&state.entry->fields[n_u64] = (u16)val;
1316 break;
1317
1318 case 4:
1319 *(u32 *)&state.entry->fields[n_u64] = (u32)val;
1320 break;
1321
1322 default:
1323 state.entry->fields[n_u64] = val;
1324 break;
1325 }
1326 n_u64++;
1327 }
1328 }
1329 va_end(args);
1330out:
1331 __synth_event_trace_end(&state);
1332
1333 return ret;
1334}
1335EXPORT_SYMBOL_GPL(synth_event_trace);
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355int synth_event_trace_array(struct trace_event_file *file, u64 *vals,
1356 unsigned int n_vals)
1357{
1358 struct synth_event_trace_state state;
1359 unsigned int i, n_u64;
1360 int ret;
1361
1362 ret = __synth_event_trace_start(file, &state);
1363 if (ret) {
1364 if (ret == -ENOENT)
1365 ret = 0;
1366 return ret;
1367 }
1368
1369 if (n_vals != state.event->n_fields) {
1370 ret = -EINVAL;
1371 goto out;
1372 }
1373
1374 for (i = 0, n_u64 = 0; i < state.event->n_fields; i++) {
1375 if (state.event->fields[i]->is_string) {
1376 char *str_val = (char *)(long)vals[i];
1377 char *str_field = (char *)&state.entry->fields[n_u64];
1378
1379 strscpy(str_field, str_val, STR_VAR_LEN_MAX);
1380 n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
1381 } else {
1382 struct synth_field *field = state.event->fields[i];
1383 u64 val = vals[i];
1384
1385 switch (field->size) {
1386 case 1:
1387 *(u8 *)&state.entry->fields[n_u64] = (u8)val;
1388 break;
1389
1390 case 2:
1391 *(u16 *)&state.entry->fields[n_u64] = (u16)val;
1392 break;
1393
1394 case 4:
1395 *(u32 *)&state.entry->fields[n_u64] = (u32)val;
1396 break;
1397
1398 default:
1399 state.entry->fields[n_u64] = val;
1400 break;
1401 }
1402 n_u64++;
1403 }
1404 }
1405out:
1406 __synth_event_trace_end(&state);
1407
1408 return ret;
1409}
1410EXPORT_SYMBOL_GPL(synth_event_trace_array);
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440int synth_event_trace_start(struct trace_event_file *file,
1441 struct synth_event_trace_state *trace_state)
1442{
1443 int ret;
1444
1445 if (!trace_state)
1446 return -EINVAL;
1447
1448 ret = __synth_event_trace_start(file, trace_state);
1449 if (ret == -ENOENT)
1450 ret = 0;
1451
1452 return ret;
1453}
1454EXPORT_SYMBOL_GPL(synth_event_trace_start);
1455
1456static int __synth_event_add_val(const char *field_name, u64 val,
1457 struct synth_event_trace_state *trace_state)
1458{
1459 struct synth_field *field = NULL;
1460 struct synth_trace_event *entry;
1461 struct synth_event *event;
1462 int i, ret = 0;
1463
1464 if (!trace_state) {
1465 ret = -EINVAL;
1466 goto out;
1467 }
1468
1469
1470 if (field_name) {
1471 if (trace_state->add_next) {
1472 ret = -EINVAL;
1473 goto out;
1474 }
1475 trace_state->add_name = true;
1476 } else {
1477 if (trace_state->add_name) {
1478 ret = -EINVAL;
1479 goto out;
1480 }
1481 trace_state->add_next = true;
1482 }
1483
1484 if (trace_state->disabled)
1485 goto out;
1486
1487 event = trace_state->event;
1488 if (trace_state->add_name) {
1489 for (i = 0; i < event->n_fields; i++) {
1490 field = event->fields[i];
1491 if (strcmp(field->name, field_name) == 0)
1492 break;
1493 }
1494 if (!field) {
1495 ret = -EINVAL;
1496 goto out;
1497 }
1498 } else {
1499 if (trace_state->cur_field >= event->n_fields) {
1500 ret = -EINVAL;
1501 goto out;
1502 }
1503 field = event->fields[trace_state->cur_field++];
1504 }
1505
1506 entry = trace_state->entry;
1507 if (field->is_string) {
1508 char *str_val = (char *)(long)val;
1509 char *str_field;
1510
1511 if (!str_val) {
1512 ret = -EINVAL;
1513 goto out;
1514 }
1515
1516 str_field = (char *)&entry->fields[field->offset];
1517 strscpy(str_field, str_val, STR_VAR_LEN_MAX);
1518 } else {
1519 switch (field->size) {
1520 case 1:
1521 *(u8 *)&trace_state->entry->fields[field->offset] = (u8)val;
1522 break;
1523
1524 case 2:
1525 *(u16 *)&trace_state->entry->fields[field->offset] = (u16)val;
1526 break;
1527
1528 case 4:
1529 *(u32 *)&trace_state->entry->fields[field->offset] = (u32)val;
1530 break;
1531
1532 default:
1533 trace_state->entry->fields[field->offset] = val;
1534 break;
1535 }
1536 }
1537 out:
1538 return ret;
1539}
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569int synth_event_add_next_val(u64 val,
1570 struct synth_event_trace_state *trace_state)
1571{
1572 return __synth_event_add_val(NULL, val, trace_state);
1573}
1574EXPORT_SYMBOL_GPL(synth_event_add_next_val);
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604int synth_event_add_val(const char *field_name, u64 val,
1605 struct synth_event_trace_state *trace_state)
1606{
1607 return __synth_event_add_val(field_name, val, trace_state);
1608}
1609EXPORT_SYMBOL_GPL(synth_event_add_val);
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631int synth_event_trace_end(struct synth_event_trace_state *trace_state)
1632{
1633 if (!trace_state)
1634 return -EINVAL;
1635
1636 __synth_event_trace_end(trace_state);
1637
1638 return 0;
1639}
1640EXPORT_SYMBOL_GPL(synth_event_trace_end);
1641
1642static int create_synth_event(int argc, const char **argv)
1643{
1644 const char *name = argv[0];
1645 int len;
1646
1647 if (name[0] != 's' || name[1] != ':')
1648 return -ECANCELED;
1649 name += 2;
1650
1651
1652 if (strchr(name, '/')) {
1653 len = str_has_prefix(name, SYNTH_SYSTEM "/");
1654 if (len == 0)
1655 return -EINVAL;
1656 name += len;
1657 }
1658 return __create_synth_event(argc - 1, name, argv + 1);
1659}
1660
1661static int synth_event_release(struct dyn_event *ev)
1662{
1663 struct synth_event *event = to_synth_event(ev);
1664 int ret;
1665
1666 if (event->ref)
1667 return -EBUSY;
1668
1669 ret = unregister_synth_event(event);
1670 if (ret)
1671 return ret;
1672
1673 dyn_event_remove(ev);
1674 free_synth_event(event);
1675 return 0;
1676}
1677
1678static int __synth_event_show(struct seq_file *m, struct synth_event *event)
1679{
1680 struct synth_field *field;
1681 unsigned int i;
1682
1683 seq_printf(m, "%s\t", event->name);
1684
1685 for (i = 0; i < event->n_fields; i++) {
1686 field = event->fields[i];
1687
1688
1689 seq_printf(m, "%s %s%s", field->type, field->name,
1690 i == event->n_fields - 1 ? "" : "; ");
1691 }
1692
1693 seq_putc(m, '\n');
1694
1695 return 0;
1696}
1697
1698static int synth_event_show(struct seq_file *m, struct dyn_event *ev)
1699{
1700 struct synth_event *event = to_synth_event(ev);
1701
1702 seq_printf(m, "s:%s/", event->class.system);
1703
1704 return __synth_event_show(m, event);
1705}
1706
1707static int synth_events_seq_show(struct seq_file *m, void *v)
1708{
1709 struct dyn_event *ev = v;
1710
1711 if (!is_synth_event(ev))
1712 return 0;
1713
1714 return __synth_event_show(m, to_synth_event(ev));
1715}
1716
1717static const struct seq_operations synth_events_seq_op = {
1718 .start = dyn_event_seq_start,
1719 .next = dyn_event_seq_next,
1720 .stop = dyn_event_seq_stop,
1721 .show = synth_events_seq_show,
1722};
1723
1724static int synth_events_open(struct inode *inode, struct file *file)
1725{
1726 int ret;
1727
1728 ret = security_locked_down(LOCKDOWN_TRACEFS);
1729 if (ret)
1730 return ret;
1731
1732 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
1733 ret = dyn_events_release_all(&synth_event_ops);
1734 if (ret < 0)
1735 return ret;
1736 }
1737
1738 return seq_open(file, &synth_events_seq_op);
1739}
1740
1741static ssize_t synth_events_write(struct file *file,
1742 const char __user *buffer,
1743 size_t count, loff_t *ppos)
1744{
1745 return trace_parse_run_command(file, buffer, count, ppos,
1746 create_or_delete_synth_event);
1747}
1748
1749static const struct file_operations synth_events_fops = {
1750 .open = synth_events_open,
1751 .write = synth_events_write,
1752 .read = seq_read,
1753 .llseek = seq_lseek,
1754 .release = seq_release,
1755};
1756
1757static __init int trace_events_synth_init(void)
1758{
1759 struct dentry *entry = NULL;
1760 struct dentry *d_tracer;
1761 int err = 0;
1762
1763 err = dyn_event_register(&synth_event_ops);
1764 if (err) {
1765 pr_warn("Could not register synth_event_ops\n");
1766 return err;
1767 }
1768
1769 d_tracer = tracing_init_dentry();
1770 if (IS_ERR(d_tracer)) {
1771 err = PTR_ERR(d_tracer);
1772 goto err;
1773 }
1774
1775 entry = tracefs_create_file("synthetic_events", 0644, d_tracer,
1776 NULL, &synth_events_fops);
1777 if (!entry) {
1778 err = -ENODEV;
1779 goto err;
1780 }
1781
1782 return err;
1783 err:
1784 pr_warn("Could not create tracefs 'synthetic_events' entry\n");
1785
1786 return err;
1787}
1788
1789fs_initcall(trace_events_synth_init);
1790