1 // SPDX-License-Identifier: GPL-2.0
3 * fprobe - Simple ftrace probe wrapper for function entry.
5 #define pr_fmt(fmt) "fprobe: " fmt
8 #include <linux/fprobe.h>
9 #include <linux/kallsyms.h>
10 #include <linux/kprobes.h>
11 #include <linux/rethook.h>
12 #include <linux/slab.h>
13 #include <linux/sort.h>
17 struct fprobe_rethook_node
{
18 struct rethook_node node
;
19 unsigned long entry_ip
;
20 unsigned long entry_parent_ip
;
24 static inline void __fprobe_handler(unsigned long ip
, unsigned long parent_ip
,
25 struct ftrace_ops
*ops
, struct ftrace_regs
*fregs
)
27 struct fprobe_rethook_node
*fpr
;
28 struct rethook_node
*rh
= NULL
;
30 void *entry_data
= NULL
;
33 fp
= container_of(ops
, struct fprobe
, ops
);
35 if (fp
->exit_handler
) {
36 rh
= rethook_try_get(fp
->rethook
);
41 fpr
= container_of(rh
, struct fprobe_rethook_node
, node
);
43 fpr
->entry_parent_ip
= parent_ip
;
44 if (fp
->entry_data_size
)
45 entry_data
= fpr
->data
;
48 if (fp
->entry_handler
)
49 ret
= fp
->entry_handler(fp
, ip
, parent_ip
, ftrace_get_regs(fregs
), entry_data
);
51 /* If entry_handler returns !0, nmissed is not counted. */
56 rethook_hook(rh
, ftrace_get_regs(fregs
), true);
60 static void fprobe_handler(unsigned long ip
, unsigned long parent_ip
,
61 struct ftrace_ops
*ops
, struct ftrace_regs
*fregs
)
66 fp
= container_of(ops
, struct fprobe
, ops
);
67 if (fprobe_disabled(fp
))
70 /* recursion detection has to go before any traceable function and
71 * all functions before this point should be marked as notrace
73 bit
= ftrace_test_recursion_trylock(ip
, parent_ip
);
78 __fprobe_handler(ip
, parent_ip
, ops
, fregs
);
79 ftrace_test_recursion_unlock(bit
);
82 NOKPROBE_SYMBOL(fprobe_handler
);
84 static void fprobe_kprobe_handler(unsigned long ip
, unsigned long parent_ip
,
85 struct ftrace_ops
*ops
, struct ftrace_regs
*fregs
)
90 fp
= container_of(ops
, struct fprobe
, ops
);
91 if (fprobe_disabled(fp
))
94 /* recursion detection has to go before any traceable function and
95 * all functions called before this point should be marked as notrace
97 bit
= ftrace_test_recursion_trylock(ip
, parent_ip
);
104 * This user handler is shared with other kprobes and is not expected to be
105 * called recursively. So if any other kprobe handler is running, this will
106 * exit as kprobe does. See the section 'Share the callbacks with kprobes'
107 * in Documentation/trace/fprobe.rst for more information.
109 if (unlikely(kprobe_running())) {
111 goto recursion_unlock
;
115 __fprobe_handler(ip
, parent_ip
, ops
, fregs
);
119 ftrace_test_recursion_unlock(bit
);
122 static void fprobe_exit_handler(struct rethook_node
*rh
, void *data
,
123 unsigned long ret_ip
, struct pt_regs
*regs
)
125 struct fprobe
*fp
= (struct fprobe
*)data
;
126 struct fprobe_rethook_node
*fpr
;
129 if (!fp
|| fprobe_disabled(fp
))
132 fpr
= container_of(rh
, struct fprobe_rethook_node
, node
);
135 * we need to assure no calls to traceable functions in-between the
136 * end of fprobe_handler and the beginning of fprobe_exit_handler.
138 bit
= ftrace_test_recursion_trylock(fpr
->entry_ip
, fpr
->entry_parent_ip
);
144 fp
->exit_handler(fp
, fpr
->entry_ip
, ret_ip
, regs
,
145 fp
->entry_data_size
? (void *)fpr
->data
: NULL
);
146 ftrace_test_recursion_unlock(bit
);
148 NOKPROBE_SYMBOL(fprobe_exit_handler
);
150 static int symbols_cmp(const void *a
, const void *b
)
152 const char **str_a
= (const char **) a
;
153 const char **str_b
= (const char **) b
;
155 return strcmp(*str_a
, *str_b
);
158 /* Convert ftrace location address from symbols */
159 static unsigned long *get_ftrace_locations(const char **syms
, int num
)
161 unsigned long *addrs
;
163 /* Convert symbols to symbol address */
164 addrs
= kcalloc(num
, sizeof(*addrs
), GFP_KERNEL
);
166 return ERR_PTR(-ENOMEM
);
168 /* ftrace_lookup_symbols expects sorted symbols */
169 sort(syms
, num
, sizeof(*syms
), symbols_cmp
, NULL
);
171 if (!ftrace_lookup_symbols(syms
, num
, addrs
))
175 return ERR_PTR(-ENOENT
);
178 static void fprobe_init(struct fprobe
*fp
)
181 if (fprobe_shared_with_kprobes(fp
))
182 fp
->ops
.func
= fprobe_kprobe_handler
;
184 fp
->ops
.func
= fprobe_handler
;
185 fp
->ops
.flags
|= FTRACE_OPS_FL_SAVE_REGS
;
188 static int fprobe_init_rethook(struct fprobe
*fp
, int num
)
192 if (!fp
->exit_handler
) {
197 /* Initialize rethook if needed */
198 if (fp
->nr_maxactive
)
199 num
= fp
->nr_maxactive
;
201 num
*= num_possible_cpus() * 2;
205 size
= sizeof(struct fprobe_rethook_node
) + fp
->entry_data_size
;
207 /* Initialize rethook */
208 fp
->rethook
= rethook_alloc((void *)fp
, fprobe_exit_handler
, size
, num
);
209 if (IS_ERR(fp
->rethook
))
210 return PTR_ERR(fp
->rethook
);
215 static void fprobe_fail_cleanup(struct fprobe
*fp
)
217 if (!IS_ERR_OR_NULL(fp
->rethook
)) {
218 /* Don't need to cleanup rethook->handler because this is not used. */
219 rethook_free(fp
->rethook
);
222 ftrace_free_filter(&fp
->ops
);
226 * register_fprobe() - Register fprobe to ftrace by pattern.
227 * @fp: A fprobe data structure to be registered.
228 * @filter: A wildcard pattern of probed symbols.
229 * @notfilter: A wildcard pattern of NOT probed symbols.
231 * Register @fp to ftrace for enabling the probe on the symbols matched to @filter.
232 * If @notfilter is not NULL, the symbols matched the @notfilter are not probed.
234 * Return 0 if @fp is registered successfully, -errno if not.
236 int register_fprobe(struct fprobe
*fp
, const char *filter
, const char *notfilter
)
238 struct ftrace_hash
*hash
;
247 len
= strlen(filter
);
248 str
= kstrdup(filter
, GFP_KERNEL
);
249 ret
= ftrace_set_filter(&fp
->ops
, str
, len
, 0);
255 len
= strlen(notfilter
);
256 str
= kstrdup(notfilter
, GFP_KERNEL
);
257 ret
= ftrace_set_notrace(&fp
->ops
, str
, len
, 0);
264 * correctly calculate the total number of filtered symbols
265 * from both filter and notfilter.
267 hash
= rcu_access_pointer(fp
->ops
.local_hash
.filter_hash
);
268 if (WARN_ON_ONCE(!hash
))
271 ret
= fprobe_init_rethook(fp
, (int)hash
->count
);
273 ret
= register_ftrace_function(&fp
->ops
);
277 fprobe_fail_cleanup(fp
);
280 EXPORT_SYMBOL_GPL(register_fprobe
);
283 * register_fprobe_ips() - Register fprobe to ftrace by address.
284 * @fp: A fprobe data structure to be registered.
285 * @addrs: An array of target ftrace location addresses.
286 * @num: The number of entries of @addrs.
288 * Register @fp to ftrace for enabling the probe on the address given by @addrs.
289 * The @addrs must be the addresses of ftrace location address, which may be
290 * the symbol address + arch-dependent offset.
291 * If you unsure what this mean, please use other registration functions.
293 * Return 0 if @fp is registered successfully, -errno if not.
295 int register_fprobe_ips(struct fprobe
*fp
, unsigned long *addrs
, int num
)
299 if (!fp
|| !addrs
|| num
<= 0)
304 ret
= ftrace_set_filter_ips(&fp
->ops
, addrs
, num
, 0, 0);
308 ret
= fprobe_init_rethook(fp
, num
);
310 ret
= register_ftrace_function(&fp
->ops
);
313 fprobe_fail_cleanup(fp
);
316 EXPORT_SYMBOL_GPL(register_fprobe_ips
);
319 * register_fprobe_syms() - Register fprobe to ftrace by symbols.
320 * @fp: A fprobe data structure to be registered.
321 * @syms: An array of target symbols.
322 * @num: The number of entries of @syms.
324 * Register @fp to the symbols given by @syms array. This will be useful if
325 * you are sure the symbols exist in the kernel.
327 * Return 0 if @fp is registered successfully, -errno if not.
329 int register_fprobe_syms(struct fprobe
*fp
, const char **syms
, int num
)
331 unsigned long *addrs
;
334 if (!fp
|| !syms
|| num
<= 0)
337 addrs
= get_ftrace_locations(syms
, num
);
339 return PTR_ERR(addrs
);
341 ret
= register_fprobe_ips(fp
, addrs
, num
);
347 EXPORT_SYMBOL_GPL(register_fprobe_syms
);
349 bool fprobe_is_registered(struct fprobe
*fp
)
351 if (!fp
|| (fp
->ops
.saved_func
!= fprobe_handler
&&
352 fp
->ops
.saved_func
!= fprobe_kprobe_handler
))
358 * unregister_fprobe() - Unregister fprobe from ftrace
359 * @fp: A fprobe data structure to be unregistered.
361 * Unregister fprobe (and remove ftrace hooks from the function entries).
363 * Return 0 if @fp is unregistered successfully, -errno if not.
365 int unregister_fprobe(struct fprobe
*fp
)
369 if (!fprobe_is_registered(fp
))
372 if (!IS_ERR_OR_NULL(fp
->rethook
))
373 rethook_stop(fp
->rethook
);
375 ret
= unregister_ftrace_function(&fp
->ops
);
379 if (!IS_ERR_OR_NULL(fp
->rethook
))
380 rethook_free(fp
->rethook
);
382 ftrace_free_filter(&fp
->ops
);
386 EXPORT_SYMBOL_GPL(unregister_fprobe
);