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().
Unified · Split
| @@ -666,7 +666,7 @@ static inline bool within_module(unsigned long addr, const struct module *mod) · 665 unmodified lines | |||
| 666 | return within_module_init(addr, mod) || within_module_core(addr, mod); | 666 | return within_module_init(addr, mod) || within_module_core(addr, mod); |
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | /* Search for module by name: must be in a RCU-sched critical section. */ | 669 | /* Search for module by name: must be in a RCU critical section. */ |
| 670 | struct module *find_module(const char *name); | 670 | struct module *find_module(const char *name); |
| 671 | 671 | ||
| 672 | extern void __noreturn __module_put_and_kthread_exit(struct module *mod, | 672 | extern void __noreturn __module_put_and_kthread_exit(struct module *mod, |
| @@ -59,7 +59,7 @@ static void klp_find_object_module(struct klp_object *obj) · 58 unmodified lines | |||
| 59 | if (!klp_is_module(obj)) | 59 | if (!klp_is_module(obj)) |
| 60 | return; | 60 | return; |
| 61 | 61 | ||
| 62 | rcu_read_lock_sched(); | 62 | guard(rcu)(); |
| 63 | /* | 63 | /* |
| 64 | * We do not want to block removal of patched modules and therefore | 64 | * We do not want to block removal of patched modules and therefore |
| 65 | * we do not take a reference here. The patches are removed by | 65 | * we do not take a reference here. The patches are removed by |
| @@ -75,8 +75,6 @@ static void klp_find_object_module(struct klp_object *obj) · 9 unmodified lines | |||
| 75 | */ | 75 | */ |
| 76 | if (mod && mod->klp_alive) | 76 | if (mod && mod->klp_alive) |
| 77 | obj->mod = mod; | 77 | obj->mod = mod; |
| 78 | |||
| 79 | rcu_read_unlock_sched(); | ||
| 80 | } | 78 | } |
| 81 | 79 | ||
| 82 | static bool klp_initialized(void) | 80 | static bool klp_initialized(void) |
| @@ -450,6 +450,7 @@ unsigned long module_kallsyms_lookup_name(const char *name) · 449 unmodified lines | |||
| 450 | unsigned long ret; | 450 | unsigned long ret; |
| 451 | 451 | ||
| 452 | /* Don't lock: we're in enough trouble already. */ | 452 | /* Don't lock: we're in enough trouble already. */ |
| 453 | guard(rcu)(); | ||
| 453 | preempt_disable(); | 454 | preempt_disable(); |
| 454 | ret = __module_kallsyms_lookup_name(name); | 455 | ret = __module_kallsyms_lookup_name(name); |
| 455 | preempt_enable(); | 456 | preempt_enable(); |
| @@ -374,16 +374,14 @@ bool find_symbol(struct find_symbol_arg *fsa) · 373 unmodified lines | |||
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | /* | 376 | /* |
| 377 | * Search for module by name: must hold module_mutex (or preempt disabled | 377 | * Search for module by name: must hold module_mutex (or RCU for read-only |
| 378 | * for read-only access). | 378 | * access). |
| 379 | */ | 379 | */ |
| 380 | struct module *find_module_all(const char *name, size_t len, | 380 | struct module *find_module_all(const char *name, size_t len, |
| 381 | bool even_unformed) | 381 | bool even_unformed) |
| 382 | { | 382 | { |
| 383 | struct module *mod; | 383 | struct module *mod; |
| 384 | 384 | ||
| 385 | module_assert_mutex_or_preempt(); | ||
| 386 | |||
| 387 | list_for_each_entry_rcu(mod, &modules, list, | 385 | list_for_each_entry_rcu(mod, &modules, list, |
| 388 | lockdep_is_held(&module_mutex)) { | 386 | lockdep_is_held(&module_mutex)) { |
| 389 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) | 387 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) |
| @@ -124,9 +124,8 @@ static nokprobe_inline bool trace_kprobe_module_exist(struct trace_kprobe *tk) · 123 unmodified lines | |||
| 124 | if (!p) | 124 | if (!p) |
| 125 | return true; | 125 | return true; |
| 126 | *p = '\0'; | 126 | *p = '\0'; |
| 127 | rcu_read_lock_sched(); | 127 | scoped_guard(rcu) |
| 128 | ret = !!find_module(tk->symbol); | 128 | ret = !!find_module(tk->symbol); |
| 129 | rcu_read_unlock_sched(); | ||
| 130 | *p = ':'; | 129 | *p = ':'; |
| 131 | 130 | ||
| 132 | return ret; | 131 | return ret; |
| @@ -796,12 +795,10 @@ static struct module *try_module_get_by_name(const char *name) · 663 unmodified lines | |||
| 796 | { | 795 | { |
| 797 | struct module *mod; | 796 | struct module *mod; |
| 798 | 797 | ||
| 799 | rcu_read_lock_sched(); | 798 | guard(rcu)(); |
| 800 | mod = find_module(name); | 799 | mod = find_module(name); |
| 801 | if (mod && !try_module_get(mod)) | 800 | if (mod && !try_module_get(mod)) |
| 802 | mod = NULL; | 801 | mod = NULL; |
| 803 | rcu_read_unlock_sched(); | ||
| 804 | |||
| 805 | return mod; | 802 | return mod; |
| 806 | } | 803 | } |
| 807 | #else | 804 | #else |