• Petr Pavlu's avatar
    module: Don't wait for GOING modules · 0254127a
    Petr Pavlu authored
    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 6e6de3de ("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 6e6de3de
    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
    6e6de3de (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: 6e6de3de ("kernel/module.c: Only return -EEXIST for modules that have finished loading")
    Co-developed-by: default avatarMartin Wilck <mwilck@suse.com>
    Signed-off-by: default avatarMartin Wilck <mwilck@suse.com>
    Signed-off-by: default avatarPetr Pavlu <petr.pavlu@suse.com>
    Cc: stable@vger.kernel.org
    Reviewed-by: default avatarPetr Mladek <pmladek@suse.com>
    [mcgrof: enhance commit log with testing and kmod test result interpretation ]
    Signed-off-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
    0254127a
main.c 79.9 KB