module_assert_mutex_or_preempt() is not needed in find_symbol(). The function checks for RCU-sched or the module_mutex to be acquired. The list_for_each_entry_rcu() below does the same check. Remove module_assert_mutex_or_preempt() from try_add_tainted_module(). Use RCU protection to invoke find_symbol() and update callers.
Showing the changes to kernel/module (2 of 2 files). Show all
Unified · Split
| @@ -331,7 +331,7 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms, · 330 unmodified lines | |||
| 331 | 331 | ||
| 332 | /* | 332 | /* |
| 333 | * Find an exported symbol and return it, along with, (optional) crc and | 333 | * Find an exported symbol and return it, along with, (optional) crc and |
| 334 | * (optional) module which owns it. Needs preempt disabled or module_mutex. | 334 | * (optional) module which owns it. Needs RCU or module_mutex. |
| 335 | */ | 335 | */ |
| 336 | bool find_symbol(struct find_symbol_arg *fsa) | 336 | bool find_symbol(struct find_symbol_arg *fsa) |
| 337 | { | 337 | { |
| @@ -345,8 +345,6 @@ bool find_symbol(struct find_symbol_arg *fsa) · 7 unmodified lines | |||
| 345 | struct module *mod; | 345 | struct module *mod; |
| 346 | unsigned int i; | 346 | unsigned int i; |
| 347 | 347 | ||
| 348 | module_assert_mutex_or_preempt(); | ||
| 349 | |||
| 350 | for (i = 0; i < ARRAY_SIZE(arr); i++) | 348 | for (i = 0; i < ARRAY_SIZE(arr); i++) |
| 351 | if (find_exported_symbol_in_section(&arr[i], NULL, fsa)) | 349 | if (find_exported_symbol_in_section(&arr[i], NULL, fsa)) |
| 352 | return true; | 350 | return true; |
| @@ -812,10 +810,9 @@ void __symbol_put(const char *symbol) · 459 unmodified lines | |||
| 812 | .gplok = true, | 810 | .gplok = true, |
| 813 | }; | 811 | }; |
| 814 | 812 | ||
| 815 | preempt_disable(); | 813 | guard(rcu)(); |
| 816 | BUG_ON(!find_symbol(&fsa)); | 814 | BUG_ON(!find_symbol(&fsa)); |
| 817 | module_put(fsa.owner); | 815 | module_put(fsa.owner); |
| 818 | preempt_enable(); | ||
| 819 | } | 816 | } |
| 820 | EXPORT_SYMBOL(__symbol_put); | 817 | EXPORT_SYMBOL(__symbol_put); |
| 821 | 818 | ||
| @@ -1369,21 +1366,18 @@ void *__symbol_get(const char *symbol) · 547 unmodified lines | |||
| 1369 | .warn = true, | 1366 | .warn = true, |
| 1370 | }; | 1367 | }; |
| 1371 | 1368 | ||
| 1372 | preempt_disable(); | 1369 | scoped_guard(rcu) { |
| 1373 | if (!find_symbol(&fsa)) | 1370 | if (!find_symbol(&fsa)) |
| 1374 | goto fail; | 1371 | return NULL; |
| 1375 | if (fsa.license != GPL_ONLY) { | 1372 | if (fsa.license != GPL_ONLY) { |
| 1376 | pr_warn("failing symbol_get of non-GPLONLY symbol %s.\n", | 1373 | pr_warn("failing symbol_get of non-GPLONLY symbol %s.\n", |
| 1377 | symbol); | 1374 | symbol); |
| 1378 | goto fail; | 1375 | return NULL; |
| 1376 | } | ||
| 1377 | if (strong_try_module_get(fsa.owner)) | ||
| 1378 | return NULL; | ||
| 1379 | } | 1379 | } |
| 1380 | if (strong_try_module_get(fsa.owner)) | ||
| 1381 | goto fail; | ||
| 1382 | preempt_enable(); | ||
| 1383 | return (void *)kernel_symbol_value(fsa.sym); | 1380 | return (void *)kernel_symbol_value(fsa.sym); |
| 1384 | fail: | ||
| 1385 | preempt_enable(); | ||
| 1386 | return NULL; | ||
| 1387 | } | 1381 | } |
| 1388 | EXPORT_SYMBOL_GPL(__symbol_get); | 1382 | EXPORT_SYMBOL_GPL(__symbol_get); |
| 1389 | 1383 | ||
| @@ -79,17 +79,17 @@ int check_modstruct_version(const struct load_info *info, · 78 unmodified lines | |||
| 79 | .name = "module_layout", | 79 | .name = "module_layout", |
| 80 | .gplok = true, | 80 | .gplok = true, |
| 81 | }; | 81 | }; |
| 82 | bool have_symbol; | ||
| 82 | 83 | ||
| 83 | /* | 84 | /* |
| 84 | * Since this should be found in kernel (which can't be removed), no | 85 | * Since this should be found in kernel (which can't be removed), no |
| 85 | * locking is necessary -- use preempt_disable() to placate lockdep. | 86 | * locking is necessary. Regardless use a RCU read section to keep |
| 87 | * lockdep happy. | ||
| 86 | */ | 88 | */ |
| 87 | preempt_disable(); | 89 | scoped_guard(rcu) |
| 88 | if (!find_symbol(&fsa)) { | 90 | have_symbol = find_symbol(&fsa); |
| 89 | preempt_enable(); | 91 | BUG_ON(!have_symbol); |
| 90 | BUG(); | 92 | |
| 91 | } | ||
| 92 | preempt_enable(); | ||
| 93 | return check_version(info, "module_layout", mod, fsa.crc); | 93 | return check_version(info, "module_layout", mod, fsa.crc); |
| 94 | } | 94 | } |
| 95 | 95 | ||