linux/kernel/module
Petr Pavlu 0254127ab9 module: Don't wait for GOING modules
During a system boot, it can happen that the kernel receives a burst of
requests to insert the same module but loading it eventually fails
during its init call. For instance, udev can make a request to insert
a frequency module for each individual CPU when another frequency module
is already loaded which causes the init function of the new module to
return an error.

Since commit 6e6de3dee5 ("kernel/module.c: Only return -EEXIST for
modules that have finished loading"), the kernel waits for modules in
MODULE_STATE_GOING state to finish unloading before making another
attempt to load the same module.

This creates unnecessary work in the described scenario and delays the
boot. In the worst case, it can prevent udev from loading drivers for
other devices and might cause timeouts of services waiting on them and
subsequently a failed boot.

This patch attempts a different solution for the problem 6e6de3dee5
was trying to solve. Rather than waiting for the unloading to complete,
it returns a different error code (-EBUSY) for modules in the GOING
state. This should avoid the error situation that was described in
6e6de3dee5 (user space attempting to load a dependent module because
the -EEXIST error code would suggest to user space that the first module
had been loaded successfully), while avoiding the delay situation too.

This has been tested on linux-next since December 2022 and passes
all kmod selftests except test 0009 with module compression enabled
but it has been confirmed that this issue has existed and has gone
unnoticed since prior to this commit and can also be reproduced without
module compression with a simple usleep(5000000) on tools/modprobe.c [0].
These failures are caused by hitting the kernel mod_concurrent_max and can
happen either due to a self inflicted kernel module auto-loead DoS somehow
or on a system with large CPU count and each CPU count incorrectly triggering
many module auto-loads. Both of those issues need to be fixed in-kernel.

[0] https://lore.kernel.org/all/Y9A4fiobL6IHp%2F%2FP@bombadil.infradead.org/

Fixes: 6e6de3dee5 ("kernel/module.c: Only return -EEXIST for modules that have finished loading")
Co-developed-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Cc: stable@vger.kernel.org
Reviewed-by: Petr Mladek <pmladek@suse.com>
[mcgrof: enhance commit log with testing and kmod test result interpretation ]
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
2023-01-24 12:52:52 -08:00
..
debug_kmemleak.c
decompress.c module/decompress: Support zstd in-kernel decompression 2022-12-07 12:05:05 -08:00
internal.h dyndbg: gather __dyndbg[] state into struct _ddebug_info 2022-09-07 17:04:48 +02:00
kallsyms.c kallsyms: Make module_kallsyms_on_each_symbol generally available 2022-10-25 10:14:50 -07:00
Kconfig module/decompress: Support zstd in-kernel decompression 2022-12-07 12:05:05 -08:00
kdb.c
livepatch.c
main.c module: Don't wait for GOING modules 2023-01-24 12:52:52 -08:00
Makefile
procfs.c module: Modify module_flags() to accept show_state argument 2022-07-14 17:40:23 -07:00
signing.c
strict_rwx.c
sysfs.c module: remove redundant module_sysfs_initialized variable 2022-11-11 10:19:52 -08:00
tracking.c module: tracking: Keep a record of tainted unloaded modules only 2022-10-10 12:16:19 -07:00
tree_lookup.c
version.c