On Mon, Oct 12, 2026 at 04:05:45PM +0200, Andrea Parri wrote:
> diff --git a/kernel/livepatch/patch.c b/kernel/livepatch/patch.c
> index 3f54a017bbf69..d01ec7a6256ab 100644
> --- a/kernel/livepatch/patch.c
> +++ b/kernel/livepatch/patch.c
> @@ -22,15 +22,19 @@
>
> static LIST_HEAD(klp_ops);
>
> +/*
> + * Caller must hold klp_mutex or rcu_read_lock(): klp_check_stack_func()
> walks
> + * klp_ops from the scheduler without klp_mutex.
> + */
> struct klp_ops *klp_find_ops(void *old_func)
> {
> struct klp_ops *ops;
> struct klp_func *func;
>
> - list_for_each_entry(ops, &klp_ops, node) {
> - func = list_first_entry(&ops->func_stack, struct klp_func,
> - stack_node);
> - if (func->old_func == old_func)
> + list_for_each_entry_rcu(ops, &klp_ops, node,
> lockdep_is_held(&klp_mutex)) {
> + func = list_first_or_null_rcu(&ops->func_stack, struct klp_func,
> + stack_node);
> + if (func && READ_ONCE(func->old_func) == old_func)
> return ops;
> }
>
> diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c
> index 2351a19ac2a9e..e9aa16baf1743 100644
> --- a/kernel/livepatch/transition.c
> +++ b/kernel/livepatch/transition.c
> @@ -8,6 +8,7 @@
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>
> #include <linux/cpu.h>
> +#include <linux/rculist.h>
> #include <linux/stacktrace.h>
> #include <linux/static_call.h>
> #include "core.h"
> @@ -201,12 +202,16 @@ void klp_update_patch_state(struct task_struct *task)
> /*
> * Determine whether the given stack trace includes any references to a
> * to-be-patched or to-be-unpatched function.
> + *
> + * Must be called under rcu_read_lock(), see klp_check_stack().
> */
> static int klp_check_stack_func(struct klp_func *func, unsigned long
> *entries,
> unsigned int nr_entries)
> {
> unsigned long func_addr, func_size, address;
> + struct klp_func *prev;
> struct klp_ops *ops;
> + void *old_func;
> int i;
>
> if (klp_target_state == KLP_TRANSITION_UNPATCHED) {
As per always, I much prefer things like lockdep_assert_held() and
__must_hold() over comments.