From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Date: Wed, 8 Jan 2025 10:04:35 +0100 Subject: [PATCH 06/28] module: Use RCU in find_module_all(). The modules list and module::kallsyms can be accessed under RCU assumption. Remove module_assert_mutex_or_preempt() from find_module_all() so it can be used under RCU protection without warnings. Update its callers to use RCU protection instead of preempt_disable(). Cc: Jiri Kosina <jikos@kernel.org> Cc: Joe Lawrence <joe.lawrence@redhat.com> Cc: Josh Poimboeuf <jpoimboe@kernel.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Cc: Miroslav Benes <mbenes@suse.cz> Cc: Petr Mladek <pmladek@suse.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: linux-trace-kernel@vger.kernel.org Cc: live-patching@vger.kernel.org Reviewed-by: Petr Mladek <pmladek@suse.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20250108090457.512198-7-bigeasy@linutronix.de Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> --- include/linux/module.h | 2 +- kernel/livepatch/core.c | 4 +--- kernel/module/kallsyms.c | 1 + kernel/module/main.c | 6 ++---- kernel/trace/trace_kprobe.c | 9 +++------ 5 files changed, 8 insertions(+), 14 deletions(-) @ include/linux/module.h:669 @ static inline bool within_module(unsigne return within_module_init(addr, mod) || within_module_core(addr, mod); } -/* Search for module by name: must be in a RCU-sched critical section. */ +/* Search for module by name: must be in a RCU critical section. */ struct module *find_module(const char *name); extern void __noreturn __module_put_and_kthread_exit(struct module *mod, --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @ include/linux/module.h:62 @ static void klp_find_object_module(struc if (!klp_is_module(obj)) return; - rcu_read_lock_sched(); + guard(rcu)(); /* * We do not want to block removal of patched modules and therefore * we do not take a reference here. The patches are removed by @ include/linux/module.h:78 @ static void klp_find_object_module(struc */ if (mod && mod->klp_alive) obj->mod = mod; - - rcu_read_unlock_sched(); } static bool klp_initialized(void) --- a/kernel/module/kallsyms.c +++ b/kernel/module/kallsyms.c @ include/linux/module.h:453 @ unsigned long module_kallsyms_lookup_nam unsigned long ret; /* Don't lock: we're in enough trouble already. */ + guard(rcu)(); preempt_disable(); ret = __module_kallsyms_lookup_name(name); preempt_enable(); --- a/kernel/module/main.c +++ b/kernel/module/main.c @ include/linux/module.h:377 @ bool find_symbol(struct find_symbol_arg } /* - * Search for module by name: must hold module_mutex (or preempt disabled - * for read-only access). + * Search for module by name: must hold module_mutex (or RCU for read-only + * access). */ struct module *find_module_all(const char *name, size_t len, bool even_unformed) { struct module *mod; - module_assert_mutex_or_preempt(); - list_for_each_entry_rcu(mod, &modules, list, lockdep_is_held(&module_mutex)) { if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @ include/linux/module.h:127 @ static nokprobe_inline bool trace_kprobe if (!p) return true; *p = '\0'; - rcu_read_lock_sched(); - ret = !!find_module(tk->symbol); - rcu_read_unlock_sched(); + scoped_guard(rcu) + ret = !!find_module(tk->symbol); *p = ':'; return ret; @ include/linux/module.h:798 @ static struct module *try_module_get_by_ { struct module *mod; - rcu_read_lock_sched(); + guard(rcu)(); mod = find_module(name); if (mod && !try_module_get(mod)) mod = NULL; - rcu_read_unlock_sched(); - return mod; } #else