Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * uprobes-based tracing events
4 : : *
5 : : * Copyright (C) IBM Corporation, 2010-2012
6 : : * Author: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
7 : : */
8 : : #define pr_fmt(fmt) "trace_uprobe: " fmt
9 : :
10 : : #include <linux/security.h>
11 : : #include <linux/ctype.h>
12 : : #include <linux/module.h>
13 : : #include <linux/uaccess.h>
14 : : #include <linux/uprobes.h>
15 : : #include <linux/namei.h>
16 : : #include <linux/string.h>
17 : : #include <linux/rculist.h>
18 : :
19 : : #include "trace_dynevent.h"
20 : : #include "trace_probe.h"
21 : : #include "trace_probe_tmpl.h"
22 : :
23 : : #define UPROBE_EVENT_SYSTEM "uprobes"
24 : :
25 : : struct uprobe_trace_entry_head {
26 : : struct trace_entry ent;
27 : : unsigned long vaddr[];
28 : : };
29 : :
30 : : #define SIZEOF_TRACE_ENTRY(is_return) \
31 : : (sizeof(struct uprobe_trace_entry_head) + \
32 : : sizeof(unsigned long) * (is_return ? 2 : 1))
33 : :
34 : : #define DATAOF_TRACE_ENTRY(entry, is_return) \
35 : : ((void*)(entry) + SIZEOF_TRACE_ENTRY(is_return))
36 : :
37 : : static int trace_uprobe_create(int argc, const char **argv);
38 : : static int trace_uprobe_show(struct seq_file *m, struct dyn_event *ev);
39 : : static int trace_uprobe_release(struct dyn_event *ev);
40 : : static bool trace_uprobe_is_busy(struct dyn_event *ev);
41 : : static bool trace_uprobe_match(const char *system, const char *event,
42 : : int argc, const char **argv, struct dyn_event *ev);
43 : :
44 : : static struct dyn_event_operations trace_uprobe_ops = {
45 : : .create = trace_uprobe_create,
46 : : .show = trace_uprobe_show,
47 : : .is_busy = trace_uprobe_is_busy,
48 : : .free = trace_uprobe_release,
49 : : .match = trace_uprobe_match,
50 : : };
51 : :
52 : : /*
53 : : * uprobe event core functions
54 : : */
55 : : struct trace_uprobe {
56 : : struct dyn_event devent;
57 : : struct uprobe_consumer consumer;
58 : : struct path path;
59 : : struct inode *inode;
60 : : char *filename;
61 : : unsigned long offset;
62 : : unsigned long ref_ctr_offset;
63 : : unsigned long nhit;
64 : : struct trace_probe tp;
65 : : };
66 : :
67 : 0 : static bool is_trace_uprobe(struct dyn_event *ev)
68 : : {
69 : 0 : return ev->ops == &trace_uprobe_ops;
70 : : }
71 : :
72 : 0 : static struct trace_uprobe *to_trace_uprobe(struct dyn_event *ev)
73 : : {
74 : 0 : return container_of(ev, struct trace_uprobe, devent);
75 : : }
76 : :
77 : : /**
78 : : * for_each_trace_uprobe - iterate over the trace_uprobe list
79 : : * @pos: the struct trace_uprobe * for each entry
80 : : * @dpos: the struct dyn_event * to use as a loop cursor
81 : : */
82 : : #define for_each_trace_uprobe(pos, dpos) \
83 : : for_each_dyn_event(dpos) \
84 : : if (is_trace_uprobe(dpos) && (pos = to_trace_uprobe(dpos)))
85 : :
86 : : #define SIZEOF_TRACE_UPROBE(n) \
87 : : (offsetof(struct trace_uprobe, tp.args) + \
88 : : (sizeof(struct probe_arg) * (n)))
89 : :
90 : : static int register_uprobe_event(struct trace_uprobe *tu);
91 : : static int unregister_uprobe_event(struct trace_uprobe *tu);
92 : :
93 : : struct uprobe_dispatch_data {
94 : : struct trace_uprobe *tu;
95 : : unsigned long bp_addr;
96 : : };
97 : :
98 : : static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
99 : : static int uretprobe_dispatcher(struct uprobe_consumer *con,
100 : : unsigned long func, struct pt_regs *regs);
101 : :
102 : : #ifdef CONFIG_STACK_GROWSUP
103 : : static unsigned long adjust_stack_addr(unsigned long addr, unsigned int n)
104 : : {
105 : : return addr - (n * sizeof(long));
106 : : }
107 : : #else
108 : 0 : static unsigned long adjust_stack_addr(unsigned long addr, unsigned int n)
109 : : {
110 : 0 : return addr + (n * sizeof(long));
111 : : }
112 : : #endif
113 : :
114 : 0 : static unsigned long get_user_stack_nth(struct pt_regs *regs, unsigned int n)
115 : : {
116 : 0 : unsigned long ret;
117 : 0 : unsigned long addr = user_stack_pointer(regs);
118 : :
119 : 0 : addr = adjust_stack_addr(addr, n);
120 : :
121 [ # # ]: 0 : if (copy_from_user(&ret, (void __force __user *) addr, sizeof(ret)))
122 : : return 0;
123 : :
124 : 0 : return ret;
125 : : }
126 : :
127 : : /*
128 : : * Uprobes-specific fetch functions
129 : : */
130 : : static nokprobe_inline int
131 : 0 : probe_mem_read(void *dest, void *src, size_t size)
132 : : {
133 : 0 : void __user *vaddr = (void __force __user *)src;
134 : :
135 [ # # # # : 0 : return copy_from_user(dest, vaddr, size) ? -EFAULT : 0;
# # ]
136 : : }
137 : :
138 : : static nokprobe_inline int
139 : 0 : probe_mem_read_user(void *dest, void *src, size_t size)
140 : : {
141 [ # # ]: 0 : return probe_mem_read(dest, src, size);
142 : : }
143 : :
144 : : /*
145 : : * Fetch a null-terminated string. Caller MUST set *(u32 *)dest with max
146 : : * length and relative data location.
147 : : */
148 : : static nokprobe_inline int
149 : 0 : fetch_store_string(unsigned long addr, void *dest, void *base)
150 : : {
151 : 0 : long ret;
152 : 0 : u32 loc = *(u32 *)dest;
153 : 0 : int maxlen = get_loc_len(loc);
154 [ # # ]: 0 : u8 *dst = get_loc_data(dest, base);
155 : 0 : void __user *src = (void __force __user *) addr;
156 : :
157 [ # # # # ]: 0 : if (unlikely(!maxlen))
158 : : return -ENOMEM;
159 : :
160 [ # # # # ]: 0 : if (addr == FETCH_TOKEN_COMM)
161 : 0 : ret = strlcpy(dst, current->comm, maxlen);
162 : : else
163 : 0 : ret = strncpy_from_user(dst, src, maxlen);
164 [ # # # # ]: 0 : if (ret >= 0) {
165 [ # # # # ]: 0 : if (ret == maxlen)
166 : 0 : dst[ret - 1] = '\0';
167 : : else
168 : : /*
169 : : * Include the terminating null byte. In this case it
170 : : * was copied by strncpy_from_user but not accounted
171 : : * for in ret.
172 : : */
173 : 0 : ret++;
174 : 0 : *(u32 *)dest = make_data_loc(ret, (void *)dst - base);
175 : : }
176 : :
177 : 0 : return ret;
178 : : }
179 : :
180 : : static nokprobe_inline int
181 : 0 : fetch_store_string_user(unsigned long addr, void *dest, void *base)
182 : : {
183 [ # # ]: 0 : return fetch_store_string(addr, dest, base);
184 : : }
185 : :
186 : : /* Return the length of string -- including null terminal byte */
187 : : static nokprobe_inline int
188 : 0 : fetch_store_strlen(unsigned long addr)
189 : : {
190 : 0 : int len;
191 : 0 : void __user *vaddr = (void __force __user *) addr;
192 : :
193 [ # # ]: 0 : if (addr == FETCH_TOKEN_COMM)
194 : 0 : len = strlen(current->comm) + 1;
195 : : else
196 : 0 : len = strnlen_user(vaddr, MAX_STRING_SIZE);
197 : :
198 [ # # # # ]: 0 : return (len > MAX_STRING_SIZE) ? 0 : len;
199 : : }
200 : :
201 : : static nokprobe_inline int
202 : 0 : fetch_store_strlen_user(unsigned long addr)
203 : : {
204 [ # # ]: 0 : return fetch_store_strlen(addr);
205 : : }
206 : :
207 : 0 : static unsigned long translate_user_vaddr(unsigned long file_offset)
208 : : {
209 : 0 : unsigned long base_addr;
210 : 0 : struct uprobe_dispatch_data *udd;
211 : :
212 : 0 : udd = (void *) current->utask->vaddr;
213 : :
214 : 0 : base_addr = udd->bp_addr - udd->tu->offset;
215 : 0 : return base_addr + file_offset;
216 : : }
217 : :
218 : : /* Note that we don't verify it, since the code does not come from user space */
219 : : static int
220 : 0 : process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
221 : : void *base)
222 : : {
223 : 0 : unsigned long val;
224 : :
225 : : /* 1st stage: get value from context */
226 [ # # # # : 0 : switch (code->op) {
# # # #
# ]
227 : 0 : case FETCH_OP_REG:
228 [ # # ]: 0 : val = regs_get_register(regs, code->param);
229 : : break;
230 : 0 : case FETCH_OP_STACK:
231 : 0 : val = get_user_stack_nth(regs, code->param);
232 : 0 : break;
233 : 0 : case FETCH_OP_STACKP:
234 : 0 : val = user_stack_pointer(regs);
235 : 0 : break;
236 : 0 : case FETCH_OP_RETVAL:
237 : 0 : val = regs_return_value(regs);
238 : 0 : break;
239 : 0 : case FETCH_OP_IMM:
240 : 0 : val = code->immediate;
241 : 0 : break;
242 : : case FETCH_OP_COMM:
243 : : val = FETCH_TOKEN_COMM;
244 : : break;
245 : 0 : case FETCH_OP_DATA:
246 : 0 : val = (unsigned long)code->data;
247 : 0 : break;
248 : 0 : case FETCH_OP_FOFFS:
249 : 0 : val = translate_user_vaddr(code->immediate);
250 : 0 : break;
251 : : default:
252 : : return -EILSEQ;
253 : : }
254 : 0 : code++;
255 : :
256 : 0 : return process_fetch_insn_bottom(code, val, dest, base);
257 : : }
258 : : NOKPROBE_SYMBOL(process_fetch_insn)
259 : :
260 : 0 : static inline void init_trace_uprobe_filter(struct trace_uprobe_filter *filter)
261 : : {
262 : 0 : rwlock_init(&filter->rwlock);
263 : 0 : filter->nr_systemwide = 0;
264 : 0 : INIT_LIST_HEAD(&filter->perf_events);
265 : : }
266 : :
267 : 0 : static inline bool uprobe_filter_is_empty(struct trace_uprobe_filter *filter)
268 : : {
269 [ # # # # ]: 0 : return !filter->nr_systemwide && list_empty(&filter->perf_events);
270 : : }
271 : :
272 : 0 : static inline bool is_ret_probe(struct trace_uprobe *tu)
273 : : {
274 : 0 : return tu->consumer.ret_handler != NULL;
275 : : }
276 : :
277 : 0 : static bool trace_uprobe_is_busy(struct dyn_event *ev)
278 : : {
279 : 0 : struct trace_uprobe *tu = to_trace_uprobe(ev);
280 : :
281 : 0 : return trace_probe_is_enabled(&tu->tp);
282 : : }
283 : :
284 : 0 : static bool trace_uprobe_match_command_head(struct trace_uprobe *tu,
285 : : int argc, const char **argv)
286 : : {
287 : 0 : char buf[MAX_ARGSTR_LEN + 1];
288 : 0 : int len;
289 : :
290 [ # # ]: 0 : if (!argc)
291 : : return true;
292 : :
293 : 0 : len = strlen(tu->filename);
294 [ # # # # ]: 0 : if (strncmp(tu->filename, argv[0], len) || argv[0][len] != ':')
295 : : return false;
296 : :
297 [ # # ]: 0 : if (tu->ref_ctr_offset == 0)
298 : 0 : snprintf(buf, sizeof(buf), "0x%0*lx",
299 : : (int)(sizeof(void *) * 2), tu->offset);
300 : : else
301 : 0 : snprintf(buf, sizeof(buf), "0x%0*lx(0x%lx)",
302 : : (int)(sizeof(void *) * 2), tu->offset,
303 : : tu->ref_ctr_offset);
304 [ # # ]: 0 : if (strcmp(buf, &argv[0][len + 1]))
305 : : return false;
306 : :
307 : 0 : argc--; argv++;
308 : :
309 : 0 : return trace_probe_match_command_args(&tu->tp, argc, argv);
310 : : }
311 : :
312 : 0 : static bool trace_uprobe_match(const char *system, const char *event,
313 : : int argc, const char **argv, struct dyn_event *ev)
314 : : {
315 : 0 : struct trace_uprobe *tu = to_trace_uprobe(ev);
316 : :
317 [ # # # # ]: 0 : return strcmp(trace_probe_name(&tu->tp), event) == 0 &&
318 [ # # # # : 0 : (!system || strcmp(trace_probe_group_name(&tu->tp), system) == 0) &&
# # ]
319 : 0 : trace_uprobe_match_command_head(tu, argc, argv);
320 : : }
321 : :
322 : : static nokprobe_inline struct trace_uprobe *
323 : 0 : trace_uprobe_primary_from_call(struct trace_event_call *call)
324 : : {
325 : 0 : struct trace_probe *tp;
326 : :
327 : 0 : tp = trace_probe_primary_from_call(call);
328 [ # # # # : 0 : if (WARN_ON_ONCE(!tp))
# # # # #
# # # ]
329 : : return NULL;
330 : :
331 : 0 : return container_of(tp, struct trace_uprobe, tp);
332 : : }
333 : :
334 : : /*
335 : : * Allocate new trace_uprobe and initialize it (including uprobes).
336 : : */
337 : : static struct trace_uprobe *
338 : 0 : alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
339 : : {
340 : 0 : struct trace_uprobe *tu;
341 : 0 : int ret;
342 : :
343 : 0 : tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL);
344 [ # # ]: 0 : if (!tu)
345 : : return ERR_PTR(-ENOMEM);
346 : :
347 : 0 : ret = trace_probe_init(&tu->tp, event, group, true);
348 [ # # ]: 0 : if (ret < 0)
349 : 0 : goto error;
350 : :
351 [ # # ]: 0 : dyn_event_init(&tu->devent, &trace_uprobe_ops);
352 : 0 : tu->consumer.handler = uprobe_dispatcher;
353 [ # # ]: 0 : if (is_ret)
354 : 0 : tu->consumer.ret_handler = uretprobe_dispatcher;
355 : 0 : init_trace_uprobe_filter(tu->tp.event->filter);
356 : 0 : return tu;
357 : :
358 : : error:
359 : 0 : kfree(tu);
360 : :
361 : 0 : return ERR_PTR(ret);
362 : : }
363 : :
364 : 0 : static void free_trace_uprobe(struct trace_uprobe *tu)
365 : : {
366 [ # # ]: 0 : if (!tu)
367 : : return;
368 : :
369 : 0 : path_put(&tu->path);
370 : 0 : trace_probe_cleanup(&tu->tp);
371 : 0 : kfree(tu->filename);
372 : 0 : kfree(tu);
373 : : }
374 : :
375 : 0 : static struct trace_uprobe *find_probe_event(const char *event, const char *group)
376 : : {
377 : 0 : struct dyn_event *pos;
378 : 0 : struct trace_uprobe *tu;
379 : :
380 [ # # # # : 0 : for_each_trace_uprobe(tu, pos)
# # ]
381 [ # # # # ]: 0 : if (strcmp(trace_probe_name(&tu->tp), event) == 0 &&
382 [ # # ]: 0 : strcmp(trace_probe_group_name(&tu->tp), group) == 0)
383 : 0 : return tu;
384 : :
385 : : return NULL;
386 : : }
387 : :
388 : : /* Unregister a trace_uprobe and probe_event */
389 : 0 : static int unregister_trace_uprobe(struct trace_uprobe *tu)
390 : : {
391 : 0 : int ret;
392 : :
393 [ # # # # ]: 0 : if (trace_probe_has_sibling(&tu->tp))
394 : 0 : goto unreg;
395 : :
396 : 0 : ret = unregister_uprobe_event(tu);
397 [ # # ]: 0 : if (ret)
398 : : return ret;
399 : :
400 : 0 : unreg:
401 : 0 : dyn_event_remove(&tu->devent);
402 : 0 : trace_probe_unlink(&tu->tp);
403 : 0 : free_trace_uprobe(tu);
404 : 0 : return 0;
405 : : }
406 : :
407 : 0 : static bool trace_uprobe_has_same_uprobe(struct trace_uprobe *orig,
408 : : struct trace_uprobe *comp)
409 : : {
410 : 0 : struct trace_probe_event *tpe = orig->tp.event;
411 : 0 : struct trace_probe *pos;
412 [ # # ]: 0 : struct inode *comp_inode = d_real_inode(comp->path.dentry);
413 : 0 : int i;
414 : :
415 [ # # ]: 0 : list_for_each_entry(pos, &tpe->probes, list) {
416 : 0 : orig = container_of(pos, struct trace_uprobe, tp);
417 [ # # # # ]: 0 : if (comp_inode != d_real_inode(orig->path.dentry) ||
418 [ # # ]: 0 : comp->offset != orig->offset)
419 : 0 : continue;
420 : :
421 : : /*
422 : : * trace_probe_compare_arg_type() ensured that nr_args and
423 : : * each argument name and type are same. Let's compare comm.
424 : : */
425 [ # # ]: 0 : for (i = 0; i < orig->tp.nr_args; i++) {
426 [ # # ]: 0 : if (strcmp(orig->tp.args[i].comm,
427 : : comp->tp.args[i].comm))
428 : : break;
429 : : }
430 : :
431 [ # # ]: 0 : if (i == orig->tp.nr_args)
432 : : return true;
433 : : }
434 : :
435 : : return false;
436 : : }
437 : :
438 : 0 : static int append_trace_uprobe(struct trace_uprobe *tu, struct trace_uprobe *to)
439 : : {
440 : 0 : int ret;
441 : :
442 : 0 : ret = trace_probe_compare_arg_type(&tu->tp, &to->tp);
443 [ # # ]: 0 : if (ret) {
444 : : /* Note that argument starts index = 2 */
445 : 0 : trace_probe_log_set_index(ret + 1);
446 : 0 : trace_probe_log_err(0, DIFF_ARG_TYPE);
447 : 0 : return -EEXIST;
448 : : }
449 [ # # ]: 0 : if (trace_uprobe_has_same_uprobe(to, tu)) {
450 : 0 : trace_probe_log_set_index(0);
451 : 0 : trace_probe_log_err(0, SAME_PROBE);
452 : 0 : return -EEXIST;
453 : : }
454 : :
455 : : /* Append to existing event */
456 : 0 : ret = trace_probe_append(&tu->tp, &to->tp);
457 [ # # ]: 0 : if (!ret)
458 [ # # ]: 0 : dyn_event_add(&tu->devent);
459 : :
460 : : return ret;
461 : : }
462 : :
463 : : /*
464 : : * Uprobe with multiple reference counter is not allowed. i.e.
465 : : * If inode and offset matches, reference counter offset *must*
466 : : * match as well. Though, there is one exception: If user is
467 : : * replacing old trace_uprobe with new one(same group/event),
468 : : * then we allow same uprobe with new reference counter as far
469 : : * as the new one does not conflict with any other existing
470 : : * ones.
471 : : */
472 : 0 : static int validate_ref_ctr_offset(struct trace_uprobe *new)
473 : : {
474 : 0 : struct dyn_event *pos;
475 : 0 : struct trace_uprobe *tmp;
476 [ # # ]: 0 : struct inode *new_inode = d_real_inode(new->path.dentry);
477 : :
478 [ # # # # : 0 : for_each_trace_uprobe(tmp, pos) {
# # ]
479 [ # # # # ]: 0 : if (new_inode == d_real_inode(tmp->path.dentry) &&
480 [ # # ]: 0 : new->offset == tmp->offset &&
481 [ # # ]: 0 : new->ref_ctr_offset != tmp->ref_ctr_offset) {
482 : 0 : pr_warn("Reference counter offset mismatch.");
483 : 0 : return -EINVAL;
484 : : }
485 : : }
486 : : return 0;
487 : : }
488 : :
489 : : /* Register a trace_uprobe and probe_event */
490 : 0 : static int register_trace_uprobe(struct trace_uprobe *tu)
491 : : {
492 : 0 : struct trace_uprobe *old_tu;
493 : 0 : int ret;
494 : :
495 : 0 : mutex_lock(&event_mutex);
496 : :
497 : 0 : ret = validate_ref_ctr_offset(tu);
498 [ # # ]: 0 : if (ret)
499 : 0 : goto end;
500 : :
501 : : /* register as an event */
502 [ # # ]: 0 : old_tu = find_probe_event(trace_probe_name(&tu->tp),
503 : : trace_probe_group_name(&tu->tp));
504 [ # # ]: 0 : if (old_tu) {
505 [ # # ]: 0 : if (is_ret_probe(tu) != is_ret_probe(old_tu)) {
506 : 0 : trace_probe_log_set_index(0);
507 : 0 : trace_probe_log_err(0, DIFF_PROBE_TYPE);
508 : 0 : ret = -EEXIST;
509 : : } else {
510 : 0 : ret = append_trace_uprobe(tu, old_tu);
511 : : }
512 : 0 : goto end;
513 : : }
514 : :
515 : 0 : ret = register_uprobe_event(tu);
516 [ # # ]: 0 : if (ret) {
517 : 0 : pr_warn("Failed to register probe event(%d)\n", ret);
518 : 0 : goto end;
519 : : }
520 : :
521 [ # # ]: 0 : dyn_event_add(&tu->devent);
522 : :
523 : 0 : end:
524 : 0 : mutex_unlock(&event_mutex);
525 : :
526 : 0 : return ret;
527 : : }
528 : :
529 : : /*
530 : : * Argument syntax:
531 : : * - Add uprobe: p|r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS]
532 : : */
533 : 0 : static int trace_uprobe_create(int argc, const char **argv)
534 : : {
535 : 0 : struct trace_uprobe *tu;
536 : 0 : const char *event = NULL, *group = UPROBE_EVENT_SYSTEM;
537 : 0 : char *arg, *filename, *rctr, *rctr_end, *tmp;
538 : 0 : char buf[MAX_EVENT_NAME_LEN];
539 : 0 : struct path path;
540 : 0 : unsigned long offset, ref_ctr_offset;
541 : 0 : bool is_return = false;
542 : 0 : int i, ret;
543 : :
544 : 0 : ret = 0;
545 : 0 : ref_ctr_offset = 0;
546 : :
547 [ # # # ]: 0 : switch (argv[0][0]) {
548 : 0 : case 'r':
549 : 0 : is_return = true;
550 : 0 : break;
551 : : case 'p':
552 : : break;
553 : : default:
554 : : return -ECANCELED;
555 : : }
556 : :
557 [ # # ]: 0 : if (argc < 2)
558 : : return -ECANCELED;
559 : :
560 [ # # ]: 0 : if (argv[0][1] == ':')
561 : 0 : event = &argv[0][2];
562 : :
563 [ # # ]: 0 : if (!strchr(argv[1], '/'))
564 : : return -ECANCELED;
565 : :
566 : 0 : filename = kstrdup(argv[1], GFP_KERNEL);
567 [ # # ]: 0 : if (!filename)
568 : : return -ENOMEM;
569 : :
570 : : /* Find the last occurrence, in case the path contains ':' too. */
571 : 0 : arg = strrchr(filename, ':');
572 [ # # # # ]: 0 : if (!arg || !isdigit(arg[1])) {
573 : 0 : kfree(filename);
574 : 0 : return -ECANCELED;
575 : : }
576 : :
577 : 0 : trace_probe_log_init("trace_uprobe", argc, argv);
578 : 0 : trace_probe_log_set_index(1); /* filename is the 2nd argument */
579 : :
580 : 0 : *arg++ = '\0';
581 : 0 : ret = kern_path(filename, LOOKUP_FOLLOW, &path);
582 [ # # ]: 0 : if (ret) {
583 : 0 : trace_probe_log_err(0, FILE_NOT_FOUND);
584 : 0 : kfree(filename);
585 : 0 : trace_probe_log_clear();
586 : 0 : return ret;
587 : : }
588 [ # # ]: 0 : if (!d_is_reg(path.dentry)) {
589 : 0 : trace_probe_log_err(0, NO_REGULAR_FILE);
590 : 0 : ret = -EINVAL;
591 : 0 : goto fail_address_parse;
592 : : }
593 : :
594 : : /* Parse reference counter offset if specified. */
595 : 0 : rctr = strchr(arg, '(');
596 [ # # ]: 0 : if (rctr) {
597 : 0 : rctr_end = strchr(rctr, ')');
598 [ # # ]: 0 : if (!rctr_end) {
599 : 0 : ret = -EINVAL;
600 : 0 : rctr_end = rctr + strlen(rctr);
601 : 0 : trace_probe_log_err(rctr_end - filename,
602 : : REFCNT_OPEN_BRACE);
603 : 0 : goto fail_address_parse;
604 [ # # ]: 0 : } else if (rctr_end[1] != '\0') {
605 : 0 : ret = -EINVAL;
606 : 0 : trace_probe_log_err(rctr_end + 1 - filename,
607 : : BAD_REFCNT_SUFFIX);
608 : 0 : goto fail_address_parse;
609 : : }
610 : :
611 : 0 : *rctr++ = '\0';
612 : 0 : *rctr_end = '\0';
613 : 0 : ret = kstrtoul(rctr, 0, &ref_ctr_offset);
614 [ # # ]: 0 : if (ret) {
615 : 0 : trace_probe_log_err(rctr - filename, BAD_REFCNT);
616 : 0 : goto fail_address_parse;
617 : : }
618 : : }
619 : :
620 : : /* Parse uprobe offset. */
621 : 0 : ret = kstrtoul(arg, 0, &offset);
622 [ # # ]: 0 : if (ret) {
623 : 0 : trace_probe_log_err(arg - filename, BAD_UPROBE_OFFS);
624 : 0 : goto fail_address_parse;
625 : : }
626 : :
627 : : /* setup a probe */
628 : 0 : trace_probe_log_set_index(0);
629 [ # # ]: 0 : if (event) {
630 : 0 : ret = traceprobe_parse_event_name(&event, &group, buf,
631 : 0 : event - argv[0]);
632 [ # # ]: 0 : if (ret)
633 : 0 : goto fail_address_parse;
634 : : } else {
635 : 0 : char *tail;
636 : 0 : char *ptr;
637 : :
638 [ # # ]: 0 : tail = kstrdup(kbasename(filename), GFP_KERNEL);
639 [ # # ]: 0 : if (!tail) {
640 : 0 : ret = -ENOMEM;
641 : 0 : goto fail_address_parse;
642 : : }
643 : :
644 : 0 : ptr = strpbrk(tail, ".-_");
645 [ # # ]: 0 : if (ptr)
646 : 0 : *ptr = '\0';
647 : :
648 : 0 : snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail, offset);
649 : 0 : event = buf;
650 : 0 : kfree(tail);
651 : : }
652 : :
653 : 0 : argc -= 2;
654 : 0 : argv += 2;
655 : :
656 : 0 : tu = alloc_trace_uprobe(group, event, argc, is_return);
657 [ # # ]: 0 : if (IS_ERR(tu)) {
658 [ # # ]: 0 : ret = PTR_ERR(tu);
659 : : /* This must return -ENOMEM otherwise there is a bug */
660 [ # # ]: 0 : WARN_ON_ONCE(ret != -ENOMEM);
661 : 0 : goto fail_address_parse;
662 : : }
663 : 0 : tu->offset = offset;
664 : 0 : tu->ref_ctr_offset = ref_ctr_offset;
665 : 0 : tu->path = path;
666 : 0 : tu->filename = filename;
667 : :
668 : : /* parse arguments */
669 [ # # ]: 0 : for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
670 : 0 : tmp = kstrdup(argv[i], GFP_KERNEL);
671 [ # # ]: 0 : if (!tmp) {
672 : 0 : ret = -ENOMEM;
673 : 0 : goto error;
674 : : }
675 : :
676 : 0 : trace_probe_log_set_index(i + 2);
677 [ # # ]: 0 : ret = traceprobe_parse_probe_arg(&tu->tp, i, tmp,
678 : : is_return ? TPARG_FL_RETURN : 0);
679 : 0 : kfree(tmp);
680 [ # # ]: 0 : if (ret)
681 : 0 : goto error;
682 : : }
683 : :
684 : 0 : ret = traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu));
685 [ # # ]: 0 : if (ret < 0)
686 : 0 : goto error;
687 : :
688 : 0 : ret = register_trace_uprobe(tu);
689 [ # # ]: 0 : if (!ret)
690 : 0 : goto out;
691 : :
692 : 0 : error:
693 : 0 : free_trace_uprobe(tu);
694 : 0 : out:
695 : 0 : trace_probe_log_clear();
696 : 0 : return ret;
697 : :
698 : 0 : fail_address_parse:
699 : 0 : trace_probe_log_clear();
700 : 0 : path_put(&path);
701 : 0 : kfree(filename);
702 : :
703 : 0 : return ret;
704 : : }
705 : :
706 : 0 : static int create_or_delete_trace_uprobe(int argc, char **argv)
707 : : {
708 : 0 : int ret;
709 : :
710 [ # # ]: 0 : if (argv[0][0] == '-')
711 : 0 : return dyn_event_release(argc, argv, &trace_uprobe_ops);
712 : :
713 : 0 : ret = trace_uprobe_create(argc, (const char **)argv);
714 [ # # ]: 0 : return ret == -ECANCELED ? -EINVAL : ret;
715 : : }
716 : :
717 : 0 : static int trace_uprobe_release(struct dyn_event *ev)
718 : : {
719 : 0 : struct trace_uprobe *tu = to_trace_uprobe(ev);
720 : :
721 : 0 : return unregister_trace_uprobe(tu);
722 : : }
723 : :
724 : : /* Probes listing interfaces */
725 : 0 : static int trace_uprobe_show(struct seq_file *m, struct dyn_event *ev)
726 : : {
727 : 0 : struct trace_uprobe *tu = to_trace_uprobe(ev);
728 [ # # ]: 0 : char c = is_ret_probe(tu) ? 'r' : 'p';
729 : 0 : int i;
730 : :
731 [ # # ]: 0 : seq_printf(m, "%c:%s/%s %s:0x%0*lx", c, trace_probe_group_name(&tu->tp),
732 : : trace_probe_name(&tu->tp), tu->filename,
733 : : (int)(sizeof(void *) * 2), tu->offset);
734 : :
735 [ # # ]: 0 : if (tu->ref_ctr_offset)
736 : 0 : seq_printf(m, "(0x%lx)", tu->ref_ctr_offset);
737 : :
738 [ # # ]: 0 : for (i = 0; i < tu->tp.nr_args; i++)
739 : 0 : seq_printf(m, " %s=%s", tu->tp.args[i].name, tu->tp.args[i].comm);
740 : :
741 : 0 : seq_putc(m, '\n');
742 : 0 : return 0;
743 : : }
744 : :
745 : 0 : static int probes_seq_show(struct seq_file *m, void *v)
746 : : {
747 : 0 : struct dyn_event *ev = v;
748 : :
749 [ # # ]: 0 : if (!is_trace_uprobe(ev))
750 : : return 0;
751 : :
752 : 0 : return trace_uprobe_show(m, ev);
753 : : }
754 : :
755 : : static const struct seq_operations probes_seq_op = {
756 : : .start = dyn_event_seq_start,
757 : : .next = dyn_event_seq_next,
758 : : .stop = dyn_event_seq_stop,
759 : : .show = probes_seq_show
760 : : };
761 : :
762 : 0 : static int probes_open(struct inode *inode, struct file *file)
763 : : {
764 : 0 : int ret;
765 : :
766 : 0 : ret = security_locked_down(LOCKDOWN_TRACEFS);
767 [ # # ]: 0 : if (ret)
768 : : return ret;
769 : :
770 [ # # ]: 0 : if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
771 : 0 : ret = dyn_events_release_all(&trace_uprobe_ops);
772 [ # # ]: 0 : if (ret)
773 : : return ret;
774 : : }
775 : :
776 : 0 : return seq_open(file, &probes_seq_op);
777 : : }
778 : :
779 : 0 : static ssize_t probes_write(struct file *file, const char __user *buffer,
780 : : size_t count, loff_t *ppos)
781 : : {
782 : 0 : return trace_parse_run_command(file, buffer, count, ppos,
783 : : create_or_delete_trace_uprobe);
784 : : }
785 : :
786 : : static const struct file_operations uprobe_events_ops = {
787 : : .owner = THIS_MODULE,
788 : : .open = probes_open,
789 : : .read = seq_read,
790 : : .llseek = seq_lseek,
791 : : .release = seq_release,
792 : : .write = probes_write,
793 : : };
794 : :
795 : : /* Probes profiling interfaces */
796 : 0 : static int probes_profile_seq_show(struct seq_file *m, void *v)
797 : : {
798 : 0 : struct dyn_event *ev = v;
799 : 0 : struct trace_uprobe *tu;
800 : :
801 [ # # ]: 0 : if (!is_trace_uprobe(ev))
802 : : return 0;
803 : :
804 : 0 : tu = to_trace_uprobe(ev);
805 [ # # ]: 0 : seq_printf(m, " %s %-44s %15lu\n", tu->filename,
806 : : trace_probe_name(&tu->tp), tu->nhit);
807 : 0 : return 0;
808 : : }
809 : :
810 : : static const struct seq_operations profile_seq_op = {
811 : : .start = dyn_event_seq_start,
812 : : .next = dyn_event_seq_next,
813 : : .stop = dyn_event_seq_stop,
814 : : .show = probes_profile_seq_show
815 : : };
816 : :
817 : 0 : static int profile_open(struct inode *inode, struct file *file)
818 : : {
819 : 0 : int ret;
820 : :
821 : 0 : ret = security_locked_down(LOCKDOWN_TRACEFS);
822 [ # # ]: 0 : if (ret)
823 : : return ret;
824 : :
825 : 0 : return seq_open(file, &profile_seq_op);
826 : : }
827 : :
828 : : static const struct file_operations uprobe_profile_ops = {
829 : : .owner = THIS_MODULE,
830 : : .open = profile_open,
831 : : .read = seq_read,
832 : : .llseek = seq_lseek,
833 : : .release = seq_release,
834 : : };
835 : :
836 : : struct uprobe_cpu_buffer {
837 : : struct mutex mutex;
838 : : void *buf;
839 : : };
840 : : static struct uprobe_cpu_buffer __percpu *uprobe_cpu_buffer;
841 : : static int uprobe_buffer_refcnt;
842 : :
843 : 0 : static int uprobe_buffer_init(void)
844 : : {
845 : 0 : int cpu, err_cpu;
846 : :
847 : 0 : uprobe_cpu_buffer = alloc_percpu(struct uprobe_cpu_buffer);
848 [ # # ]: 0 : if (uprobe_cpu_buffer == NULL)
849 : : return -ENOMEM;
850 : :
851 [ # # ]: 0 : for_each_possible_cpu(cpu) {
852 [ # # ]: 0 : struct page *p = alloc_pages_node(cpu_to_node(cpu),
853 : : GFP_KERNEL, 0);
854 [ # # ]: 0 : if (p == NULL) {
855 : 0 : err_cpu = cpu;
856 : 0 : goto err;
857 : : }
858 : 0 : per_cpu_ptr(uprobe_cpu_buffer, cpu)->buf = page_address(p);
859 : 0 : mutex_init(&per_cpu_ptr(uprobe_cpu_buffer, cpu)->mutex);
860 : : }
861 : :
862 : : return 0;
863 : :
864 : : err:
865 [ # # ]: 0 : for_each_possible_cpu(cpu) {
866 [ # # ]: 0 : if (cpu == err_cpu)
867 : : break;
868 : 0 : free_page((unsigned long)per_cpu_ptr(uprobe_cpu_buffer, cpu)->buf);
869 : : }
870 : :
871 : 0 : free_percpu(uprobe_cpu_buffer);
872 : 0 : return -ENOMEM;
873 : : }
874 : :
875 : 0 : static int uprobe_buffer_enable(void)
876 : : {
877 : 0 : int ret = 0;
878 : :
879 [ # # ]: 0 : BUG_ON(!mutex_is_locked(&event_mutex));
880 : :
881 [ # # ]: 0 : if (uprobe_buffer_refcnt++ == 0) {
882 : 0 : ret = uprobe_buffer_init();
883 [ # # ]: 0 : if (ret < 0)
884 : 0 : uprobe_buffer_refcnt--;
885 : : }
886 : :
887 : 0 : return ret;
888 : : }
889 : :
890 : 0 : static void uprobe_buffer_disable(void)
891 : : {
892 : 0 : int cpu;
893 : :
894 [ # # ]: 0 : BUG_ON(!mutex_is_locked(&event_mutex));
895 : :
896 [ # # ]: 0 : if (--uprobe_buffer_refcnt == 0) {
897 [ # # ]: 0 : for_each_possible_cpu(cpu)
898 : 0 : free_page((unsigned long)per_cpu_ptr(uprobe_cpu_buffer,
899 : : cpu)->buf);
900 : :
901 : 0 : free_percpu(uprobe_cpu_buffer);
902 : 0 : uprobe_cpu_buffer = NULL;
903 : : }
904 : 0 : }
905 : :
906 : 0 : static struct uprobe_cpu_buffer *uprobe_buffer_get(void)
907 : : {
908 : 0 : struct uprobe_cpu_buffer *ucb;
909 : 0 : int cpu;
910 : :
911 : 0 : cpu = raw_smp_processor_id();
912 : 0 : ucb = per_cpu_ptr(uprobe_cpu_buffer, cpu);
913 : :
914 : : /*
915 : : * Use per-cpu buffers for fastest access, but we might migrate
916 : : * so the mutex makes sure we have sole access to it.
917 : : */
918 : 0 : mutex_lock(&ucb->mutex);
919 : :
920 : 0 : return ucb;
921 : : }
922 : :
923 : 0 : static void uprobe_buffer_put(struct uprobe_cpu_buffer *ucb)
924 : : {
925 : 0 : mutex_unlock(&ucb->mutex);
926 : : }
927 : :
928 : : static void __uprobe_trace_func(struct trace_uprobe *tu,
929 : : unsigned long func, struct pt_regs *regs,
930 : : struct uprobe_cpu_buffer *ucb, int dsize,
931 : : struct trace_event_file *trace_file)
932 : : {
933 : : struct uprobe_trace_entry_head *entry;
934 : : struct trace_buffer *buffer;
935 : : struct ring_buffer_event *event;
936 : : void *data;
937 : : int size, esize;
938 : : struct trace_event_call *call = trace_probe_event_call(&tu->tp);
939 : :
940 : : WARN_ON(call != trace_file->event_call);
941 : :
942 : : if (WARN_ON_ONCE(tu->tp.size + dsize > PAGE_SIZE))
943 : : return;
944 : :
945 : : if (trace_trigger_soft_disabled(trace_file))
946 : : return;
947 : :
948 : : esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
949 : : size = esize + tu->tp.size + dsize;
950 : : event = trace_event_buffer_lock_reserve(&buffer, trace_file,
951 : : call->event.type, size, 0, 0);
952 : : if (!event)
953 : : return;
954 : :
955 : : entry = ring_buffer_event_data(event);
956 : : if (is_ret_probe(tu)) {
957 : : entry->vaddr[0] = func;
958 : : entry->vaddr[1] = instruction_pointer(regs);
959 : : data = DATAOF_TRACE_ENTRY(entry, true);
960 : : } else {
961 : : entry->vaddr[0] = instruction_pointer(regs);
962 : : data = DATAOF_TRACE_ENTRY(entry, false);
963 : : }
964 : :
965 : : memcpy(data, ucb->buf, tu->tp.size + dsize);
966 : :
967 : : event_trigger_unlock_commit(trace_file, buffer, event, entry, 0, 0);
968 : : }
969 : :
970 : : /* uprobe handler */
971 : 0 : static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs,
972 : : struct uprobe_cpu_buffer *ucb, int dsize)
973 : : {
974 : 0 : struct event_file_link *link;
975 : :
976 [ # # ]: 0 : if (is_ret_probe(tu))
977 : : return 0;
978 : :
979 : 0 : rcu_read_lock();
980 [ # # ]: 0 : trace_probe_for_each_link_rcu(link, &tu->tp)
981 : 0 : __uprobe_trace_func(tu, 0, regs, ucb, dsize, link->file);
982 : 0 : rcu_read_unlock();
983 : :
984 : 0 : return 0;
985 : : }
986 : :
987 : 0 : static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func,
988 : : struct pt_regs *regs,
989 : : struct uprobe_cpu_buffer *ucb, int dsize)
990 : : {
991 : 0 : struct event_file_link *link;
992 : :
993 : 0 : rcu_read_lock();
994 [ # # ]: 0 : trace_probe_for_each_link_rcu(link, &tu->tp)
995 : 0 : __uprobe_trace_func(tu, func, regs, ucb, dsize, link->file);
996 : 0 : rcu_read_unlock();
997 : 0 : }
998 : :
999 : : /* Event entry printers */
1000 : : static enum print_line_t
1001 : 0 : print_uprobe_event(struct trace_iterator *iter, int flags, struct trace_event *event)
1002 : : {
1003 : 0 : struct uprobe_trace_entry_head *entry;
1004 : 0 : struct trace_seq *s = &iter->seq;
1005 : 0 : struct trace_uprobe *tu;
1006 : 0 : u8 *data;
1007 : :
1008 : 0 : entry = (struct uprobe_trace_entry_head *)iter->ent;
1009 : 0 : tu = trace_uprobe_primary_from_call(
1010 [ # # ]: 0 : container_of(event, struct trace_event_call, event));
1011 [ # # ]: 0 : if (unlikely(!tu))
1012 : 0 : goto out;
1013 : :
1014 [ # # ]: 0 : if (is_ret_probe(tu)) {
1015 [ # # ]: 0 : trace_seq_printf(s, "%s: (0x%lx <- 0x%lx)",
1016 : : trace_probe_name(&tu->tp),
1017 : : entry->vaddr[1], entry->vaddr[0]);
1018 : 0 : data = DATAOF_TRACE_ENTRY(entry, true);
1019 : : } else {
1020 [ # # ]: 0 : trace_seq_printf(s, "%s: (0x%lx)",
1021 : : trace_probe_name(&tu->tp),
1022 : : entry->vaddr[0]);
1023 : 0 : data = DATAOF_TRACE_ENTRY(entry, false);
1024 : : }
1025 : :
1026 [ # # ]: 0 : if (print_probe_args(s, tu->tp.args, tu->tp.nr_args, data, entry) < 0)
1027 : 0 : goto out;
1028 : :
1029 : 0 : trace_seq_putc(s, '\n');
1030 : :
1031 : 0 : out:
1032 : 0 : return trace_handle_return(s);
1033 : : }
1034 : :
1035 : : typedef bool (*filter_func_t)(struct uprobe_consumer *self,
1036 : : enum uprobe_filter_ctx ctx,
1037 : : struct mm_struct *mm);
1038 : :
1039 : 0 : static int trace_uprobe_enable(struct trace_uprobe *tu, filter_func_t filter)
1040 : : {
1041 : 0 : int ret;
1042 : :
1043 : 0 : tu->consumer.filter = filter;
1044 [ # # ]: 0 : tu->inode = d_real_inode(tu->path.dentry);
1045 : :
1046 [ # # ]: 0 : if (tu->ref_ctr_offset)
1047 : 0 : ret = uprobe_register_refctr(tu->inode, tu->offset,
1048 : : tu->ref_ctr_offset, &tu->consumer);
1049 : : else
1050 : 0 : ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
1051 : :
1052 [ # # ]: 0 : if (ret)
1053 : 0 : tu->inode = NULL;
1054 : :
1055 : 0 : return ret;
1056 : : }
1057 : :
1058 : 0 : static void __probe_event_disable(struct trace_probe *tp)
1059 : : {
1060 : 0 : struct trace_probe *pos;
1061 : 0 : struct trace_uprobe *tu;
1062 : :
1063 : 0 : tu = container_of(tp, struct trace_uprobe, tp);
1064 [ # # # # ]: 0 : WARN_ON(!uprobe_filter_is_empty(tu->tp.event->filter));
1065 : :
1066 [ # # ]: 0 : list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
1067 : 0 : tu = container_of(pos, struct trace_uprobe, tp);
1068 [ # # ]: 0 : if (!tu->inode)
1069 : 0 : continue;
1070 : :
1071 : 0 : uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
1072 : 0 : tu->inode = NULL;
1073 : : }
1074 : 0 : }
1075 : :
1076 : 0 : static int probe_event_enable(struct trace_event_call *call,
1077 : : struct trace_event_file *file, filter_func_t filter)
1078 : : {
1079 : 0 : struct trace_probe *pos, *tp;
1080 : 0 : struct trace_uprobe *tu;
1081 : 0 : bool enabled;
1082 : 0 : int ret;
1083 : :
1084 [ # # ]: 0 : tp = trace_probe_primary_from_call(call);
1085 [ # # # # ]: 0 : if (WARN_ON_ONCE(!tp))
1086 : : return -ENODEV;
1087 [ # # ]: 0 : enabled = trace_probe_is_enabled(tp);
1088 : :
1089 : : /* This may also change "enabled" state */
1090 [ # # ]: 0 : if (file) {
1091 [ # # ]: 0 : if (trace_probe_test_flag(tp, TP_FLAG_PROFILE))
1092 : : return -EINTR;
1093 : :
1094 : 0 : ret = trace_probe_add_file(tp, file);
1095 [ # # ]: 0 : if (ret < 0)
1096 : : return ret;
1097 : : } else {
1098 [ # # ]: 0 : if (trace_probe_test_flag(tp, TP_FLAG_TRACE))
1099 : : return -EINTR;
1100 : :
1101 : 0 : trace_probe_set_flag(tp, TP_FLAG_PROFILE);
1102 : : }
1103 : :
1104 : 0 : tu = container_of(tp, struct trace_uprobe, tp);
1105 [ # # # # ]: 0 : WARN_ON(!uprobe_filter_is_empty(tu->tp.event->filter));
1106 : :
1107 [ # # ]: 0 : if (enabled)
1108 : : return 0;
1109 : :
1110 : 0 : ret = uprobe_buffer_enable();
1111 [ # # ]: 0 : if (ret)
1112 : 0 : goto err_flags;
1113 : :
1114 [ # # ]: 0 : list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
1115 : 0 : tu = container_of(pos, struct trace_uprobe, tp);
1116 : 0 : ret = trace_uprobe_enable(tu, filter);
1117 [ # # ]: 0 : if (ret) {
1118 : 0 : __probe_event_disable(tp);
1119 : 0 : goto err_buffer;
1120 : : }
1121 : : }
1122 : :
1123 : : return 0;
1124 : :
1125 : : err_buffer:
1126 : 0 : uprobe_buffer_disable();
1127 : :
1128 : 0 : err_flags:
1129 [ # # ]: 0 : if (file)
1130 : 0 : trace_probe_remove_file(tp, file);
1131 : : else
1132 : 0 : trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
1133 : :
1134 : : return ret;
1135 : : }
1136 : :
1137 : 0 : static void probe_event_disable(struct trace_event_call *call,
1138 : : struct trace_event_file *file)
1139 : : {
1140 : 0 : struct trace_probe *tp;
1141 : :
1142 [ # # ]: 0 : tp = trace_probe_primary_from_call(call);
1143 [ # # # # ]: 0 : if (WARN_ON_ONCE(!tp))
1144 : : return;
1145 : :
1146 [ # # ]: 0 : if (!trace_probe_is_enabled(tp))
1147 : : return;
1148 : :
1149 [ # # ]: 0 : if (file) {
1150 [ # # ]: 0 : if (trace_probe_remove_file(tp, file) < 0)
1151 : : return;
1152 : :
1153 [ # # ]: 0 : if (trace_probe_is_enabled(tp))
1154 : : return;
1155 : : } else
1156 : 0 : trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
1157 : :
1158 : 0 : __probe_event_disable(tp);
1159 : 0 : uprobe_buffer_disable();
1160 : : }
1161 : :
1162 : 0 : static int uprobe_event_define_fields(struct trace_event_call *event_call)
1163 : : {
1164 : 0 : int ret, size;
1165 : 0 : struct uprobe_trace_entry_head field;
1166 : 0 : struct trace_uprobe *tu;
1167 : :
1168 [ # # ]: 0 : tu = trace_uprobe_primary_from_call(event_call);
1169 [ # # ]: 0 : if (unlikely(!tu))
1170 : : return -ENODEV;
1171 : :
1172 [ # # ]: 0 : if (is_ret_probe(tu)) {
1173 [ # # ]: 0 : DEFINE_FIELD(unsigned long, vaddr[0], FIELD_STRING_FUNC, 0);
1174 [ # # ]: 0 : DEFINE_FIELD(unsigned long, vaddr[1], FIELD_STRING_RETIP, 0);
1175 : : size = SIZEOF_TRACE_ENTRY(true);
1176 : : } else {
1177 [ # # ]: 0 : DEFINE_FIELD(unsigned long, vaddr[0], FIELD_STRING_IP, 0);
1178 : : size = SIZEOF_TRACE_ENTRY(false);
1179 : : }
1180 : :
1181 : 0 : return traceprobe_define_arg_fields(event_call, size, &tu->tp);
1182 : : }
1183 : :
1184 : : #ifdef CONFIG_PERF_EVENTS
1185 : : static bool
1186 : 0 : __uprobe_perf_filter(struct trace_uprobe_filter *filter, struct mm_struct *mm)
1187 : : {
1188 : 0 : struct perf_event *event;
1189 : :
1190 : 0 : if (filter->nr_systemwide)
1191 : : return true;
1192 : :
1193 [ # # # # : 0 : list_for_each_entry(event, &filter->perf_events, hw.tp_list) {
# # ]
1194 [ # # # # : 0 : if (event->hw.target->mm == mm)
# # ]
1195 : : return true;
1196 : : }
1197 : :
1198 : : return false;
1199 : : }
1200 : :
1201 : : static inline bool
1202 : 0 : trace_uprobe_filter_event(struct trace_uprobe_filter *filter,
1203 : : struct perf_event *event)
1204 : : {
1205 : 0 : return __uprobe_perf_filter(filter, event->hw.target->mm);
1206 : : }
1207 : :
1208 : 0 : static bool trace_uprobe_filter_remove(struct trace_uprobe_filter *filter,
1209 : : struct perf_event *event)
1210 : : {
1211 : 0 : bool done;
1212 : :
1213 : 0 : write_lock(&filter->rwlock);
1214 [ # # ]: 0 : if (event->hw.target) {
1215 [ # # ]: 0 : list_del(&event->hw.tp_list);
1216 : 0 : done = filter->nr_systemwide ||
1217 [ # # # # : 0 : (event->hw.target->flags & PF_EXITING) ||
# # ]
1218 : : trace_uprobe_filter_event(filter, event);
1219 : : } else {
1220 : 0 : filter->nr_systemwide--;
1221 : 0 : done = filter->nr_systemwide;
1222 : : }
1223 : 0 : write_unlock(&filter->rwlock);
1224 : :
1225 : 0 : return done;
1226 : : }
1227 : :
1228 : : /* This returns true if the filter always covers target mm */
1229 : 0 : static bool trace_uprobe_filter_add(struct trace_uprobe_filter *filter,
1230 : : struct perf_event *event)
1231 : : {
1232 : 0 : bool done;
1233 : :
1234 : 0 : write_lock(&filter->rwlock);
1235 [ # # ]: 0 : if (event->hw.target) {
1236 : : /*
1237 : : * event->parent != NULL means copy_process(), we can avoid
1238 : : * uprobe_apply(). current->mm must be probed and we can rely
1239 : : * on dup_mmap() which preserves the already installed bp's.
1240 : : *
1241 : : * attr.enable_on_exec means that exec/mmap will install the
1242 : : * breakpoints we need.
1243 : : */
1244 : 0 : done = filter->nr_systemwide ||
1245 [ # # # # : 0 : event->parent || event->attr.enable_on_exec ||
# # # # ]
1246 : : trace_uprobe_filter_event(filter, event);
1247 : 0 : list_add(&event->hw.tp_list, &filter->perf_events);
1248 : : } else {
1249 : 0 : done = filter->nr_systemwide;
1250 : 0 : filter->nr_systemwide++;
1251 : : }
1252 : 0 : write_unlock(&filter->rwlock);
1253 : :
1254 : 0 : return done;
1255 : : }
1256 : :
1257 : 0 : static int uprobe_perf_close(struct trace_event_call *call,
1258 : : struct perf_event *event)
1259 : : {
1260 : 0 : struct trace_probe *pos, *tp;
1261 : 0 : struct trace_uprobe *tu;
1262 : 0 : int ret = 0;
1263 : :
1264 [ # # ]: 0 : tp = trace_probe_primary_from_call(call);
1265 [ # # # # ]: 0 : if (WARN_ON_ONCE(!tp))
1266 : : return -ENODEV;
1267 : :
1268 : 0 : tu = container_of(tp, struct trace_uprobe, tp);
1269 [ # # ]: 0 : if (trace_uprobe_filter_remove(tu->tp.event->filter, event))
1270 : : return 0;
1271 : :
1272 [ # # ]: 0 : list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
1273 : 0 : tu = container_of(pos, struct trace_uprobe, tp);
1274 : 0 : ret = uprobe_apply(tu->inode, tu->offset, &tu->consumer, false);
1275 [ # # ]: 0 : if (ret)
1276 : : break;
1277 : : }
1278 : :
1279 : : return ret;
1280 : : }
1281 : :
1282 : 0 : static int uprobe_perf_open(struct trace_event_call *call,
1283 : : struct perf_event *event)
1284 : : {
1285 : 0 : struct trace_probe *pos, *tp;
1286 : 0 : struct trace_uprobe *tu;
1287 : 0 : int err = 0;
1288 : :
1289 [ # # ]: 0 : tp = trace_probe_primary_from_call(call);
1290 [ # # # # ]: 0 : if (WARN_ON_ONCE(!tp))
1291 : : return -ENODEV;
1292 : :
1293 : 0 : tu = container_of(tp, struct trace_uprobe, tp);
1294 [ # # ]: 0 : if (trace_uprobe_filter_add(tu->tp.event->filter, event))
1295 : : return 0;
1296 : :
1297 [ # # ]: 0 : list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
1298 : 0 : err = uprobe_apply(tu->inode, tu->offset, &tu->consumer, true);
1299 [ # # ]: 0 : if (err) {
1300 : 0 : uprobe_perf_close(call, event);
1301 : 0 : break;
1302 : : }
1303 : : }
1304 : :
1305 : : return err;
1306 : : }
1307 : :
1308 : 0 : static bool uprobe_perf_filter(struct uprobe_consumer *uc,
1309 : : enum uprobe_filter_ctx ctx, struct mm_struct *mm)
1310 : : {
1311 : 0 : struct trace_uprobe_filter *filter;
1312 : 0 : struct trace_uprobe *tu;
1313 : 0 : int ret;
1314 : :
1315 : 0 : tu = container_of(uc, struct trace_uprobe, consumer);
1316 : 0 : filter = tu->tp.event->filter;
1317 : :
1318 : 0 : read_lock(&filter->rwlock);
1319 [ # # ]: 0 : ret = __uprobe_perf_filter(filter, mm);
1320 : 0 : read_unlock(&filter->rwlock);
1321 : :
1322 : 0 : return ret;
1323 : : }
1324 : :
1325 : : static void __uprobe_perf_func(struct trace_uprobe *tu,
1326 : : unsigned long func, struct pt_regs *regs,
1327 : : struct uprobe_cpu_buffer *ucb, int dsize)
1328 : : {
1329 : : struct trace_event_call *call = trace_probe_event_call(&tu->tp);
1330 : : struct uprobe_trace_entry_head *entry;
1331 : : struct hlist_head *head;
1332 : : void *data;
1333 : : int size, esize;
1334 : : int rctx;
1335 : :
1336 : : if (bpf_prog_array_valid(call) && !trace_call_bpf(call, regs))
1337 : : return;
1338 : :
1339 : : esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1340 : :
1341 : : size = esize + tu->tp.size + dsize;
1342 : : size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32);
1343 : : if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
1344 : : return;
1345 : :
1346 : : preempt_disable();
1347 : : head = this_cpu_ptr(call->perf_events);
1348 : : if (hlist_empty(head))
1349 : : goto out;
1350 : :
1351 : : entry = perf_trace_buf_alloc(size, NULL, &rctx);
1352 : : if (!entry)
1353 : : goto out;
1354 : :
1355 : : if (is_ret_probe(tu)) {
1356 : : entry->vaddr[0] = func;
1357 : : entry->vaddr[1] = instruction_pointer(regs);
1358 : : data = DATAOF_TRACE_ENTRY(entry, true);
1359 : : } else {
1360 : : entry->vaddr[0] = instruction_pointer(regs);
1361 : : data = DATAOF_TRACE_ENTRY(entry, false);
1362 : : }
1363 : :
1364 : : memcpy(data, ucb->buf, tu->tp.size + dsize);
1365 : :
1366 : : if (size - esize > tu->tp.size + dsize) {
1367 : : int len = tu->tp.size + dsize;
1368 : :
1369 : : memset(data + len, 0, size - esize - len);
1370 : : }
1371 : :
1372 : : perf_trace_buf_submit(entry, size, rctx, call->event.type, 1, regs,
1373 : : head, NULL);
1374 : : out:
1375 : : preempt_enable();
1376 : : }
1377 : :
1378 : : /* uprobe profile handler */
1379 : 0 : static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs,
1380 : : struct uprobe_cpu_buffer *ucb, int dsize)
1381 : : {
1382 [ # # ]: 0 : if (!uprobe_perf_filter(&tu->consumer, 0, current->mm))
1383 : : return UPROBE_HANDLER_REMOVE;
1384 : :
1385 [ # # ]: 0 : if (!is_ret_probe(tu))
1386 : 0 : __uprobe_perf_func(tu, 0, regs, ucb, dsize);
1387 : : return 0;
1388 : : }
1389 : :
1390 : 0 : static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
1391 : : struct pt_regs *regs,
1392 : : struct uprobe_cpu_buffer *ucb, int dsize)
1393 : : {
1394 : 0 : __uprobe_perf_func(tu, func, regs, ucb, dsize);
1395 : 0 : }
1396 : :
1397 : 0 : int bpf_get_uprobe_info(const struct perf_event *event, u32 *fd_type,
1398 : : const char **filename, u64 *probe_offset,
1399 : : bool perf_type_tracepoint)
1400 : : {
1401 [ # # ]: 0 : const char *pevent = trace_event_name(event->tp_event);
1402 : 0 : const char *group = event->tp_event->class->system;
1403 : 0 : struct trace_uprobe *tu;
1404 : :
1405 [ # # ]: 0 : if (perf_type_tracepoint)
1406 : 0 : tu = find_probe_event(pevent, group);
1407 : : else
1408 : 0 : tu = event->tp_event->data;
1409 [ # # ]: 0 : if (!tu)
1410 : : return -EINVAL;
1411 : :
1412 : 0 : *fd_type = is_ret_probe(tu) ? BPF_FD_TYPE_URETPROBE
1413 [ # # ]: 0 : : BPF_FD_TYPE_UPROBE;
1414 : 0 : *filename = tu->filename;
1415 : 0 : *probe_offset = tu->offset;
1416 : 0 : return 0;
1417 : : }
1418 : : #endif /* CONFIG_PERF_EVENTS */
1419 : :
1420 : : static int
1421 : 0 : trace_uprobe_register(struct trace_event_call *event, enum trace_reg type,
1422 : : void *data)
1423 : : {
1424 : 0 : struct trace_event_file *file = data;
1425 : :
1426 [ # # # # : 0 : switch (type) {
# # # ]
1427 : 0 : case TRACE_REG_REGISTER:
1428 : 0 : return probe_event_enable(event, file, NULL);
1429 : :
1430 : 0 : case TRACE_REG_UNREGISTER:
1431 : 0 : probe_event_disable(event, file);
1432 : 0 : return 0;
1433 : :
1434 : : #ifdef CONFIG_PERF_EVENTS
1435 : 0 : case TRACE_REG_PERF_REGISTER:
1436 : 0 : return probe_event_enable(event, NULL, uprobe_perf_filter);
1437 : :
1438 : 0 : case TRACE_REG_PERF_UNREGISTER:
1439 : 0 : probe_event_disable(event, NULL);
1440 : 0 : return 0;
1441 : :
1442 : 0 : case TRACE_REG_PERF_OPEN:
1443 : 0 : return uprobe_perf_open(event, data);
1444 : :
1445 : 0 : case TRACE_REG_PERF_CLOSE:
1446 : 0 : return uprobe_perf_close(event, data);
1447 : :
1448 : : #endif
1449 : : default:
1450 : : return 0;
1451 : : }
1452 : : return 0;
1453 : : }
1454 : :
1455 : 0 : static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
1456 : : {
1457 : 0 : struct trace_uprobe *tu;
1458 : 0 : struct uprobe_dispatch_data udd;
1459 : 0 : struct uprobe_cpu_buffer *ucb;
1460 : 0 : int dsize, esize;
1461 : 0 : int ret = 0;
1462 : :
1463 : :
1464 : 0 : tu = container_of(con, struct trace_uprobe, consumer);
1465 : 0 : tu->nhit++;
1466 : :
1467 : 0 : udd.tu = tu;
1468 [ # # ]: 0 : udd.bp_addr = instruction_pointer(regs);
1469 : :
1470 [ # # ]: 0 : current->utask->vaddr = (unsigned long) &udd;
1471 : :
1472 [ # # # # ]: 0 : if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1473 : : return 0;
1474 : :
1475 : : dsize = __get_data_size(&tu->tp, regs);
1476 [ # # ]: 0 : esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1477 : :
1478 : 0 : ucb = uprobe_buffer_get();
1479 : 0 : store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
1480 : :
1481 [ # # ]: 0 : if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
1482 : 0 : ret |= uprobe_trace_func(tu, regs, ucb, dsize);
1483 : :
1484 : : #ifdef CONFIG_PERF_EVENTS
1485 [ # # ]: 0 : if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
1486 : 0 : ret |= uprobe_perf_func(tu, regs, ucb, dsize);
1487 : : #endif
1488 : 0 : uprobe_buffer_put(ucb);
1489 : 0 : return ret;
1490 : : }
1491 : :
1492 : 0 : static int uretprobe_dispatcher(struct uprobe_consumer *con,
1493 : : unsigned long func, struct pt_regs *regs)
1494 : : {
1495 : 0 : struct trace_uprobe *tu;
1496 : 0 : struct uprobe_dispatch_data udd;
1497 : 0 : struct uprobe_cpu_buffer *ucb;
1498 : 0 : int dsize, esize;
1499 : :
1500 : 0 : tu = container_of(con, struct trace_uprobe, consumer);
1501 : :
1502 : 0 : udd.tu = tu;
1503 : 0 : udd.bp_addr = func;
1504 : :
1505 [ # # ]: 0 : current->utask->vaddr = (unsigned long) &udd;
1506 : :
1507 [ # # # # ]: 0 : if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1508 : : return 0;
1509 : :
1510 : : dsize = __get_data_size(&tu->tp, regs);
1511 [ # # ]: 0 : esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1512 : :
1513 : 0 : ucb = uprobe_buffer_get();
1514 : 0 : store_trace_args(ucb->buf, &tu->tp, regs, esize, dsize);
1515 : :
1516 [ # # ]: 0 : if (trace_probe_test_flag(&tu->tp, TP_FLAG_TRACE))
1517 : 0 : uretprobe_trace_func(tu, func, regs, ucb, dsize);
1518 : :
1519 : : #ifdef CONFIG_PERF_EVENTS
1520 [ # # ]: 0 : if (trace_probe_test_flag(&tu->tp, TP_FLAG_PROFILE))
1521 : 0 : uretprobe_perf_func(tu, func, regs, ucb, dsize);
1522 : : #endif
1523 : 0 : uprobe_buffer_put(ucb);
1524 : 0 : return 0;
1525 : : }
1526 : :
1527 : : static struct trace_event_functions uprobe_funcs = {
1528 : : .trace = print_uprobe_event
1529 : : };
1530 : :
1531 : : static struct trace_event_fields uprobe_fields_array[] = {
1532 : : { .type = TRACE_FUNCTION_TYPE,
1533 : : .define_fields = uprobe_event_define_fields },
1534 : : {}
1535 : : };
1536 : :
1537 : 0 : static inline void init_trace_event_call(struct trace_uprobe *tu)
1538 : : {
1539 : 0 : struct trace_event_call *call = trace_probe_event_call(&tu->tp);
1540 : 0 : call->event.funcs = &uprobe_funcs;
1541 : 0 : call->class->fields_array = uprobe_fields_array;
1542 : :
1543 : 0 : call->flags = TRACE_EVENT_FL_UPROBE | TRACE_EVENT_FL_CAP_ANY;
1544 : 0 : call->class->reg = trace_uprobe_register;
1545 : : }
1546 : :
1547 : 0 : static int register_uprobe_event(struct trace_uprobe *tu)
1548 : : {
1549 : 0 : init_trace_event_call(tu);
1550 : :
1551 : 0 : return trace_probe_register_event_call(&tu->tp);
1552 : : }
1553 : :
1554 : 0 : static int unregister_uprobe_event(struct trace_uprobe *tu)
1555 : : {
1556 : 0 : return trace_probe_unregister_event_call(&tu->tp);
1557 : : }
1558 : :
1559 : : #ifdef CONFIG_PERF_EVENTS
1560 : : struct trace_event_call *
1561 : 0 : create_local_trace_uprobe(char *name, unsigned long offs,
1562 : : unsigned long ref_ctr_offset, bool is_return)
1563 : : {
1564 : 0 : struct trace_uprobe *tu;
1565 : 0 : struct path path;
1566 : 0 : int ret;
1567 : :
1568 : 0 : ret = kern_path(name, LOOKUP_FOLLOW, &path);
1569 [ # # ]: 0 : if (ret)
1570 : 0 : return ERR_PTR(ret);
1571 : :
1572 [ # # ]: 0 : if (!d_is_reg(path.dentry)) {
1573 : 0 : path_put(&path);
1574 : 0 : return ERR_PTR(-EINVAL);
1575 : : }
1576 : :
1577 : : /*
1578 : : * local trace_kprobes are not added to dyn_event, so they are never
1579 : : * searched in find_trace_kprobe(). Therefore, there is no concern of
1580 : : * duplicated name "DUMMY_EVENT" here.
1581 : : */
1582 : 0 : tu = alloc_trace_uprobe(UPROBE_EVENT_SYSTEM, "DUMMY_EVENT", 0,
1583 : : is_return);
1584 : :
1585 [ # # ]: 0 : if (IS_ERR(tu)) {
1586 : 0 : pr_info("Failed to allocate trace_uprobe.(%d)\n",
1587 : : (int)PTR_ERR(tu));
1588 : 0 : path_put(&path);
1589 : 0 : return ERR_CAST(tu);
1590 : : }
1591 : :
1592 : 0 : tu->offset = offs;
1593 : 0 : tu->path = path;
1594 : 0 : tu->ref_ctr_offset = ref_ctr_offset;
1595 : 0 : tu->filename = kstrdup(name, GFP_KERNEL);
1596 : 0 : init_trace_event_call(tu);
1597 : :
1598 [ # # ]: 0 : if (traceprobe_set_print_fmt(&tu->tp, is_ret_probe(tu)) < 0) {
1599 : 0 : ret = -ENOMEM;
1600 : 0 : goto error;
1601 : : }
1602 : :
1603 : 0 : return trace_probe_event_call(&tu->tp);
1604 : : error:
1605 : 0 : free_trace_uprobe(tu);
1606 : 0 : return ERR_PTR(ret);
1607 : : }
1608 : :
1609 : 0 : void destroy_local_trace_uprobe(struct trace_event_call *event_call)
1610 : : {
1611 : 0 : struct trace_uprobe *tu;
1612 : :
1613 [ # # ]: 0 : tu = trace_uprobe_primary_from_call(event_call);
1614 : :
1615 : 0 : free_trace_uprobe(tu);
1616 : 0 : }
1617 : : #endif /* CONFIG_PERF_EVENTS */
1618 : :
1619 : : /* Make a trace interface for controling probe points */
1620 : 21 : static __init int init_uprobe_trace(void)
1621 : : {
1622 : 21 : struct dentry *d_tracer;
1623 : 21 : int ret;
1624 : :
1625 : 21 : ret = dyn_event_register(&trace_uprobe_ops);
1626 [ + - ]: 21 : if (ret)
1627 : : return ret;
1628 : :
1629 : 21 : d_tracer = tracing_init_dentry();
1630 [ + - ]: 21 : if (IS_ERR(d_tracer))
1631 : : return 0;
1632 : :
1633 : 21 : trace_create_file("uprobe_events", 0644, d_tracer,
1634 : : NULL, &uprobe_events_ops);
1635 : : /* Profile interface */
1636 : 21 : trace_create_file("uprobe_profile", 0444, d_tracer,
1637 : : NULL, &uprobe_profile_ops);
1638 : 21 : return 0;
1639 : : }
1640 : :
1641 : : fs_initcall(init_uprobe_trace);
|