Skip to content

Commit 887d458

Browse files
liu-song-6Kernel Patches Daemon
authored andcommitted
ftrace: Fix BPF fexit with livepatch
When livepatch is attached to the same function as bpf trampoline with a fexit program, bpf trampoline code calls register_ftrace_direct() twice. The first time will fail with -EAGAIN, and the second time it will succeed. This requires register_ftrace_direct() to unregister the address on the first attempt. Otherwise, the bpf trampoline cannot attach. Here is an easy way to reproduce this issue: insmod samples/livepatch/livepatch-sample.ko bpftrace -e 'fexit:cmdline_proc_show {}' ERROR: Unable to attach probe: fexit:vmlinux:cmdline_proc_show... Fix this by cleaning up the hash when register_ftrace_function_nolock hits errors. Also, move the code that resets ops->func and ops->trampoline to the error path of register_ftrace_direct(); and add a helper function reset_direct() in register_ftrace_direct() and unregister_ftrace_direct(). Fixes: d05cb47 ("ftrace: Fix modification of direct_function hash while in use") Cc: [email protected] # v6.6+ Reported-by: Andrey Grodzovsky <[email protected]> Closes: https://lore.kernel.org/live-patching/[email protected]/ Cc: Steven Rostedt (Google) <[email protected]> Cc: Masami Hiramatsu (Google) <[email protected]> Acked-and-tested-by: Andrey Grodzovsky <[email protected]> Signed-off-by: Song Liu <[email protected]> Reviewed-by: Jiri Olsa <[email protected]>
1 parent 7c8a49d commit 887d458

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

kernel/bpf/trampoline.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -479,11 +479,6 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
479479
* BPF_TRAMP_F_SHARE_IPMODIFY is set, we can generate the
480480
* trampoline again, and retry register.
481481
*/
482-
/* reset fops->func and fops->trampoline for re-register */
483-
tr->fops->func = NULL;
484-
tr->fops->trampoline = 0;
485-
486-
/* free im memory and reallocate later */
487482
bpf_tramp_image_free(im);
488483
goto again;
489484
}

kernel/trace/ftrace.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5953,6 +5953,17 @@ static void register_ftrace_direct_cb(struct rcu_head *rhp)
59535953
free_ftrace_hash(fhp);
59545954
}
59555955

5956+
static void reset_direct(struct ftrace_ops *ops, unsigned long addr)
5957+
{
5958+
struct ftrace_hash *hash = ops->func_hash->filter_hash;
5959+
5960+
remove_direct_functions_hash(hash, addr);
5961+
5962+
/* cleanup for possible another register call */
5963+
ops->func = NULL;
5964+
ops->trampoline = 0;
5965+
}
5966+
59565967
/**
59575968
* register_ftrace_direct - Call a custom trampoline directly
59585969
* for multiple functions registered in @ops
@@ -6048,6 +6059,8 @@ int register_ftrace_direct(struct ftrace_ops *ops, unsigned long addr)
60486059
ops->direct_call = addr;
60496060

60506061
err = register_ftrace_function_nolock(ops);
6062+
if (err)
6063+
reset_direct(ops, addr);
60516064

60526065
out_unlock:
60536066
mutex_unlock(&direct_mutex);
@@ -6080,7 +6093,6 @@ EXPORT_SYMBOL_GPL(register_ftrace_direct);
60806093
int unregister_ftrace_direct(struct ftrace_ops *ops, unsigned long addr,
60816094
bool free_filters)
60826095
{
6083-
struct ftrace_hash *hash = ops->func_hash->filter_hash;
60846096
int err;
60856097

60866098
if (check_direct_multi(ops))
@@ -6090,13 +6102,9 @@ int unregister_ftrace_direct(struct ftrace_ops *ops, unsigned long addr,
60906102

60916103
mutex_lock(&direct_mutex);
60926104
err = unregister_ftrace_function(ops);
6093-
remove_direct_functions_hash(hash, addr);
6105+
reset_direct(ops, addr);
60946106
mutex_unlock(&direct_mutex);
60956107

6096-
/* cleanup for possible another register call */
6097-
ops->func = NULL;
6098-
ops->trampoline = 0;
6099-
61006108
if (free_filters)
61016109
ftrace_free_filter(ops);
61026110
return err;

0 commit comments

Comments
 (0)