• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Fprobe-based tracing events
4  * Copyright (C) 2022 Google LLC.
5  */
6 #define pr_fmt(fmt)	"trace_fprobe: " fmt
7 #include <asm/ptrace.h>
8 
9 #include <linux/fprobe.h>
10 #include <linux/module.h>
11 #include <linux/rculist.h>
12 #include <linux/security.h>
13 #include <linux/tracepoint.h>
14 #include <linux/uaccess.h>
15 
16 #include "trace_dynevent.h"
17 #include "trace_probe.h"
18 #include "trace_probe_kernel.h"
19 #include "trace_probe_tmpl.h"
20 
21 #define FPROBE_EVENT_SYSTEM "fprobes"
22 #define TRACEPOINT_EVENT_SYSTEM "tracepoints"
23 #define RETHOOK_MAXACTIVE_MAX 4096
24 #define TRACEPOINT_STUB ERR_PTR(-ENOENT)
25 
26 static int trace_fprobe_create(const char *raw_command);
27 static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev);
28 static int trace_fprobe_release(struct dyn_event *ev);
29 static bool trace_fprobe_is_busy(struct dyn_event *ev);
30 static bool trace_fprobe_match(const char *system, const char *event,
31 			int argc, const char **argv, struct dyn_event *ev);
32 
33 static struct dyn_event_operations trace_fprobe_ops = {
34 	.create = trace_fprobe_create,
35 	.show = trace_fprobe_show,
36 	.is_busy = trace_fprobe_is_busy,
37 	.free = trace_fprobe_release,
38 	.match = trace_fprobe_match,
39 };
40 
41 /*
42  * Fprobe event core functions
43  */
44 struct trace_fprobe {
45 	struct dyn_event	devent;
46 	struct fprobe		fp;
47 	const char		*symbol;
48 	struct tracepoint	*tpoint;
49 	struct module		*mod;
50 	struct trace_probe	tp;
51 };
52 
is_trace_fprobe(struct dyn_event * ev)53 static bool is_trace_fprobe(struct dyn_event *ev)
54 {
55 	return ev->ops == &trace_fprobe_ops;
56 }
57 
to_trace_fprobe(struct dyn_event * ev)58 static struct trace_fprobe *to_trace_fprobe(struct dyn_event *ev)
59 {
60 	return container_of(ev, struct trace_fprobe, devent);
61 }
62 
63 /**
64  * for_each_trace_fprobe - iterate over the trace_fprobe list
65  * @pos:	the struct trace_fprobe * for each entry
66  * @dpos:	the struct dyn_event * to use as a loop cursor
67  */
68 #define for_each_trace_fprobe(pos, dpos)	\
69 	for_each_dyn_event(dpos)		\
70 		if (is_trace_fprobe(dpos) && (pos = to_trace_fprobe(dpos)))
71 
trace_fprobe_is_return(struct trace_fprobe * tf)72 static bool trace_fprobe_is_return(struct trace_fprobe *tf)
73 {
74 	return tf->fp.exit_handler != NULL;
75 }
76 
trace_fprobe_is_tracepoint(struct trace_fprobe * tf)77 static bool trace_fprobe_is_tracepoint(struct trace_fprobe *tf)
78 {
79 	return tf->tpoint != NULL;
80 }
81 
trace_fprobe_symbol(struct trace_fprobe * tf)82 static const char *trace_fprobe_symbol(struct trace_fprobe *tf)
83 {
84 	return tf->symbol ? tf->symbol : "unknown";
85 }
86 
trace_fprobe_is_busy(struct dyn_event * ev)87 static bool trace_fprobe_is_busy(struct dyn_event *ev)
88 {
89 	struct trace_fprobe *tf = to_trace_fprobe(ev);
90 
91 	return trace_probe_is_enabled(&tf->tp);
92 }
93 
trace_fprobe_match_command_head(struct trace_fprobe * tf,int argc,const char ** argv)94 static bool trace_fprobe_match_command_head(struct trace_fprobe *tf,
95 					    int argc, const char **argv)
96 {
97 	char buf[MAX_ARGSTR_LEN + 1];
98 
99 	if (!argc)
100 		return true;
101 
102 	snprintf(buf, sizeof(buf), "%s", trace_fprobe_symbol(tf));
103 	if (strcmp(buf, argv[0]))
104 		return false;
105 	argc--; argv++;
106 
107 	return trace_probe_match_command_args(&tf->tp, argc, argv);
108 }
109 
trace_fprobe_match(const char * system,const char * event,int argc,const char ** argv,struct dyn_event * ev)110 static bool trace_fprobe_match(const char *system, const char *event,
111 			int argc, const char **argv, struct dyn_event *ev)
112 {
113 	struct trace_fprobe *tf = to_trace_fprobe(ev);
114 
115 	if (event[0] != '\0' && strcmp(trace_probe_name(&tf->tp), event))
116 		return false;
117 
118 	if (system && strcmp(trace_probe_group_name(&tf->tp), system))
119 		return false;
120 
121 	return trace_fprobe_match_command_head(tf, argc, argv);
122 }
123 
trace_fprobe_is_registered(struct trace_fprobe * tf)124 static bool trace_fprobe_is_registered(struct trace_fprobe *tf)
125 {
126 	return fprobe_is_registered(&tf->fp);
127 }
128 
129 /*
130  * Note that we don't verify the fetch_insn code, since it does not come
131  * from user space.
132  */
133 static int
process_fetch_insn(struct fetch_insn * code,void * rec,void * edata,void * dest,void * base)134 process_fetch_insn(struct fetch_insn *code, void *rec, void *edata,
135 		   void *dest, void *base)
136 {
137 	struct pt_regs *regs = rec;
138 	unsigned long val;
139 	int ret;
140 
141 retry:
142 	/* 1st stage: get value from context */
143 	switch (code->op) {
144 	case FETCH_OP_STACK:
145 		val = regs_get_kernel_stack_nth(regs, code->param);
146 		break;
147 	case FETCH_OP_STACKP:
148 		val = kernel_stack_pointer(regs);
149 		break;
150 	case FETCH_OP_RETVAL:
151 		val = regs_return_value(regs);
152 		break;
153 #ifdef CONFIG_HAVE_FUNCTION_ARG_ACCESS_API
154 	case FETCH_OP_ARG:
155 		val = regs_get_kernel_argument(regs, code->param);
156 		break;
157 	case FETCH_OP_EDATA:
158 		val = *(unsigned long *)((unsigned long)edata + code->offset);
159 		break;
160 #endif
161 	case FETCH_NOP_SYMBOL:	/* Ignore a place holder */
162 		code++;
163 		goto retry;
164 	default:
165 		ret = process_common_fetch_insn(code, &val);
166 		if (ret < 0)
167 			return ret;
168 	}
169 	code++;
170 
171 	return process_fetch_insn_bottom(code, val, dest, base);
172 }
NOKPROBE_SYMBOL(process_fetch_insn)173 NOKPROBE_SYMBOL(process_fetch_insn)
174 
175 /* function entry handler */
176 static nokprobe_inline void
177 __fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
178 		    struct pt_regs *regs,
179 		    struct trace_event_file *trace_file)
180 {
181 	struct fentry_trace_entry_head *entry;
182 	struct trace_event_call *call = trace_probe_event_call(&tf->tp);
183 	struct trace_event_buffer fbuffer;
184 	int dsize;
185 
186 	if (WARN_ON_ONCE(call != trace_file->event_call))
187 		return;
188 
189 	if (trace_trigger_soft_disabled(trace_file))
190 		return;
191 
192 	dsize = __get_data_size(&tf->tp, regs, NULL);
193 
194 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,
195 					   sizeof(*entry) + tf->tp.size + dsize);
196 	if (!entry)
197 		return;
198 
199 	fbuffer.regs = regs;
200 	entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event);
201 	entry->ip = entry_ip;
202 	store_trace_args(&entry[1], &tf->tp, regs, NULL, sizeof(*entry), dsize);
203 
204 	trace_event_buffer_commit(&fbuffer);
205 }
206 
207 static void
fentry_trace_func(struct trace_fprobe * tf,unsigned long entry_ip,struct pt_regs * regs)208 fentry_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
209 		  struct pt_regs *regs)
210 {
211 	struct event_file_link *link;
212 
213 	trace_probe_for_each_link_rcu(link, &tf->tp)
214 		__fentry_trace_func(tf, entry_ip, regs, link->file);
215 }
216 NOKPROBE_SYMBOL(fentry_trace_func);
217 
218 /* function exit handler */
trace_fprobe_entry_handler(struct fprobe * fp,unsigned long entry_ip,unsigned long ret_ip,struct pt_regs * regs,void * entry_data)219 static int trace_fprobe_entry_handler(struct fprobe *fp, unsigned long entry_ip,
220 				unsigned long ret_ip, struct pt_regs *regs,
221 				void *entry_data)
222 {
223 	struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
224 
225 	if (tf->tp.entry_arg)
226 		store_trace_entry_data(entry_data, &tf->tp, regs);
227 
228 	return 0;
229 }
NOKPROBE_SYMBOL(trace_fprobe_entry_handler)230 NOKPROBE_SYMBOL(trace_fprobe_entry_handler)
231 
232 static nokprobe_inline void
233 __fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
234 		   unsigned long ret_ip, struct pt_regs *regs,
235 		   void *entry_data, struct trace_event_file *trace_file)
236 {
237 	struct fexit_trace_entry_head *entry;
238 	struct trace_event_buffer fbuffer;
239 	struct trace_event_call *call = trace_probe_event_call(&tf->tp);
240 	int dsize;
241 
242 	if (WARN_ON_ONCE(call != trace_file->event_call))
243 		return;
244 
245 	if (trace_trigger_soft_disabled(trace_file))
246 		return;
247 
248 	dsize = __get_data_size(&tf->tp, regs, entry_data);
249 
250 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,
251 					   sizeof(*entry) + tf->tp.size + dsize);
252 	if (!entry)
253 		return;
254 
255 	fbuffer.regs = regs;
256 	entry = fbuffer.entry = ring_buffer_event_data(fbuffer.event);
257 	entry->func = entry_ip;
258 	entry->ret_ip = ret_ip;
259 	store_trace_args(&entry[1], &tf->tp, regs, entry_data, sizeof(*entry), dsize);
260 
261 	trace_event_buffer_commit(&fbuffer);
262 }
263 
264 static void
fexit_trace_func(struct trace_fprobe * tf,unsigned long entry_ip,unsigned long ret_ip,struct pt_regs * regs,void * entry_data)265 fexit_trace_func(struct trace_fprobe *tf, unsigned long entry_ip,
266 		 unsigned long ret_ip, struct pt_regs *regs, void *entry_data)
267 {
268 	struct event_file_link *link;
269 
270 	trace_probe_for_each_link_rcu(link, &tf->tp)
271 		__fexit_trace_func(tf, entry_ip, ret_ip, regs, entry_data, link->file);
272 }
273 NOKPROBE_SYMBOL(fexit_trace_func);
274 
275 #ifdef CONFIG_PERF_EVENTS
276 
fentry_perf_func(struct trace_fprobe * tf,unsigned long entry_ip,struct pt_regs * regs)277 static int fentry_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
278 			    struct pt_regs *regs)
279 {
280 	struct trace_event_call *call = trace_probe_event_call(&tf->tp);
281 	struct fentry_trace_entry_head *entry;
282 	struct hlist_head *head;
283 	int size, __size, dsize;
284 	int rctx;
285 
286 	head = this_cpu_ptr(call->perf_events);
287 	if (hlist_empty(head))
288 		return 0;
289 
290 	dsize = __get_data_size(&tf->tp, regs, NULL);
291 	__size = sizeof(*entry) + tf->tp.size + dsize;
292 	size = ALIGN(__size + sizeof(u32), sizeof(u64));
293 	size -= sizeof(u32);
294 
295 	entry = perf_trace_buf_alloc(size, NULL, &rctx);
296 	if (!entry)
297 		return 0;
298 
299 	entry->ip = entry_ip;
300 	memset(&entry[1], 0, dsize);
301 	store_trace_args(&entry[1], &tf->tp, regs, NULL, sizeof(*entry), dsize);
302 	perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs,
303 			      head, NULL);
304 	return 0;
305 }
306 NOKPROBE_SYMBOL(fentry_perf_func);
307 
308 static void
fexit_perf_func(struct trace_fprobe * tf,unsigned long entry_ip,unsigned long ret_ip,struct pt_regs * regs,void * entry_data)309 fexit_perf_func(struct trace_fprobe *tf, unsigned long entry_ip,
310 		unsigned long ret_ip, struct pt_regs *regs,
311 		void *entry_data)
312 {
313 	struct trace_event_call *call = trace_probe_event_call(&tf->tp);
314 	struct fexit_trace_entry_head *entry;
315 	struct hlist_head *head;
316 	int size, __size, dsize;
317 	int rctx;
318 
319 	head = this_cpu_ptr(call->perf_events);
320 	if (hlist_empty(head))
321 		return;
322 
323 	dsize = __get_data_size(&tf->tp, regs, entry_data);
324 	__size = sizeof(*entry) + tf->tp.size + dsize;
325 	size = ALIGN(__size + sizeof(u32), sizeof(u64));
326 	size -= sizeof(u32);
327 
328 	entry = perf_trace_buf_alloc(size, NULL, &rctx);
329 	if (!entry)
330 		return;
331 
332 	entry->func = entry_ip;
333 	entry->ret_ip = ret_ip;
334 	store_trace_args(&entry[1], &tf->tp, regs, entry_data, sizeof(*entry), dsize);
335 	perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs,
336 			      head, NULL);
337 }
338 NOKPROBE_SYMBOL(fexit_perf_func);
339 #endif	/* CONFIG_PERF_EVENTS */
340 
fentry_dispatcher(struct fprobe * fp,unsigned long entry_ip,unsigned long ret_ip,struct pt_regs * regs,void * entry_data)341 static int fentry_dispatcher(struct fprobe *fp, unsigned long entry_ip,
342 			     unsigned long ret_ip, struct pt_regs *regs,
343 			     void *entry_data)
344 {
345 	struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
346 	int ret = 0;
347 
348 	if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE))
349 		fentry_trace_func(tf, entry_ip, regs);
350 #ifdef CONFIG_PERF_EVENTS
351 	if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE))
352 		ret = fentry_perf_func(tf, entry_ip, regs);
353 #endif
354 	return ret;
355 }
356 NOKPROBE_SYMBOL(fentry_dispatcher);
357 
fexit_dispatcher(struct fprobe * fp,unsigned long entry_ip,unsigned long ret_ip,struct pt_regs * regs,void * entry_data)358 static void fexit_dispatcher(struct fprobe *fp, unsigned long entry_ip,
359 			     unsigned long ret_ip, struct pt_regs *regs,
360 			     void *entry_data)
361 {
362 	struct trace_fprobe *tf = container_of(fp, struct trace_fprobe, fp);
363 
364 	if (trace_probe_test_flag(&tf->tp, TP_FLAG_TRACE))
365 		fexit_trace_func(tf, entry_ip, ret_ip, regs, entry_data);
366 #ifdef CONFIG_PERF_EVENTS
367 	if (trace_probe_test_flag(&tf->tp, TP_FLAG_PROFILE))
368 		fexit_perf_func(tf, entry_ip, ret_ip, regs, entry_data);
369 #endif
370 }
371 NOKPROBE_SYMBOL(fexit_dispatcher);
372 
free_trace_fprobe(struct trace_fprobe * tf)373 static void free_trace_fprobe(struct trace_fprobe *tf)
374 {
375 	if (tf) {
376 		trace_probe_cleanup(&tf->tp);
377 		kfree(tf->symbol);
378 		kfree(tf);
379 	}
380 }
381 
382 /*
383  * Allocate new trace_probe and initialize it (including fprobe).
384  */
alloc_trace_fprobe(const char * group,const char * event,const char * symbol,struct tracepoint * tpoint,struct module * mod,int maxactive,int nargs,bool is_return)385 static struct trace_fprobe *alloc_trace_fprobe(const char *group,
386 					       const char *event,
387 					       const char *symbol,
388 					       struct tracepoint *tpoint,
389 					       struct module *mod,
390 					       int maxactive,
391 					       int nargs, bool is_return)
392 {
393 	struct trace_fprobe *tf;
394 	int ret = -ENOMEM;
395 
396 	tf = kzalloc(struct_size(tf, tp.args, nargs), GFP_KERNEL);
397 	if (!tf)
398 		return ERR_PTR(ret);
399 
400 	tf->symbol = kstrdup(symbol, GFP_KERNEL);
401 	if (!tf->symbol)
402 		goto error;
403 
404 	if (is_return)
405 		tf->fp.exit_handler = fexit_dispatcher;
406 	else
407 		tf->fp.entry_handler = fentry_dispatcher;
408 
409 	tf->tpoint = tpoint;
410 	tf->mod = mod;
411 	tf->fp.nr_maxactive = maxactive;
412 
413 	ret = trace_probe_init(&tf->tp, event, group, false, nargs);
414 	if (ret < 0)
415 		goto error;
416 
417 	dyn_event_init(&tf->devent, &trace_fprobe_ops);
418 	return tf;
419 error:
420 	free_trace_fprobe(tf);
421 	return ERR_PTR(ret);
422 }
423 
find_trace_fprobe(const char * event,const char * group)424 static struct trace_fprobe *find_trace_fprobe(const char *event,
425 					      const char *group)
426 {
427 	struct dyn_event *pos;
428 	struct trace_fprobe *tf;
429 
430 	for_each_trace_fprobe(tf, pos)
431 		if (strcmp(trace_probe_name(&tf->tp), event) == 0 &&
432 		    strcmp(trace_probe_group_name(&tf->tp), group) == 0)
433 			return tf;
434 	return NULL;
435 }
436 
__enable_trace_fprobe(struct trace_fprobe * tf)437 static inline int __enable_trace_fprobe(struct trace_fprobe *tf)
438 {
439 	if (trace_fprobe_is_registered(tf))
440 		enable_fprobe(&tf->fp);
441 
442 	return 0;
443 }
444 
__disable_trace_fprobe(struct trace_probe * tp)445 static void __disable_trace_fprobe(struct trace_probe *tp)
446 {
447 	struct trace_fprobe *tf;
448 
449 	list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
450 		if (!trace_fprobe_is_registered(tf))
451 			continue;
452 		disable_fprobe(&tf->fp);
453 	}
454 }
455 
456 /*
457  * Enable trace_probe
458  * if the file is NULL, enable "perf" handler, or enable "trace" handler.
459  */
enable_trace_fprobe(struct trace_event_call * call,struct trace_event_file * file)460 static int enable_trace_fprobe(struct trace_event_call *call,
461 			       struct trace_event_file *file)
462 {
463 	struct trace_probe *tp;
464 	struct trace_fprobe *tf;
465 	bool enabled;
466 	int ret = 0;
467 
468 	tp = trace_probe_primary_from_call(call);
469 	if (WARN_ON_ONCE(!tp))
470 		return -ENODEV;
471 	enabled = trace_probe_is_enabled(tp);
472 
473 	/* This also changes "enabled" state */
474 	if (file) {
475 		ret = trace_probe_add_file(tp, file);
476 		if (ret)
477 			return ret;
478 	} else
479 		trace_probe_set_flag(tp, TP_FLAG_PROFILE);
480 
481 	if (!enabled) {
482 		list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
483 			/* TODO: check the fprobe is gone */
484 			__enable_trace_fprobe(tf);
485 		}
486 	}
487 
488 	return 0;
489 }
490 
491 /*
492  * Disable trace_probe
493  * if the file is NULL, disable "perf" handler, or disable "trace" handler.
494  */
disable_trace_fprobe(struct trace_event_call * call,struct trace_event_file * file)495 static int disable_trace_fprobe(struct trace_event_call *call,
496 				struct trace_event_file *file)
497 {
498 	struct trace_probe *tp;
499 
500 	tp = trace_probe_primary_from_call(call);
501 	if (WARN_ON_ONCE(!tp))
502 		return -ENODEV;
503 
504 	if (file) {
505 		if (!trace_probe_get_file_link(tp, file))
506 			return -ENOENT;
507 		if (!trace_probe_has_single_file(tp))
508 			goto out;
509 		trace_probe_clear_flag(tp, TP_FLAG_TRACE);
510 	} else
511 		trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
512 
513 	if (!trace_probe_is_enabled(tp))
514 		__disable_trace_fprobe(tp);
515 
516  out:
517 	if (file)
518 		/*
519 		 * Synchronization is done in below function. For perf event,
520 		 * file == NULL and perf_trace_event_unreg() calls
521 		 * tracepoint_synchronize_unregister() to ensure synchronize
522 		 * event. We don't need to care about it.
523 		 */
524 		trace_probe_remove_file(tp, file);
525 
526 	return 0;
527 }
528 
529 /* Event entry printers */
530 static enum print_line_t
print_fentry_event(struct trace_iterator * iter,int flags,struct trace_event * event)531 print_fentry_event(struct trace_iterator *iter, int flags,
532 		   struct trace_event *event)
533 {
534 	struct fentry_trace_entry_head *field;
535 	struct trace_seq *s = &iter->seq;
536 	struct trace_probe *tp;
537 
538 	field = (struct fentry_trace_entry_head *)iter->ent;
539 	tp = trace_probe_primary_from_call(
540 		container_of(event, struct trace_event_call, event));
541 	if (WARN_ON_ONCE(!tp))
542 		goto out;
543 
544 	trace_seq_printf(s, "%s: (", trace_probe_name(tp));
545 
546 	if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
547 		goto out;
548 
549 	trace_seq_putc(s, ')');
550 
551 	if (trace_probe_print_args(s, tp->args, tp->nr_args,
552 			     (u8 *)&field[1], field) < 0)
553 		goto out;
554 
555 	trace_seq_putc(s, '\n');
556  out:
557 	return trace_handle_return(s);
558 }
559 
560 static enum print_line_t
print_fexit_event(struct trace_iterator * iter,int flags,struct trace_event * event)561 print_fexit_event(struct trace_iterator *iter, int flags,
562 		  struct trace_event *event)
563 {
564 	struct fexit_trace_entry_head *field;
565 	struct trace_seq *s = &iter->seq;
566 	struct trace_probe *tp;
567 
568 	field = (struct fexit_trace_entry_head *)iter->ent;
569 	tp = trace_probe_primary_from_call(
570 		container_of(event, struct trace_event_call, event));
571 	if (WARN_ON_ONCE(!tp))
572 		goto out;
573 
574 	trace_seq_printf(s, "%s: (", trace_probe_name(tp));
575 
576 	if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET))
577 		goto out;
578 
579 	trace_seq_puts(s, " <- ");
580 
581 	if (!seq_print_ip_sym(s, field->func, flags & ~TRACE_ITER_SYM_OFFSET))
582 		goto out;
583 
584 	trace_seq_putc(s, ')');
585 
586 	if (trace_probe_print_args(s, tp->args, tp->nr_args,
587 			     (u8 *)&field[1], field) < 0)
588 		goto out;
589 
590 	trace_seq_putc(s, '\n');
591 
592  out:
593 	return trace_handle_return(s);
594 }
595 
fentry_event_define_fields(struct trace_event_call * event_call)596 static int fentry_event_define_fields(struct trace_event_call *event_call)
597 {
598 	int ret;
599 	struct fentry_trace_entry_head field;
600 	struct trace_probe *tp;
601 
602 	tp = trace_probe_primary_from_call(event_call);
603 	if (WARN_ON_ONCE(!tp))
604 		return -ENOENT;
605 
606 	DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
607 
608 	return traceprobe_define_arg_fields(event_call, sizeof(field), tp);
609 }
610 
fexit_event_define_fields(struct trace_event_call * event_call)611 static int fexit_event_define_fields(struct trace_event_call *event_call)
612 {
613 	int ret;
614 	struct fexit_trace_entry_head field;
615 	struct trace_probe *tp;
616 
617 	tp = trace_probe_primary_from_call(event_call);
618 	if (WARN_ON_ONCE(!tp))
619 		return -ENOENT;
620 
621 	DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
622 	DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
623 
624 	return traceprobe_define_arg_fields(event_call, sizeof(field), tp);
625 }
626 
627 static struct trace_event_functions fentry_funcs = {
628 	.trace		= print_fentry_event
629 };
630 
631 static struct trace_event_functions fexit_funcs = {
632 	.trace		= print_fexit_event
633 };
634 
635 static struct trace_event_fields fentry_fields_array[] = {
636 	{ .type = TRACE_FUNCTION_TYPE,
637 	  .define_fields = fentry_event_define_fields },
638 	{}
639 };
640 
641 static struct trace_event_fields fexit_fields_array[] = {
642 	{ .type = TRACE_FUNCTION_TYPE,
643 	  .define_fields = fexit_event_define_fields },
644 	{}
645 };
646 
647 static int fprobe_register(struct trace_event_call *event,
648 			   enum trace_reg type, void *data);
649 
init_trace_event_call(struct trace_fprobe * tf)650 static inline void init_trace_event_call(struct trace_fprobe *tf)
651 {
652 	struct trace_event_call *call = trace_probe_event_call(&tf->tp);
653 
654 	if (trace_fprobe_is_return(tf)) {
655 		call->event.funcs = &fexit_funcs;
656 		call->class->fields_array = fexit_fields_array;
657 	} else {
658 		call->event.funcs = &fentry_funcs;
659 		call->class->fields_array = fentry_fields_array;
660 	}
661 
662 	call->flags = TRACE_EVENT_FL_FPROBE;
663 	call->class->reg = fprobe_register;
664 }
665 
register_fprobe_event(struct trace_fprobe * tf)666 static int register_fprobe_event(struct trace_fprobe *tf)
667 {
668 	init_trace_event_call(tf);
669 
670 	return trace_probe_register_event_call(&tf->tp);
671 }
672 
unregister_fprobe_event(struct trace_fprobe * tf)673 static int unregister_fprobe_event(struct trace_fprobe *tf)
674 {
675 	return trace_probe_unregister_event_call(&tf->tp);
676 }
677 
__regsiter_tracepoint_fprobe(struct trace_fprobe * tf)678 static int __regsiter_tracepoint_fprobe(struct trace_fprobe *tf)
679 {
680 	struct tracepoint *tpoint = tf->tpoint;
681 	unsigned long ip = (unsigned long)tpoint->probestub;
682 	int ret;
683 
684 	/*
685 	 * Here, we do 2 steps to enable fprobe on a tracepoint.
686 	 * At first, put __probestub_##TP function on the tracepoint
687 	 * and put a fprobe on the stub function.
688 	 */
689 	ret = tracepoint_probe_register_prio_may_exist(tpoint,
690 				tpoint->probestub, NULL, 0);
691 	if (ret < 0)
692 		return ret;
693 	return register_fprobe_ips(&tf->fp, &ip, 1);
694 }
695 
696 /* Internal register function - just handle fprobe and flags */
__register_trace_fprobe(struct trace_fprobe * tf)697 static int __register_trace_fprobe(struct trace_fprobe *tf)
698 {
699 	int i, ret;
700 
701 	/* Should we need new LOCKDOWN flag for fprobe? */
702 	ret = security_locked_down(LOCKDOWN_KPROBES);
703 	if (ret)
704 		return ret;
705 
706 	if (trace_fprobe_is_registered(tf))
707 		return -EINVAL;
708 
709 	for (i = 0; i < tf->tp.nr_args; i++) {
710 		ret = traceprobe_update_arg(&tf->tp.args[i]);
711 		if (ret)
712 			return ret;
713 	}
714 
715 	/* Set/clear disabled flag according to tp->flag */
716 	if (trace_probe_is_enabled(&tf->tp))
717 		tf->fp.flags &= ~FPROBE_FL_DISABLED;
718 	else
719 		tf->fp.flags |= FPROBE_FL_DISABLED;
720 
721 	if (trace_fprobe_is_tracepoint(tf)) {
722 
723 		/* This tracepoint is not loaded yet */
724 		if (tf->tpoint == TRACEPOINT_STUB)
725 			return 0;
726 
727 		return __regsiter_tracepoint_fprobe(tf);
728 	}
729 
730 	/* TODO: handle filter, nofilter or symbol list */
731 	return register_fprobe(&tf->fp, tf->symbol, NULL);
732 }
733 
734 /* Internal unregister function - just handle fprobe and flags */
__unregister_trace_fprobe(struct trace_fprobe * tf)735 static void __unregister_trace_fprobe(struct trace_fprobe *tf)
736 {
737 	if (trace_fprobe_is_registered(tf)) {
738 		unregister_fprobe(&tf->fp);
739 		memset(&tf->fp, 0, sizeof(tf->fp));
740 		if (trace_fprobe_is_tracepoint(tf)) {
741 			tracepoint_probe_unregister(tf->tpoint,
742 					tf->tpoint->probestub, NULL);
743 			tf->tpoint = NULL;
744 			tf->mod = NULL;
745 		}
746 	}
747 }
748 
749 /* TODO: make this trace_*probe common function */
750 /* Unregister a trace_probe and probe_event */
unregister_trace_fprobe(struct trace_fprobe * tf)751 static int unregister_trace_fprobe(struct trace_fprobe *tf)
752 {
753 	/* If other probes are on the event, just unregister fprobe */
754 	if (trace_probe_has_sibling(&tf->tp))
755 		goto unreg;
756 
757 	/* Enabled event can not be unregistered */
758 	if (trace_probe_is_enabled(&tf->tp))
759 		return -EBUSY;
760 
761 	/* If there's a reference to the dynamic event */
762 	if (trace_event_dyn_busy(trace_probe_event_call(&tf->tp)))
763 		return -EBUSY;
764 
765 	/* Will fail if probe is being used by ftrace or perf */
766 	if (unregister_fprobe_event(tf))
767 		return -EBUSY;
768 
769 unreg:
770 	__unregister_trace_fprobe(tf);
771 	dyn_event_remove(&tf->devent);
772 	trace_probe_unlink(&tf->tp);
773 
774 	return 0;
775 }
776 
trace_fprobe_has_same_fprobe(struct trace_fprobe * orig,struct trace_fprobe * comp)777 static bool trace_fprobe_has_same_fprobe(struct trace_fprobe *orig,
778 					 struct trace_fprobe *comp)
779 {
780 	struct trace_probe_event *tpe = orig->tp.event;
781 	int i;
782 
783 	list_for_each_entry(orig, &tpe->probes, tp.list) {
784 		if (strcmp(trace_fprobe_symbol(orig),
785 			   trace_fprobe_symbol(comp)))
786 			continue;
787 
788 		/*
789 		 * trace_probe_compare_arg_type() ensured that nr_args and
790 		 * each argument name and type are same. Let's compare comm.
791 		 */
792 		for (i = 0; i < orig->tp.nr_args; i++) {
793 			if (strcmp(orig->tp.args[i].comm,
794 				   comp->tp.args[i].comm))
795 				break;
796 		}
797 
798 		if (i == orig->tp.nr_args)
799 			return true;
800 	}
801 
802 	return false;
803 }
804 
append_trace_fprobe(struct trace_fprobe * tf,struct trace_fprobe * to)805 static int append_trace_fprobe(struct trace_fprobe *tf, struct trace_fprobe *to)
806 {
807 	int ret;
808 
809 	if (trace_fprobe_is_return(tf) != trace_fprobe_is_return(to) ||
810 	    trace_fprobe_is_tracepoint(tf) != trace_fprobe_is_tracepoint(to)) {
811 		trace_probe_log_set_index(0);
812 		trace_probe_log_err(0, DIFF_PROBE_TYPE);
813 		return -EEXIST;
814 	}
815 	ret = trace_probe_compare_arg_type(&tf->tp, &to->tp);
816 	if (ret) {
817 		/* Note that argument starts index = 2 */
818 		trace_probe_log_set_index(ret + 1);
819 		trace_probe_log_err(0, DIFF_ARG_TYPE);
820 		return -EEXIST;
821 	}
822 	if (trace_fprobe_has_same_fprobe(to, tf)) {
823 		trace_probe_log_set_index(0);
824 		trace_probe_log_err(0, SAME_PROBE);
825 		return -EEXIST;
826 	}
827 
828 	/* Append to existing event */
829 	ret = trace_probe_append(&tf->tp, &to->tp);
830 	if (ret)
831 		return ret;
832 
833 	ret = __register_trace_fprobe(tf);
834 	if (ret)
835 		trace_probe_unlink(&tf->tp);
836 	else
837 		dyn_event_add(&tf->devent, trace_probe_event_call(&tf->tp));
838 
839 	return ret;
840 }
841 
842 /* Register a trace_probe and probe_event */
register_trace_fprobe(struct trace_fprobe * tf)843 static int register_trace_fprobe(struct trace_fprobe *tf)
844 {
845 	struct trace_fprobe *old_tf;
846 	int ret;
847 
848 	mutex_lock(&event_mutex);
849 
850 	old_tf = find_trace_fprobe(trace_probe_name(&tf->tp),
851 				   trace_probe_group_name(&tf->tp));
852 	if (old_tf) {
853 		ret = append_trace_fprobe(tf, old_tf);
854 		goto end;
855 	}
856 
857 	/* Register new event */
858 	ret = register_fprobe_event(tf);
859 	if (ret) {
860 		if (ret == -EEXIST) {
861 			trace_probe_log_set_index(0);
862 			trace_probe_log_err(0, EVENT_EXIST);
863 		} else
864 			pr_warn("Failed to register probe event(%d)\n", ret);
865 		goto end;
866 	}
867 
868 	/* Register fprobe */
869 	ret = __register_trace_fprobe(tf);
870 	if (ret < 0)
871 		unregister_fprobe_event(tf);
872 	else
873 		dyn_event_add(&tf->devent, trace_probe_event_call(&tf->tp));
874 
875 end:
876 	mutex_unlock(&event_mutex);
877 	return ret;
878 }
879 
880 struct __find_tracepoint_cb_data {
881 	const char *tp_name;
882 	struct tracepoint *tpoint;
883 	struct module *mod;
884 };
885 
__find_tracepoint_module_cb(struct tracepoint * tp,struct module * mod,void * priv)886 static void __find_tracepoint_module_cb(struct tracepoint *tp, struct module *mod, void *priv)
887 {
888 	struct __find_tracepoint_cb_data *data = priv;
889 
890 	if (!data->tpoint && !strcmp(data->tp_name, tp->name)) {
891 		/* If module is not specified, try getting module refcount. */
892 		if (!data->mod && mod) {
893 			/* If failed to get refcount, ignore this tracepoint. */
894 			if (!try_module_get(mod))
895 				return;
896 
897 			data->mod = mod;
898 		}
899 		data->tpoint = tp;
900 	}
901 }
902 
__find_tracepoint_cb(struct tracepoint * tp,void * priv)903 static void __find_tracepoint_cb(struct tracepoint *tp, void *priv)
904 {
905 	struct __find_tracepoint_cb_data *data = priv;
906 
907 	if (!data->tpoint && !strcmp(data->tp_name, tp->name))
908 		data->tpoint = tp;
909 }
910 
911 /*
912  * Find a tracepoint from kernel and module. If the tracepoint is on the module,
913  * the module's refcount is incremented and returned as *@tp_mod. Thus, if it is
914  * not NULL, caller must call module_put(*tp_mod) after used the tracepoint.
915  */
find_tracepoint(const char * tp_name,struct module ** tp_mod)916 static struct tracepoint *find_tracepoint(const char *tp_name,
917 					  struct module **tp_mod)
918 {
919 	struct __find_tracepoint_cb_data data = {
920 		.tp_name = tp_name,
921 		.mod = NULL,
922 	};
923 
924 	for_each_kernel_tracepoint(__find_tracepoint_cb, &data);
925 
926 	if (!data.tpoint && IS_ENABLED(CONFIG_MODULES)) {
927 		for_each_module_tracepoint(__find_tracepoint_module_cb, &data);
928 		*tp_mod = data.mod;
929 	}
930 
931 	return data.tpoint;
932 }
933 
934 #ifdef CONFIG_MODULES
reenable_trace_fprobe(struct trace_fprobe * tf)935 static void reenable_trace_fprobe(struct trace_fprobe *tf)
936 {
937 	struct trace_probe *tp = &tf->tp;
938 
939 	list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
940 		__enable_trace_fprobe(tf);
941 	}
942 }
943 
944 /*
945  * Find a tracepoint from specified module. In this case, this does not get the
946  * module's refcount. The caller must ensure the module is not freed.
947  */
find_tracepoint_in_module(struct module * mod,const char * tp_name)948 static struct tracepoint *find_tracepoint_in_module(struct module *mod,
949 						    const char *tp_name)
950 {
951 	struct __find_tracepoint_cb_data data = {
952 		.tp_name = tp_name,
953 		.mod = mod,
954 	};
955 
956 	for_each_tracepoint_in_module(mod, __find_tracepoint_module_cb, &data);
957 	return data.tpoint;
958 }
959 
__tracepoint_probe_module_cb(struct notifier_block * self,unsigned long val,void * data)960 static int __tracepoint_probe_module_cb(struct notifier_block *self,
961 					unsigned long val, void *data)
962 {
963 	struct tp_module *tp_mod = data;
964 	struct tracepoint *tpoint;
965 	struct trace_fprobe *tf;
966 	struct dyn_event *pos;
967 
968 	if (val != MODULE_STATE_GOING && val != MODULE_STATE_COMING)
969 		return NOTIFY_DONE;
970 
971 	mutex_lock(&event_mutex);
972 	for_each_trace_fprobe(tf, pos) {
973 		if (val == MODULE_STATE_COMING && tf->tpoint == TRACEPOINT_STUB) {
974 			tpoint = find_tracepoint_in_module(tp_mod->mod, tf->symbol);
975 			if (tpoint) {
976 				tf->tpoint = tpoint;
977 				tf->mod = tp_mod->mod;
978 				if (!WARN_ON_ONCE(__regsiter_tracepoint_fprobe(tf)) &&
979 				    trace_probe_is_enabled(&tf->tp))
980 					reenable_trace_fprobe(tf);
981 			}
982 		} else if (val == MODULE_STATE_GOING && tp_mod->mod == tf->mod) {
983 			unregister_fprobe(&tf->fp);
984 			if (trace_fprobe_is_tracepoint(tf)) {
985 				tracepoint_probe_unregister(tf->tpoint,
986 					tf->tpoint->probestub, NULL);
987 				tf->tpoint = TRACEPOINT_STUB;
988 				tf->mod = NULL;
989 			}
990 		}
991 	}
992 	mutex_unlock(&event_mutex);
993 
994 	return NOTIFY_DONE;
995 }
996 
997 static struct notifier_block tracepoint_module_nb = {
998 	.notifier_call = __tracepoint_probe_module_cb,
999 };
1000 #endif /* CONFIG_MODULES */
1001 
parse_symbol_and_return(int argc,const char * argv[],char ** symbol,bool * is_return,bool is_tracepoint)1002 static int parse_symbol_and_return(int argc, const char *argv[],
1003 				   char **symbol, bool *is_return,
1004 				   bool is_tracepoint)
1005 {
1006 	char *tmp = strchr(argv[1], '%');
1007 	int i;
1008 
1009 	if (tmp) {
1010 		int len = tmp - argv[1];
1011 
1012 		if (!is_tracepoint && !strcmp(tmp, "%return")) {
1013 			*is_return = true;
1014 		} else {
1015 			trace_probe_log_err(len, BAD_ADDR_SUFFIX);
1016 			return -EINVAL;
1017 		}
1018 		*symbol = kmemdup_nul(argv[1], len, GFP_KERNEL);
1019 	} else
1020 		*symbol = kstrdup(argv[1], GFP_KERNEL);
1021 	if (!*symbol)
1022 		return -ENOMEM;
1023 
1024 	if (*is_return)
1025 		return 0;
1026 
1027 	if (is_tracepoint) {
1028 		tmp = *symbol;
1029 		while (*tmp && (isalnum(*tmp) || *tmp == '_'))
1030 			tmp++;
1031 		if (*tmp) {
1032 			/* find a wrong character. */
1033 			trace_probe_log_err(tmp - *symbol, BAD_TP_NAME);
1034 			kfree(*symbol);
1035 			*symbol = NULL;
1036 			return -EINVAL;
1037 		}
1038 	}
1039 
1040 	/* If there is $retval, this should be a return fprobe. */
1041 	for (i = 2; i < argc; i++) {
1042 		tmp = strstr(argv[i], "$retval");
1043 		if (tmp && !isalnum(tmp[7]) && tmp[7] != '_') {
1044 			if (is_tracepoint) {
1045 				trace_probe_log_set_index(i);
1046 				trace_probe_log_err(tmp - argv[i], RETVAL_ON_PROBE);
1047 				kfree(*symbol);
1048 				*symbol = NULL;
1049 				return -EINVAL;
1050 			}
1051 			*is_return = true;
1052 			break;
1053 		}
1054 	}
1055 	return 0;
1056 }
1057 
__trace_fprobe_create(int argc,const char * argv[])1058 static int __trace_fprobe_create(int argc, const char *argv[])
1059 {
1060 	/*
1061 	 * Argument syntax:
1062 	 *  - Add fentry probe:
1063 	 *      f[:[GRP/][EVENT]] [MOD:]KSYM [FETCHARGS]
1064 	 *  - Add fexit probe:
1065 	 *      f[N][:[GRP/][EVENT]] [MOD:]KSYM%return [FETCHARGS]
1066 	 *  - Add tracepoint probe:
1067 	 *      t[:[GRP/][EVENT]] TRACEPOINT [FETCHARGS]
1068 	 *
1069 	 * Fetch args:
1070 	 *  $retval	: fetch return value
1071 	 *  $stack	: fetch stack address
1072 	 *  $stackN	: fetch Nth entry of stack (N:0-)
1073 	 *  $argN	: fetch Nth argument (N:1-)
1074 	 *  $comm       : fetch current task comm
1075 	 *  @ADDR	: fetch memory at ADDR (ADDR should be in kernel)
1076 	 *  @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol)
1077 	 * Dereferencing memory fetch:
1078 	 *  +|-offs(ARG) : fetch memory at ARG +|- offs address.
1079 	 * Alias name of args:
1080 	 *  NAME=FETCHARG : set NAME as alias of FETCHARG.
1081 	 * Type of args:
1082 	 *  FETCHARG:TYPE : use TYPE instead of unsigned long.
1083 	 */
1084 	struct trace_fprobe *tf = NULL;
1085 	int i, len, new_argc = 0, ret = 0;
1086 	bool is_return = false;
1087 	char *symbol = NULL;
1088 	const char *event = NULL, *group = FPROBE_EVENT_SYSTEM;
1089 	const char **new_argv = NULL;
1090 	int maxactive = 0;
1091 	char buf[MAX_EVENT_NAME_LEN];
1092 	char gbuf[MAX_EVENT_NAME_LEN];
1093 	char sbuf[KSYM_NAME_LEN];
1094 	char abuf[MAX_BTF_ARGS_LEN];
1095 	char *dbuf = NULL;
1096 	bool is_tracepoint = false;
1097 	struct module *tp_mod = NULL;
1098 	struct tracepoint *tpoint = NULL;
1099 	struct traceprobe_parse_context ctx = {
1100 		.flags = TPARG_FL_KERNEL | TPARG_FL_FPROBE,
1101 	};
1102 
1103 	if ((argv[0][0] != 'f' && argv[0][0] != 't') || argc < 2)
1104 		return -ECANCELED;
1105 
1106 	if (argv[0][0] == 't') {
1107 		is_tracepoint = true;
1108 		group = TRACEPOINT_EVENT_SYSTEM;
1109 	}
1110 
1111 	trace_probe_log_init("trace_fprobe", argc, argv);
1112 
1113 	event = strchr(&argv[0][1], ':');
1114 	if (event)
1115 		event++;
1116 
1117 	if (isdigit(argv[0][1])) {
1118 		if (event)
1119 			len = event - &argv[0][1] - 1;
1120 		else
1121 			len = strlen(&argv[0][1]);
1122 		if (len > MAX_EVENT_NAME_LEN - 1) {
1123 			trace_probe_log_err(1, BAD_MAXACT);
1124 			goto parse_error;
1125 		}
1126 		memcpy(buf, &argv[0][1], len);
1127 		buf[len] = '\0';
1128 		ret = kstrtouint(buf, 0, &maxactive);
1129 		if (ret || !maxactive) {
1130 			trace_probe_log_err(1, BAD_MAXACT);
1131 			goto parse_error;
1132 		}
1133 		/* fprobe rethook instances are iterated over via a list. The
1134 		 * maximum should stay reasonable.
1135 		 */
1136 		if (maxactive > RETHOOK_MAXACTIVE_MAX) {
1137 			trace_probe_log_err(1, MAXACT_TOO_BIG);
1138 			goto parse_error;
1139 		}
1140 	}
1141 
1142 	trace_probe_log_set_index(1);
1143 
1144 	/* a symbol(or tracepoint) must be specified */
1145 	ret = parse_symbol_and_return(argc, argv, &symbol, &is_return, is_tracepoint);
1146 	if (ret < 0)
1147 		goto parse_error;
1148 
1149 	if (!is_return && maxactive) {
1150 		trace_probe_log_set_index(0);
1151 		trace_probe_log_err(1, BAD_MAXACT_TYPE);
1152 		goto parse_error;
1153 	}
1154 
1155 	trace_probe_log_set_index(0);
1156 	if (event) {
1157 		ret = traceprobe_parse_event_name(&event, &group, gbuf,
1158 						  event - argv[0]);
1159 		if (ret)
1160 			goto parse_error;
1161 	}
1162 
1163 	if (!event) {
1164 		/* Make a new event name */
1165 		if (is_tracepoint)
1166 			snprintf(buf, MAX_EVENT_NAME_LEN, "%s%s",
1167 				 isdigit(*symbol) ? "_" : "", symbol);
1168 		else
1169 			snprintf(buf, MAX_EVENT_NAME_LEN, "%s__%s", symbol,
1170 				 is_return ? "exit" : "entry");
1171 		sanitize_event_name(buf);
1172 		event = buf;
1173 	}
1174 
1175 	if (is_return)
1176 		ctx.flags |= TPARG_FL_RETURN;
1177 	else
1178 		ctx.flags |= TPARG_FL_FENTRY;
1179 
1180 	if (is_tracepoint) {
1181 		ctx.flags |= TPARG_FL_TPOINT;
1182 		tpoint = find_tracepoint(symbol, &tp_mod);
1183 		if (tpoint) {
1184 			ctx.funcname = kallsyms_lookup(
1185 				(unsigned long)tpoint->probestub,
1186 				NULL, NULL, NULL, sbuf);
1187 		} else if (IS_ENABLED(CONFIG_MODULES)) {
1188 				/* This *may* be loaded afterwards */
1189 				tpoint = TRACEPOINT_STUB;
1190 				ctx.funcname = symbol;
1191 		} else {
1192 			trace_probe_log_set_index(1);
1193 			trace_probe_log_err(0, NO_TRACEPOINT);
1194 			goto parse_error;
1195 		}
1196 	} else
1197 		ctx.funcname = symbol;
1198 
1199 	argc -= 2; argv += 2;
1200 	new_argv = traceprobe_expand_meta_args(argc, argv, &new_argc,
1201 					       abuf, MAX_BTF_ARGS_LEN, &ctx);
1202 	if (IS_ERR(new_argv)) {
1203 		ret = PTR_ERR(new_argv);
1204 		new_argv = NULL;
1205 		goto out;
1206 	}
1207 	if (new_argv) {
1208 		argc = new_argc;
1209 		argv = new_argv;
1210 	}
1211 	if (argc > MAX_TRACE_ARGS) {
1212 		ret = -E2BIG;
1213 		goto out;
1214 	}
1215 
1216 	ret = traceprobe_expand_dentry_args(argc, argv, &dbuf);
1217 	if (ret)
1218 		goto out;
1219 
1220 	/* setup a probe */
1221 	tf = alloc_trace_fprobe(group, event, symbol, tpoint, tp_mod,
1222 				maxactive, argc, is_return);
1223 	if (IS_ERR(tf)) {
1224 		ret = PTR_ERR(tf);
1225 		/* This must return -ENOMEM, else there is a bug */
1226 		WARN_ON_ONCE(ret != -ENOMEM);
1227 		goto out;	/* We know tf is not allocated */
1228 	}
1229 
1230 	/* parse arguments */
1231 	for (i = 0; i < argc; i++) {
1232 		trace_probe_log_set_index(i + 2);
1233 		ctx.offset = 0;
1234 		ret = traceprobe_parse_probe_arg(&tf->tp, i, argv[i], &ctx);
1235 		if (ret)
1236 			goto error;	/* This can be -ENOMEM */
1237 	}
1238 
1239 	if (is_return && tf->tp.entry_arg) {
1240 		tf->fp.entry_handler = trace_fprobe_entry_handler;
1241 		tf->fp.entry_data_size = traceprobe_get_entry_data_size(&tf->tp);
1242 	}
1243 
1244 	ret = traceprobe_set_print_fmt(&tf->tp,
1245 			is_return ? PROBE_PRINT_RETURN : PROBE_PRINT_NORMAL);
1246 	if (ret < 0)
1247 		goto error;
1248 
1249 	ret = register_trace_fprobe(tf);
1250 	if (ret) {
1251 		trace_probe_log_set_index(1);
1252 		if (ret == -EILSEQ)
1253 			trace_probe_log_err(0, BAD_INSN_BNDRY);
1254 		else if (ret == -ENOENT)
1255 			trace_probe_log_err(0, BAD_PROBE_ADDR);
1256 		else if (ret != -ENOMEM && ret != -EEXIST)
1257 			trace_probe_log_err(0, FAIL_REG_PROBE);
1258 		goto error;
1259 	}
1260 
1261 out:
1262 	if (tp_mod)
1263 		module_put(tp_mod);
1264 	traceprobe_finish_parse(&ctx);
1265 	trace_probe_log_clear();
1266 	kfree(new_argv);
1267 	kfree(symbol);
1268 	kfree(dbuf);
1269 	return ret;
1270 
1271 parse_error:
1272 	ret = -EINVAL;
1273 error:
1274 	free_trace_fprobe(tf);
1275 	goto out;
1276 }
1277 
trace_fprobe_create(const char * raw_command)1278 static int trace_fprobe_create(const char *raw_command)
1279 {
1280 	return trace_probe_create(raw_command, __trace_fprobe_create);
1281 }
1282 
trace_fprobe_release(struct dyn_event * ev)1283 static int trace_fprobe_release(struct dyn_event *ev)
1284 {
1285 	struct trace_fprobe *tf = to_trace_fprobe(ev);
1286 	int ret = unregister_trace_fprobe(tf);
1287 
1288 	if (!ret)
1289 		free_trace_fprobe(tf);
1290 	return ret;
1291 }
1292 
trace_fprobe_show(struct seq_file * m,struct dyn_event * ev)1293 static int trace_fprobe_show(struct seq_file *m, struct dyn_event *ev)
1294 {
1295 	struct trace_fprobe *tf = to_trace_fprobe(ev);
1296 	int i;
1297 
1298 	if (trace_fprobe_is_tracepoint(tf))
1299 		seq_putc(m, 't');
1300 	else
1301 		seq_putc(m, 'f');
1302 	if (trace_fprobe_is_return(tf) && tf->fp.nr_maxactive)
1303 		seq_printf(m, "%d", tf->fp.nr_maxactive);
1304 	seq_printf(m, ":%s/%s", trace_probe_group_name(&tf->tp),
1305 				trace_probe_name(&tf->tp));
1306 
1307 	seq_printf(m, " %s%s", trace_fprobe_symbol(tf),
1308 			       trace_fprobe_is_return(tf) ? "%return" : "");
1309 
1310 	for (i = 0; i < tf->tp.nr_args; i++)
1311 		seq_printf(m, " %s=%s", tf->tp.args[i].name, tf->tp.args[i].comm);
1312 	seq_putc(m, '\n');
1313 
1314 	return 0;
1315 }
1316 
1317 /*
1318  * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex.
1319  */
fprobe_register(struct trace_event_call * event,enum trace_reg type,void * data)1320 static int fprobe_register(struct trace_event_call *event,
1321 			   enum trace_reg type, void *data)
1322 {
1323 	struct trace_event_file *file = data;
1324 
1325 	switch (type) {
1326 	case TRACE_REG_REGISTER:
1327 		return enable_trace_fprobe(event, file);
1328 	case TRACE_REG_UNREGISTER:
1329 		return disable_trace_fprobe(event, file);
1330 
1331 #ifdef CONFIG_PERF_EVENTS
1332 	case TRACE_REG_PERF_REGISTER:
1333 		return enable_trace_fprobe(event, NULL);
1334 	case TRACE_REG_PERF_UNREGISTER:
1335 		return disable_trace_fprobe(event, NULL);
1336 	case TRACE_REG_PERF_OPEN:
1337 	case TRACE_REG_PERF_CLOSE:
1338 	case TRACE_REG_PERF_ADD:
1339 	case TRACE_REG_PERF_DEL:
1340 		return 0;
1341 #endif
1342 	}
1343 	return 0;
1344 }
1345 
1346 /*
1347  * Register dynevent at core_initcall. This allows kernel to setup fprobe
1348  * events in postcore_initcall without tracefs.
1349  */
init_fprobe_trace_early(void)1350 static __init int init_fprobe_trace_early(void)
1351 {
1352 	int ret;
1353 
1354 	ret = dyn_event_register(&trace_fprobe_ops);
1355 	if (ret)
1356 		return ret;
1357 
1358 #ifdef CONFIG_MODULES
1359 	ret = register_tracepoint_module_notifier(&tracepoint_module_nb);
1360 	if (ret)
1361 		return ret;
1362 #endif
1363 
1364 	return 0;
1365 }
1366 core_initcall(init_fprobe_trace_early);
1367