1313#include <linux/static_call.h>
1414#include <linux/bpf_verifier.h>
1515#include <linux/bpf_lsm.h>
16+ #include <linux/delay.h>
1617
1718/* dummy _ops. The verifier will operate on target program's ops. */
1819const struct bpf_verifier_ops bpf_extension_verifier_ops = {
@@ -29,6 +30,81 @@ static struct hlist_head trampoline_table[TRAMPOLINE_TABLE_SIZE];
2930/* serializes access to trampoline_table */
3031static DEFINE_MUTEX (trampoline_mutex );
3132
33+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
34+ static int bpf_trampoline_update (struct bpf_trampoline * tr , bool lock_direct_mutex );
35+
36+ static int bpf_tramp_ftrace_ops_func (struct ftrace_ops * ops , enum ftrace_ops_cmd cmd )
37+ {
38+ struct bpf_trampoline * tr = ops -> private ;
39+ int ret = 0 ;
40+
41+ if (cmd == FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF ) {
42+ /* This is called inside register_ftrace_direct_multi(), so
43+ * tr->mutex is already locked.
44+ */
45+ lockdep_assert_held_once (& tr -> mutex );
46+
47+ /* Instead of updating the trampoline here, we propagate
48+ * -EAGAIN to register_ftrace_direct_multi(). Then we can
49+ * retry register_ftrace_direct_multi() after updating the
50+ * trampoline.
51+ */
52+ if ((tr -> flags & BPF_TRAMP_F_CALL_ORIG ) &&
53+ !(tr -> flags & BPF_TRAMP_F_ORIG_STACK )) {
54+ if (WARN_ON_ONCE (tr -> flags & BPF_TRAMP_F_SHARE_IPMODIFY ))
55+ return - EBUSY ;
56+
57+ tr -> flags |= BPF_TRAMP_F_SHARE_IPMODIFY ;
58+ return - EAGAIN ;
59+ }
60+
61+ return 0 ;
62+ }
63+
64+ /* The normal locking order is
65+ * tr->mutex => direct_mutex (ftrace.c) => ftrace_lock (ftrace.c)
66+ *
67+ * The following two commands are called from
68+ *
69+ * prepare_direct_functions_for_ipmodify
70+ * cleanup_direct_functions_after_ipmodify
71+ *
72+ * In both cases, direct_mutex is already locked. Use
73+ * mutex_trylock(&tr->mutex) to avoid deadlock in race condition
74+ * (something else is making changes to this same trampoline).
75+ */
76+ if (!mutex_trylock (& tr -> mutex )) {
77+ /* sleep 1 ms to make sure whatever holding tr->mutex makes
78+ * some progress.
79+ */
80+ msleep (1 );
81+ return - EAGAIN ;
82+ }
83+
84+ switch (cmd ) {
85+ case FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_PEER :
86+ tr -> flags |= BPF_TRAMP_F_SHARE_IPMODIFY ;
87+
88+ if ((tr -> flags & BPF_TRAMP_F_CALL_ORIG ) &&
89+ !(tr -> flags & BPF_TRAMP_F_ORIG_STACK ))
90+ ret = bpf_trampoline_update (tr , false /* lock_direct_mutex */ );
91+ break ;
92+ case FTRACE_OPS_CMD_DISABLE_SHARE_IPMODIFY_PEER :
93+ tr -> flags &= ~BPF_TRAMP_F_SHARE_IPMODIFY ;
94+
95+ if (tr -> flags & BPF_TRAMP_F_ORIG_STACK )
96+ ret = bpf_trampoline_update (tr , false /* lock_direct_mutex */ );
97+ break ;
98+ default :
99+ ret = - EINVAL ;
100+ break ;
101+ };
102+
103+ mutex_unlock (& tr -> mutex );
104+ return ret ;
105+ }
106+ #endif
107+
32108bool bpf_prog_has_trampoline (const struct bpf_prog * prog )
33109{
34110 enum bpf_attach_type eatype = prog -> expected_attach_type ;
@@ -89,6 +165,16 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key)
89165 tr = kzalloc (sizeof (* tr ), GFP_KERNEL );
90166 if (!tr )
91167 goto out ;
168+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
169+ tr -> fops = kzalloc (sizeof (struct ftrace_ops ), GFP_KERNEL );
170+ if (!tr -> fops ) {
171+ kfree (tr );
172+ tr = NULL ;
173+ goto out ;
174+ }
175+ tr -> fops -> private = tr ;
176+ tr -> fops -> ops_func = bpf_tramp_ftrace_ops_func ;
177+ #endif
92178
93179 tr -> key = key ;
94180 INIT_HLIST_NODE (& tr -> hlist );
@@ -128,7 +214,7 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
128214 int ret ;
129215
130216 if (tr -> func .ftrace_managed )
131- ret = unregister_ftrace_direct (( long ) ip , (long )old_addr );
217+ ret = unregister_ftrace_direct_multi ( tr -> fops , (long )old_addr );
132218 else
133219 ret = bpf_arch_text_poke (ip , BPF_MOD_CALL , old_addr , NULL );
134220
@@ -137,15 +223,20 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
137223 return ret ;
138224}
139225
140- static int modify_fentry (struct bpf_trampoline * tr , void * old_addr , void * new_addr )
226+ static int modify_fentry (struct bpf_trampoline * tr , void * old_addr , void * new_addr ,
227+ bool lock_direct_mutex )
141228{
142229 void * ip = tr -> func .addr ;
143230 int ret ;
144231
145- if (tr -> func .ftrace_managed )
146- ret = modify_ftrace_direct ((long )ip , (long )old_addr , (long )new_addr );
147- else
232+ if (tr -> func .ftrace_managed ) {
233+ if (lock_direct_mutex )
234+ ret = modify_ftrace_direct_multi (tr -> fops , (long )new_addr );
235+ else
236+ ret = modify_ftrace_direct_multi_nolock (tr -> fops , (long )new_addr );
237+ } else {
148238 ret = bpf_arch_text_poke (ip , BPF_MOD_CALL , old_addr , new_addr );
239+ }
149240 return ret ;
150241}
151242
@@ -163,10 +254,12 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
163254 if (bpf_trampoline_module_get (tr ))
164255 return - ENOENT ;
165256
166- if (tr -> func .ftrace_managed )
167- ret = register_ftrace_direct ((long )ip , (long )new_addr );
168- else
257+ if (tr -> func .ftrace_managed ) {
258+ ftrace_set_filter_ip (tr -> fops , (unsigned long )ip , 0 , 0 );
259+ ret = register_ftrace_direct_multi (tr -> fops , (long )new_addr );
260+ } else {
169261 ret = bpf_arch_text_poke (ip , BPF_MOD_CALL , NULL , new_addr );
262+ }
170263
171264 if (ret )
172265 bpf_trampoline_module_put (tr );
@@ -332,11 +425,11 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, u32 idx)
332425 return ERR_PTR (err );
333426}
334427
335- static int bpf_trampoline_update (struct bpf_trampoline * tr )
428+ static int bpf_trampoline_update (struct bpf_trampoline * tr , bool lock_direct_mutex )
336429{
337430 struct bpf_tramp_image * im ;
338431 struct bpf_tramp_links * tlinks ;
339- u32 flags = BPF_TRAMP_F_RESTORE_REGS ;
432+ u32 orig_flags = tr -> flags ;
340433 bool ip_arg = false;
341434 int err , total ;
342435
@@ -358,18 +451,31 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr)
358451 goto out ;
359452 }
360453
454+ /* clear all bits except SHARE_IPMODIFY */
455+ tr -> flags &= BPF_TRAMP_F_SHARE_IPMODIFY ;
456+
361457 if (tlinks [BPF_TRAMP_FEXIT ].nr_links ||
362- tlinks [BPF_TRAMP_MODIFY_RETURN ].nr_links )
458+ tlinks [BPF_TRAMP_MODIFY_RETURN ].nr_links ) {
363459 /* NOTE: BPF_TRAMP_F_RESTORE_REGS and BPF_TRAMP_F_SKIP_FRAME
364460 * should not be set together.
365461 */
366- flags = BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_SKIP_FRAME ;
462+ tr -> flags |= BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_SKIP_FRAME ;
463+ } else {
464+ tr -> flags |= BPF_TRAMP_F_RESTORE_REGS ;
465+ }
367466
368467 if (ip_arg )
369- flags |= BPF_TRAMP_F_IP_ARG ;
468+ tr -> flags |= BPF_TRAMP_F_IP_ARG ;
469+
470+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
471+ again :
472+ if ((tr -> flags & BPF_TRAMP_F_SHARE_IPMODIFY ) &&
473+ (tr -> flags & BPF_TRAMP_F_CALL_ORIG ))
474+ tr -> flags |= BPF_TRAMP_F_ORIG_STACK ;
475+ #endif
370476
371477 err = arch_prepare_bpf_trampoline (im , im -> image , im -> image + PAGE_SIZE ,
372- & tr -> func .model , flags , tlinks ,
478+ & tr -> func .model , tr -> flags , tlinks ,
373479 tr -> func .addr );
374480 if (err < 0 )
375481 goto out ;
@@ -378,17 +484,34 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr)
378484 WARN_ON (!tr -> cur_image && tr -> selector );
379485 if (tr -> cur_image )
380486 /* progs already running at this address */
381- err = modify_fentry (tr , tr -> cur_image -> image , im -> image );
487+ err = modify_fentry (tr , tr -> cur_image -> image , im -> image , lock_direct_mutex );
382488 else
383489 /* first time registering */
384490 err = register_fentry (tr , im -> image );
491+
492+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
493+ if (err == - EAGAIN ) {
494+ /* -EAGAIN from bpf_tramp_ftrace_ops_func. Now
495+ * BPF_TRAMP_F_SHARE_IPMODIFY is set, we can generate the
496+ * trampoline again, and retry register.
497+ */
498+ /* reset fops->func and fops->trampoline for re-register */
499+ tr -> fops -> func = NULL ;
500+ tr -> fops -> trampoline = 0 ;
501+ goto again ;
502+ }
503+ #endif
385504 if (err )
386505 goto out ;
506+
387507 if (tr -> cur_image )
388508 bpf_tramp_image_put (tr -> cur_image );
389509 tr -> cur_image = im ;
390510 tr -> selector ++ ;
391511out :
512+ /* If any error happens, restore previous flags */
513+ if (err )
514+ tr -> flags = orig_flags ;
392515 kfree (tlinks );
393516 return err ;
394517}
@@ -454,7 +577,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link, struct bpf_tr
454577
455578 hlist_add_head (& link -> tramp_hlist , & tr -> progs_hlist [kind ]);
456579 tr -> progs_cnt [kind ]++ ;
457- err = bpf_trampoline_update (tr );
580+ err = bpf_trampoline_update (tr , true /* lock_direct_mutex */ );
458581 if (err ) {
459582 hlist_del_init (& link -> tramp_hlist );
460583 tr -> progs_cnt [kind ]-- ;
@@ -487,7 +610,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, struct bpf_
487610 }
488611 hlist_del_init (& link -> tramp_hlist );
489612 tr -> progs_cnt [kind ]-- ;
490- return bpf_trampoline_update (tr );
613+ return bpf_trampoline_update (tr , true /* lock_direct_mutex */ );
491614}
492615
493616/* bpf_trampoline_unlink_prog() should never fail. */
@@ -715,6 +838,7 @@ void bpf_trampoline_put(struct bpf_trampoline *tr)
715838 * multiple rcu callbacks.
716839 */
717840 hlist_del (& tr -> hlist );
841+ kfree (tr -> fops );
718842 kfree (tr );
719843out :
720844 mutex_unlock (& trampoline_mutex );
0 commit comments