@@ -33,12 +33,40 @@ static DEFINE_MUTEX(trampoline_mutex);
3333#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
3434static int bpf_trampoline_update (struct bpf_trampoline * tr , bool lock_direct_mutex );
3535
36+ #ifdef CONFIG_HAVE_SINGLE_FTRACE_DIRECT_OPS
37+ static struct bpf_trampoline * direct_ops_ip_lookup (struct ftrace_ops * ops , unsigned long ip )
38+ {
39+ struct hlist_head * head_ip ;
40+ struct bpf_trampoline * tr ;
41+
42+ mutex_lock (& trampoline_mutex );
43+ head_ip = & trampoline_ip_table [hash_64 (ip , TRAMPOLINE_HASH_BITS )];
44+ hlist_for_each_entry (tr , head_ip , hlist_ip ) {
45+ if (tr -> func .addr == (void * ) ip )
46+ goto out ;
47+ }
48+ tr = NULL ;
49+ out :
50+ mutex_unlock (& trampoline_mutex );
51+ return tr ;
52+ }
53+ #else
54+ static struct bpf_trampoline * direct_ops_ip_lookup (struct ftrace_ops * ops , unsigned long ip )
55+ {
56+ return ops -> private ;
57+ }
58+ #endif /* CONFIG_HAVE_SINGLE_FTRACE_DIRECT_OPS */
59+
3660static int bpf_tramp_ftrace_ops_func (struct ftrace_ops * ops , unsigned long ip ,
3761 enum ftrace_ops_cmd cmd )
3862{
39- struct bpf_trampoline * tr = ops -> private ;
63+ struct bpf_trampoline * tr ;
4064 int ret = 0 ;
4165
66+ tr = direct_ops_ip_lookup (ops , ip );
67+ if (!tr )
68+ return - EINVAL ;
69+
4270 if (cmd == FTRACE_OPS_CMD_ENABLE_SHARE_IPMODIFY_SELF ) {
4371 /* This is called inside register_ftrace_direct_multi(), so
4472 * tr->mutex is already locked.
@@ -137,6 +165,48 @@ void bpf_image_ksym_del(struct bpf_ksym *ksym)
137165 PAGE_SIZE , true, ksym -> name );
138166}
139167
168+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
169+ #ifdef CONFIG_HAVE_SINGLE_FTRACE_DIRECT_OPS
170+ struct ftrace_ops direct_ops = {
171+ .ops_func = bpf_tramp_ftrace_ops_func ,
172+ };
173+
174+ static int direct_ops_get (struct bpf_trampoline * tr )
175+ {
176+ tr -> fops = & direct_ops ;
177+ return 0 ;
178+ }
179+ static void direct_ops_clear (struct bpf_trampoline * tr ) { }
180+ static void direct_ops_free (struct bpf_trampoline * tr ) { }
181+ #else
182+ static int direct_ops_get (struct bpf_trampoline * tr )
183+ {
184+ tr -> fops = kzalloc (sizeof (struct ftrace_ops ), GFP_KERNEL );
185+ if (!tr -> fops )
186+ return -1 ;
187+ tr -> fops -> private = tr ;
188+ tr -> fops -> ops_func = bpf_tramp_ftrace_ops_func ;
189+ return 0 ;
190+ }
191+
192+ static void direct_ops_clear (struct bpf_trampoline * tr )
193+ {
194+ tr -> fops -> func = NULL ;
195+ tr -> fops -> trampoline = 0 ;
196+ }
197+
198+ static void direct_ops_free (struct bpf_trampoline * tr )
199+ {
200+ if (tr -> fops ) {
201+ ftrace_free_filter (tr -> fops );
202+ kfree (tr -> fops );
203+ }
204+ }
205+ #endif /* CONFIG_HAVE_SINGLE_FTRACE_DIRECT_OPS */
206+ #else
207+ static void direct_ops_free (struct bpf_trampoline * tr ) { }
208+ #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
209+
140210static struct bpf_trampoline * bpf_trampoline_lookup (u64 key , unsigned long ip )
141211{
142212 struct bpf_trampoline * tr ;
@@ -155,14 +225,11 @@ static struct bpf_trampoline *bpf_trampoline_lookup(u64 key, unsigned long ip)
155225 if (!tr )
156226 goto out ;
157227#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
158- tr -> fops = kzalloc (sizeof (struct ftrace_ops ), GFP_KERNEL );
159- if (!tr -> fops ) {
228+ if (direct_ops_get (tr )) {
160229 kfree (tr );
161230 tr = NULL ;
162231 goto out ;
163232 }
164- tr -> fops -> private = tr ;
165- tr -> fops -> ops_func = bpf_tramp_ftrace_ops_func ;
166233#endif
167234
168235 tr -> key = key ;
@@ -482,8 +549,7 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
482549 * trampoline again, and retry register.
483550 */
484551 /* reset fops->func and fops->trampoline for re-register */
485- tr -> fops -> func = NULL ;
486- tr -> fops -> trampoline = 0 ;
552+ direct_ops_clear (tr );
487553
488554 /* free im memory and reallocate later */
489555 bpf_tramp_image_free (im );
@@ -864,10 +930,7 @@ void bpf_trampoline_put(struct bpf_trampoline *tr)
864930 */
865931 hlist_del (& tr -> hlist_key );
866932 hlist_del (& tr -> hlist_ip );
867- if (tr -> fops ) {
868- ftrace_free_filter (tr -> fops );
869- kfree (tr -> fops );
870- }
933+ direct_ops_free (tr );
871934 kfree (tr );
872935out :
873936 mutex_unlock (& trampoline_mutex );
0 commit comments