1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * fprobe - Simple ftrace probe wrapper for function entry.
4 */
5 #define pr_fmt(fmt) "fprobe: " fmt
6
7 #include <linux/err.h>
8 #include <linux/fprobe.h>
9 #include <linux/kallsyms.h>
10 #include <linux/kprobes.h>
11 #include <linux/list.h>
12 #include <linux/mutex.h>
13 #include <linux/slab.h>
14 #include <linux/sort.h>
15
16 #include <asm/fprobe.h>
17
18 #include "trace.h"
19
20 #define FPROBE_IP_HASH_BITS 8
21 #define FPROBE_IP_TABLE_SIZE (1 << FPROBE_IP_HASH_BITS)
22
23 #define FPROBE_HASH_BITS 6
24 #define FPROBE_TABLE_SIZE (1 << FPROBE_HASH_BITS)
25
26 #define SIZE_IN_LONG(x) ((x + sizeof(long) - 1) >> (sizeof(long) == 8 ? 3 : 2))
27
28 /*
29 * fprobe_table: hold 'fprobe_hlist::hlist' for checking the fprobe still
30 * exists. The key is the address of fprobe instance.
31 * fprobe_ip_table: hold 'fprobe_hlist::array[*]' for searching the fprobe
32 * instance related to the funciton address. The key is the ftrace IP
33 * address.
34 *
35 * When unregistering the fprobe, fprobe_hlist::fp and fprobe_hlist::array[*].fp
36 * are set NULL and delete those from both hash tables (by hlist_del_rcu).
37 * After an RCU grace period, the fprobe_hlist itself will be released.
38 *
39 * fprobe_table and fprobe_ip_table can be accessed from either
40 * - Normal hlist traversal and RCU add/del under 'fprobe_mutex' is held.
41 * - RCU hlist traversal under disabling preempt
42 */
43 static struct hlist_head fprobe_table[FPROBE_TABLE_SIZE];
44 static struct hlist_head fprobe_ip_table[FPROBE_IP_TABLE_SIZE];
45 static DEFINE_MUTEX(fprobe_mutex);
46
47 /*
48 * Find first fprobe in the hlist. It will be iterated twice in the entry
49 * probe, once for correcting the total required size, the second time is
50 * calling back the user handlers.
51 * Thus the hlist in the fprobe_table must be sorted and new probe needs to
52 * be added *before* the first fprobe.
53 */
find_first_fprobe_node(unsigned long ip)54 static struct fprobe_hlist_node *find_first_fprobe_node(unsigned long ip)
55 {
56 struct fprobe_hlist_node *node;
57 struct hlist_head *head;
58
59 head = &fprobe_ip_table[hash_ptr((void *)ip, FPROBE_IP_HASH_BITS)];
60 hlist_for_each_entry_rcu(node, head, hlist,
61 lockdep_is_held(&fprobe_mutex)) {
62 if (node->addr == ip)
63 return node;
64 }
65 return NULL;
66 }
67 NOKPROBE_SYMBOL(find_first_fprobe_node);
68
69 /* Node insertion and deletion requires the fprobe_mutex */
insert_fprobe_node(struct fprobe_hlist_node * node)70 static void insert_fprobe_node(struct fprobe_hlist_node *node)
71 {
72 unsigned long ip = node->addr;
73 struct fprobe_hlist_node *next;
74 struct hlist_head *head;
75
76 lockdep_assert_held(&fprobe_mutex);
77
78 next = find_first_fprobe_node(ip);
79 if (next) {
80 hlist_add_before_rcu(&node->hlist, &next->hlist);
81 return;
82 }
83 head = &fprobe_ip_table[hash_ptr((void *)ip, FPROBE_IP_HASH_BITS)];
84 hlist_add_head_rcu(&node->hlist, head);
85 }
86
87 /* Return true if there are synonims */
delete_fprobe_node(struct fprobe_hlist_node * node)88 static bool delete_fprobe_node(struct fprobe_hlist_node *node)
89 {
90 lockdep_assert_held(&fprobe_mutex);
91
92 /* Avoid double deleting */
93 if (READ_ONCE(node->fp) != NULL) {
94 WRITE_ONCE(node->fp, NULL);
95 hlist_del_rcu(&node->hlist);
96 }
97 return !!find_first_fprobe_node(node->addr);
98 }
99
100 /* Check existence of the fprobe */
is_fprobe_still_exist(struct fprobe * fp)101 static bool is_fprobe_still_exist(struct fprobe *fp)
102 {
103 struct hlist_head *head;
104 struct fprobe_hlist *fph;
105
106 head = &fprobe_table[hash_ptr(fp, FPROBE_HASH_BITS)];
107 hlist_for_each_entry_rcu(fph, head, hlist,
108 lockdep_is_held(&fprobe_mutex)) {
109 if (fph->fp == fp)
110 return true;
111 }
112 return false;
113 }
114 NOKPROBE_SYMBOL(is_fprobe_still_exist);
115
add_fprobe_hash(struct fprobe * fp)116 static int add_fprobe_hash(struct fprobe *fp)
117 {
118 struct fprobe_hlist *fph = fp->hlist_array;
119 struct hlist_head *head;
120
121 lockdep_assert_held(&fprobe_mutex);
122
123 if (WARN_ON_ONCE(!fph))
124 return -EINVAL;
125
126 if (is_fprobe_still_exist(fp))
127 return -EEXIST;
128
129 head = &fprobe_table[hash_ptr(fp, FPROBE_HASH_BITS)];
130 hlist_add_head_rcu(&fp->hlist_array->hlist, head);
131 return 0;
132 }
133
del_fprobe_hash(struct fprobe * fp)134 static int del_fprobe_hash(struct fprobe *fp)
135 {
136 struct fprobe_hlist *fph = fp->hlist_array;
137
138 lockdep_assert_held(&fprobe_mutex);
139
140 if (WARN_ON_ONCE(!fph))
141 return -EINVAL;
142
143 if (!is_fprobe_still_exist(fp))
144 return -ENOENT;
145
146 fph->fp = NULL;
147 hlist_del_rcu(&fph->hlist);
148 return 0;
149 }
150
151 #ifdef ARCH_DEFINE_ENCODE_FPROBE_HEADER
152
153 /* The arch should encode fprobe_header info into one unsigned long */
154 #define FPROBE_HEADER_SIZE_IN_LONG 1
155
write_fprobe_header(unsigned long * stack,struct fprobe * fp,unsigned int size_words)156 static inline bool write_fprobe_header(unsigned long *stack,
157 struct fprobe *fp, unsigned int size_words)
158 {
159 if (WARN_ON_ONCE(size_words > MAX_FPROBE_DATA_SIZE_WORD ||
160 !arch_fprobe_header_encodable(fp)))
161 return false;
162
163 *stack = arch_encode_fprobe_header(fp, size_words);
164 return true;
165 }
166
read_fprobe_header(unsigned long * stack,struct fprobe ** fp,unsigned int * size_words)167 static inline void read_fprobe_header(unsigned long *stack,
168 struct fprobe **fp, unsigned int *size_words)
169 {
170 *fp = arch_decode_fprobe_header_fp(*stack);
171 *size_words = arch_decode_fprobe_header_size(*stack);
172 }
173
174 #else
175
176 /* Generic fprobe_header */
177 struct __fprobe_header {
178 struct fprobe *fp;
179 unsigned long size_words;
180 } __packed;
181
182 #define FPROBE_HEADER_SIZE_IN_LONG SIZE_IN_LONG(sizeof(struct __fprobe_header))
183
write_fprobe_header(unsigned long * stack,struct fprobe * fp,unsigned int size_words)184 static inline bool write_fprobe_header(unsigned long *stack,
185 struct fprobe *fp, unsigned int size_words)
186 {
187 struct __fprobe_header *fph = (struct __fprobe_header *)stack;
188
189 if (WARN_ON_ONCE(size_words > MAX_FPROBE_DATA_SIZE_WORD))
190 return false;
191
192 fph->fp = fp;
193 fph->size_words = size_words;
194 return true;
195 }
196
read_fprobe_header(unsigned long * stack,struct fprobe ** fp,unsigned int * size_words)197 static inline void read_fprobe_header(unsigned long *stack,
198 struct fprobe **fp, unsigned int *size_words)
199 {
200 struct __fprobe_header *fph = (struct __fprobe_header *)stack;
201
202 *fp = fph->fp;
203 *size_words = fph->size_words;
204 }
205
206 #endif
207
208 /*
209 * fprobe shadow stack management:
210 * Since fprobe shares a single fgraph_ops, it needs to share the stack entry
211 * among the probes on the same function exit. Note that a new probe can be
212 * registered before a target function is returning, we can not use the hash
213 * table to find the corresponding probes. Thus the probe address is stored on
214 * the shadow stack with its entry data size.
215 *
216 */
__fprobe_handler(unsigned long ip,unsigned long parent_ip,struct fprobe * fp,struct ftrace_regs * fregs,void * data)217 static inline int __fprobe_handler(unsigned long ip, unsigned long parent_ip,
218 struct fprobe *fp, struct ftrace_regs *fregs,
219 void *data)
220 {
221 if (!fp->entry_handler)
222 return 0;
223
224 return fp->entry_handler(fp, ip, parent_ip, fregs, data);
225 }
226
__fprobe_kprobe_handler(unsigned long ip,unsigned long parent_ip,struct fprobe * fp,struct ftrace_regs * fregs,void * data)227 static inline int __fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip,
228 struct fprobe *fp, struct ftrace_regs *fregs,
229 void *data)
230 {
231 int ret;
232 /*
233 * This user handler is shared with other kprobes and is not expected to be
234 * called recursively. So if any other kprobe handler is running, this will
235 * exit as kprobe does. See the section 'Share the callbacks with kprobes'
236 * in Documentation/trace/fprobe.rst for more information.
237 */
238 if (unlikely(kprobe_running())) {
239 fp->nmissed++;
240 return 0;
241 }
242
243 kprobe_busy_begin();
244 ret = __fprobe_handler(ip, parent_ip, fp, fregs, data);
245 kprobe_busy_end();
246 return ret;
247 }
248
fprobe_entry(struct ftrace_graph_ent * trace,struct fgraph_ops * gops,struct ftrace_regs * fregs)249 static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops,
250 struct ftrace_regs *fregs)
251 {
252 struct fprobe_hlist_node *node, *first;
253 unsigned long *fgraph_data = NULL;
254 unsigned long func = trace->func;
255 unsigned long ret_ip;
256 int reserved_words;
257 struct fprobe *fp;
258 int used, ret;
259
260 if (WARN_ON_ONCE(!fregs))
261 return 0;
262
263 first = node = find_first_fprobe_node(func);
264 if (unlikely(!first))
265 return 0;
266
267 reserved_words = 0;
268 hlist_for_each_entry_from_rcu(node, hlist) {
269 if (node->addr != func)
270 break;
271 fp = READ_ONCE(node->fp);
272 if (!fp || !fp->exit_handler)
273 continue;
274 /*
275 * Since fprobe can be enabled until the next loop, we ignore the
276 * fprobe's disabled flag in this loop.
277 */
278 reserved_words +=
279 FPROBE_HEADER_SIZE_IN_LONG + SIZE_IN_LONG(fp->entry_data_size);
280 }
281 node = first;
282 if (reserved_words) {
283 fgraph_data = fgraph_reserve_data(gops->idx, reserved_words * sizeof(long));
284 if (unlikely(!fgraph_data)) {
285 hlist_for_each_entry_from_rcu(node, hlist) {
286 if (node->addr != func)
287 break;
288 fp = READ_ONCE(node->fp);
289 if (fp && !fprobe_disabled(fp))
290 fp->nmissed++;
291 }
292 return 0;
293 }
294 }
295
296 /*
297 * TODO: recursion detection has been done in the fgraph. Thus we need
298 * to add a callback to increment missed counter.
299 */
300 ret_ip = ftrace_regs_get_return_address(fregs);
301 used = 0;
302 hlist_for_each_entry_from_rcu(node, hlist) {
303 int data_size;
304 void *data;
305
306 if (node->addr != func)
307 break;
308 fp = READ_ONCE(node->fp);
309 if (!fp || fprobe_disabled(fp))
310 continue;
311
312 data_size = fp->entry_data_size;
313 if (data_size && fp->exit_handler)
314 data = fgraph_data + used + FPROBE_HEADER_SIZE_IN_LONG;
315 else
316 data = NULL;
317
318 if (fprobe_shared_with_kprobes(fp))
319 ret = __fprobe_kprobe_handler(func, ret_ip, fp, fregs, data);
320 else
321 ret = __fprobe_handler(func, ret_ip, fp, fregs, data);
322
323 /* If entry_handler returns !0, nmissed is not counted but skips exit_handler. */
324 if (!ret && fp->exit_handler) {
325 int size_words = SIZE_IN_LONG(data_size);
326
327 if (write_fprobe_header(&fgraph_data[used], fp, size_words))
328 used += FPROBE_HEADER_SIZE_IN_LONG + size_words;
329 }
330 }
331 if (used < reserved_words)
332 memset(fgraph_data + used, 0, reserved_words - used);
333
334 /* If any exit_handler is set, data must be used. */
335 return used != 0;
336 }
337 NOKPROBE_SYMBOL(fprobe_entry);
338
fprobe_return(struct ftrace_graph_ret * trace,struct fgraph_ops * gops,struct ftrace_regs * fregs)339 static void fprobe_return(struct ftrace_graph_ret *trace,
340 struct fgraph_ops *gops,
341 struct ftrace_regs *fregs)
342 {
343 unsigned long *fgraph_data = NULL;
344 unsigned long ret_ip;
345 struct fprobe *fp;
346 int size, curr;
347 int size_words;
348
349 fgraph_data = (unsigned long *)fgraph_retrieve_data(gops->idx, &size);
350 if (WARN_ON_ONCE(!fgraph_data))
351 return;
352 size_words = SIZE_IN_LONG(size);
353 ret_ip = ftrace_regs_get_instruction_pointer(fregs);
354
355 preempt_disable();
356
357 curr = 0;
358 while (size_words > curr) {
359 read_fprobe_header(&fgraph_data[curr], &fp, &size);
360 if (!fp)
361 break;
362 curr += FPROBE_HEADER_SIZE_IN_LONG;
363 if (is_fprobe_still_exist(fp) && !fprobe_disabled(fp)) {
364 if (WARN_ON_ONCE(curr + size > size_words))
365 break;
366 fp->exit_handler(fp, trace->func, ret_ip, fregs,
367 size ? fgraph_data + curr : NULL);
368 }
369 curr += size;
370 }
371 preempt_enable();
372 }
373 NOKPROBE_SYMBOL(fprobe_return);
374
375 static struct fgraph_ops fprobe_graph_ops = {
376 .entryfunc = fprobe_entry,
377 .retfunc = fprobe_return,
378 };
379 static int fprobe_graph_active;
380
381 /* Add @addrs to the ftrace filter and register fgraph if needed. */
fprobe_graph_add_ips(unsigned long * addrs,int num)382 static int fprobe_graph_add_ips(unsigned long *addrs, int num)
383 {
384 int ret;
385
386 lockdep_assert_held(&fprobe_mutex);
387
388 ret = ftrace_set_filter_ips(&fprobe_graph_ops.ops, addrs, num, 0, 0);
389 if (ret)
390 return ret;
391
392 if (!fprobe_graph_active) {
393 ret = register_ftrace_graph(&fprobe_graph_ops);
394 if (WARN_ON_ONCE(ret)) {
395 ftrace_free_filter(&fprobe_graph_ops.ops);
396 return ret;
397 }
398 }
399 fprobe_graph_active++;
400 return 0;
401 }
402
403 /* Remove @addrs from the ftrace filter and unregister fgraph if possible. */
fprobe_graph_remove_ips(unsigned long * addrs,int num)404 static void fprobe_graph_remove_ips(unsigned long *addrs, int num)
405 {
406 lockdep_assert_held(&fprobe_mutex);
407
408 fprobe_graph_active--;
409 /* Q: should we unregister it ? */
410 if (!fprobe_graph_active)
411 unregister_ftrace_graph(&fprobe_graph_ops);
412
413 if (num)
414 ftrace_set_filter_ips(&fprobe_graph_ops.ops, addrs, num, 1, 0);
415 }
416
417 #ifdef CONFIG_MODULES
418
419 #define FPROBE_IPS_BATCH_INIT 8
420 /* instruction pointer address list */
421 struct fprobe_addr_list {
422 int index;
423 int size;
424 unsigned long *addrs;
425 };
426
fprobe_addr_list_add(struct fprobe_addr_list * alist,unsigned long addr)427 static int fprobe_addr_list_add(struct fprobe_addr_list *alist, unsigned long addr)
428 {
429 unsigned long *addrs;
430
431 if (alist->index >= alist->size)
432 return -ENOMEM;
433
434 alist->addrs[alist->index++] = addr;
435 if (alist->index < alist->size)
436 return 0;
437
438 /* Expand the address list */
439 addrs = kcalloc(alist->size * 2, sizeof(*addrs), GFP_KERNEL);
440 if (!addrs)
441 return -ENOMEM;
442
443 memcpy(addrs, alist->addrs, alist->size * sizeof(*addrs));
444 alist->size *= 2;
445 kfree(alist->addrs);
446 alist->addrs = addrs;
447
448 return 0;
449 }
450
fprobe_remove_node_in_module(struct module * mod,struct hlist_head * head,struct fprobe_addr_list * alist)451 static void fprobe_remove_node_in_module(struct module *mod, struct hlist_head *head,
452 struct fprobe_addr_list *alist)
453 {
454 struct fprobe_hlist_node *node;
455 int ret = 0;
456
457 hlist_for_each_entry_rcu(node, head, hlist) {
458 if (!within_module(node->addr, mod))
459 continue;
460 if (delete_fprobe_node(node))
461 continue;
462 /*
463 * If failed to update alist, just continue to update hlist.
464 * Therefore, at list user handler will not hit anymore.
465 */
466 if (!ret)
467 ret = fprobe_addr_list_add(alist, node->addr);
468 }
469 }
470
471 /* Handle module unloading to manage fprobe_ip_table. */
fprobe_module_callback(struct notifier_block * nb,unsigned long val,void * data)472 static int fprobe_module_callback(struct notifier_block *nb,
473 unsigned long val, void *data)
474 {
475 struct fprobe_addr_list alist = {.size = FPROBE_IPS_BATCH_INIT};
476 struct module *mod = data;
477 int i;
478
479 if (val != MODULE_STATE_GOING)
480 return NOTIFY_DONE;
481
482 alist.addrs = kcalloc(alist.size, sizeof(*alist.addrs), GFP_KERNEL);
483 /* If failed to alloc memory, we can not remove ips from hash. */
484 if (!alist.addrs)
485 return NOTIFY_DONE;
486
487 mutex_lock(&fprobe_mutex);
488 for (i = 0; i < FPROBE_IP_TABLE_SIZE; i++)
489 fprobe_remove_node_in_module(mod, &fprobe_ip_table[i], &alist);
490
491 if (alist.index < alist.size && alist.index > 0)
492 ftrace_set_filter_ips(&fprobe_graph_ops.ops,
493 alist.addrs, alist.index, 1, 0);
494 mutex_unlock(&fprobe_mutex);
495
496 kfree(alist.addrs);
497
498 return NOTIFY_DONE;
499 }
500
501 static struct notifier_block fprobe_module_nb = {
502 .notifier_call = fprobe_module_callback,
503 .priority = 0,
504 };
505
init_fprobe_module(void)506 static int __init init_fprobe_module(void)
507 {
508 return register_module_notifier(&fprobe_module_nb);
509 }
510 early_initcall(init_fprobe_module);
511 #endif
512
symbols_cmp(const void * a,const void * b)513 static int symbols_cmp(const void *a, const void *b)
514 {
515 const char **str_a = (const char **) a;
516 const char **str_b = (const char **) b;
517
518 return strcmp(*str_a, *str_b);
519 }
520
521 /* Convert ftrace location address from symbols */
get_ftrace_locations(const char ** syms,int num)522 static unsigned long *get_ftrace_locations(const char **syms, int num)
523 {
524 unsigned long *addrs;
525
526 /* Convert symbols to symbol address */
527 addrs = kcalloc(num, sizeof(*addrs), GFP_KERNEL);
528 if (!addrs)
529 return ERR_PTR(-ENOMEM);
530
531 /* ftrace_lookup_symbols expects sorted symbols */
532 sort(syms, num, sizeof(*syms), symbols_cmp, NULL);
533
534 if (!ftrace_lookup_symbols(syms, num, addrs))
535 return addrs;
536
537 kfree(addrs);
538 return ERR_PTR(-ENOENT);
539 }
540
541 struct filter_match_data {
542 const char *filter;
543 const char *notfilter;
544 size_t index;
545 size_t size;
546 unsigned long *addrs;
547 struct module **mods;
548 };
549
filter_match_callback(void * data,const char * name,unsigned long addr)550 static int filter_match_callback(void *data, const char *name, unsigned long addr)
551 {
552 struct filter_match_data *match = data;
553
554 if (!glob_match(match->filter, name) ||
555 (match->notfilter && glob_match(match->notfilter, name)))
556 return 0;
557
558 if (!ftrace_location(addr))
559 return 0;
560
561 if (match->addrs) {
562 struct module *mod = __module_text_address(addr);
563
564 if (mod && !try_module_get(mod))
565 return 0;
566
567 match->mods[match->index] = mod;
568 match->addrs[match->index] = addr;
569 }
570 match->index++;
571 return match->index == match->size;
572 }
573
574 /*
575 * Make IP list from the filter/no-filter glob patterns.
576 * Return the number of matched symbols, or errno.
577 * If @addrs == NULL, this just counts the number of matched symbols. If @addrs
578 * is passed with an array, we need to pass the an @mods array of the same size
579 * to increment the module refcount for each symbol.
580 * This means we also need to call `module_put` for each element of @mods after
581 * using the @addrs.
582 */
get_ips_from_filter(const char * filter,const char * notfilter,unsigned long * addrs,struct module ** mods,size_t size)583 static int get_ips_from_filter(const char *filter, const char *notfilter,
584 unsigned long *addrs, struct module **mods,
585 size_t size)
586 {
587 struct filter_match_data match = { .filter = filter, .notfilter = notfilter,
588 .index = 0, .size = size, .addrs = addrs, .mods = mods};
589 int ret;
590
591 if (addrs && !mods)
592 return -EINVAL;
593
594 ret = kallsyms_on_each_symbol(filter_match_callback, &match);
595 if (ret < 0)
596 return ret;
597 if (IS_ENABLED(CONFIG_MODULES)) {
598 ret = module_kallsyms_on_each_symbol(NULL, filter_match_callback, &match);
599 if (ret < 0)
600 return ret;
601 }
602
603 return match.index ?: -ENOENT;
604 }
605
fprobe_fail_cleanup(struct fprobe * fp)606 static void fprobe_fail_cleanup(struct fprobe *fp)
607 {
608 kfree(fp->hlist_array);
609 fp->hlist_array = NULL;
610 }
611
612 /* Initialize the fprobe data structure. */
fprobe_init(struct fprobe * fp,unsigned long * addrs,int num)613 static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num)
614 {
615 struct fprobe_hlist *hlist_array;
616 unsigned long addr;
617 int size, i;
618
619 if (!fp || !addrs || num <= 0)
620 return -EINVAL;
621
622 size = ALIGN(fp->entry_data_size, sizeof(long));
623 if (size > MAX_FPROBE_DATA_SIZE)
624 return -E2BIG;
625 fp->entry_data_size = size;
626
627 hlist_array = kzalloc(struct_size(hlist_array, array, num), GFP_KERNEL);
628 if (!hlist_array)
629 return -ENOMEM;
630
631 fp->nmissed = 0;
632
633 hlist_array->size = num;
634 fp->hlist_array = hlist_array;
635 hlist_array->fp = fp;
636 for (i = 0; i < num; i++) {
637 hlist_array->array[i].fp = fp;
638 addr = ftrace_location(addrs[i]);
639 if (!addr) {
640 fprobe_fail_cleanup(fp);
641 return -ENOENT;
642 }
643 hlist_array->array[i].addr = addr;
644 }
645 return 0;
646 }
647
648 #define FPROBE_IPS_MAX INT_MAX
649
650 /**
651 * register_fprobe() - Register fprobe to ftrace by pattern.
652 * @fp: A fprobe data structure to be registered.
653 * @filter: A wildcard pattern of probed symbols.
654 * @notfilter: A wildcard pattern of NOT probed symbols.
655 *
656 * Register @fp to ftrace for enabling the probe on the symbols matched to @filter.
657 * If @notfilter is not NULL, the symbols matched the @notfilter are not probed.
658 *
659 * Return 0 if @fp is registered successfully, -errno if not.
660 */
register_fprobe(struct fprobe * fp,const char * filter,const char * notfilter)661 int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter)
662 {
663 unsigned long *addrs __free(kfree) = NULL;
664 struct module **mods __free(kfree) = NULL;
665 int ret, num;
666
667 if (!fp || !filter)
668 return -EINVAL;
669
670 num = get_ips_from_filter(filter, notfilter, NULL, NULL, FPROBE_IPS_MAX);
671 if (num < 0)
672 return num;
673
674 addrs = kcalloc(num, sizeof(*addrs), GFP_KERNEL);
675 if (!addrs)
676 return -ENOMEM;
677
678 mods = kcalloc(num, sizeof(*mods), GFP_KERNEL);
679 if (!mods)
680 return -ENOMEM;
681
682 ret = get_ips_from_filter(filter, notfilter, addrs, mods, num);
683 if (ret < 0)
684 return ret;
685
686 ret = register_fprobe_ips(fp, addrs, ret);
687
688 for (int i = 0; i < num; i++) {
689 if (mods[i])
690 module_put(mods[i]);
691 }
692 return ret;
693 }
694 EXPORT_SYMBOL_GPL(register_fprobe);
695
696 /**
697 * register_fprobe_ips() - Register fprobe to ftrace by address.
698 * @fp: A fprobe data structure to be registered.
699 * @addrs: An array of target function address.
700 * @num: The number of entries of @addrs.
701 *
702 * Register @fp to ftrace for enabling the probe on the address given by @addrs.
703 * The @addrs must be the addresses of ftrace location address, which may be
704 * the symbol address + arch-dependent offset.
705 * If you unsure what this mean, please use other registration functions.
706 *
707 * Return 0 if @fp is registered successfully, -errno if not.
708 */
register_fprobe_ips(struct fprobe * fp,unsigned long * addrs,int num)709 int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num)
710 {
711 struct fprobe_hlist *hlist_array;
712 int ret, i;
713
714 ret = fprobe_init(fp, addrs, num);
715 if (ret)
716 return ret;
717
718 mutex_lock(&fprobe_mutex);
719
720 hlist_array = fp->hlist_array;
721 ret = fprobe_graph_add_ips(addrs, num);
722 if (!ret) {
723 add_fprobe_hash(fp);
724 for (i = 0; i < hlist_array->size; i++)
725 insert_fprobe_node(&hlist_array->array[i]);
726 }
727 mutex_unlock(&fprobe_mutex);
728
729 if (ret)
730 fprobe_fail_cleanup(fp);
731
732 return ret;
733 }
734 EXPORT_SYMBOL_GPL(register_fprobe_ips);
735
736 /**
737 * register_fprobe_syms() - Register fprobe to ftrace by symbols.
738 * @fp: A fprobe data structure to be registered.
739 * @syms: An array of target symbols.
740 * @num: The number of entries of @syms.
741 *
742 * Register @fp to the symbols given by @syms array. This will be useful if
743 * you are sure the symbols exist in the kernel.
744 *
745 * Return 0 if @fp is registered successfully, -errno if not.
746 */
register_fprobe_syms(struct fprobe * fp,const char ** syms,int num)747 int register_fprobe_syms(struct fprobe *fp, const char **syms, int num)
748 {
749 unsigned long *addrs;
750 int ret;
751
752 if (!fp || !syms || num <= 0)
753 return -EINVAL;
754
755 addrs = get_ftrace_locations(syms, num);
756 if (IS_ERR(addrs))
757 return PTR_ERR(addrs);
758
759 ret = register_fprobe_ips(fp, addrs, num);
760
761 kfree(addrs);
762
763 return ret;
764 }
765 EXPORT_SYMBOL_GPL(register_fprobe_syms);
766
fprobe_is_registered(struct fprobe * fp)767 bool fprobe_is_registered(struct fprobe *fp)
768 {
769 if (!fp || !fp->hlist_array)
770 return false;
771 return true;
772 }
773
774 /**
775 * unregister_fprobe() - Unregister fprobe.
776 * @fp: A fprobe data structure to be unregistered.
777 *
778 * Unregister fprobe (and remove ftrace hooks from the function entries).
779 *
780 * Return 0 if @fp is unregistered successfully, -errno if not.
781 */
unregister_fprobe(struct fprobe * fp)782 int unregister_fprobe(struct fprobe *fp)
783 {
784 struct fprobe_hlist *hlist_array;
785 unsigned long *addrs = NULL;
786 int ret = 0, i, count;
787
788 mutex_lock(&fprobe_mutex);
789 if (!fp || !is_fprobe_still_exist(fp)) {
790 ret = -EINVAL;
791 goto out;
792 }
793
794 hlist_array = fp->hlist_array;
795 addrs = kcalloc(hlist_array->size, sizeof(unsigned long), GFP_KERNEL);
796 if (!addrs) {
797 ret = -ENOMEM; /* TODO: Fallback to one-by-one loop */
798 goto out;
799 }
800
801 /* Remove non-synonim ips from table and hash */
802 count = 0;
803 for (i = 0; i < hlist_array->size; i++) {
804 if (!delete_fprobe_node(&hlist_array->array[i]))
805 addrs[count++] = hlist_array->array[i].addr;
806 }
807 del_fprobe_hash(fp);
808
809 fprobe_graph_remove_ips(addrs, count);
810
811 kfree_rcu(hlist_array, rcu);
812 fp->hlist_array = NULL;
813
814 out:
815 mutex_unlock(&fprobe_mutex);
816
817 kfree(addrs);
818 return ret;
819 }
820 EXPORT_SYMBOL_GPL(unregister_fprobe);
821