Re: [RFC] module: init-failure path can free a module with live try_module_get() users
From: David Laight
Date: Mon Sep 21 2026 - 12:15:31 EST
On Mon, 21 Sep 2026 20:04:10 +0530
Mahanta Jambigi <mjambigi@xxxxxxxxxxxxx> wrote:
> On 18/09/26 6:52 pm, David Laight wrote:
> > On Mon, 24 Aug 2026 11:43:46 +0530
> > Mahanta Jambigi <mjambigi@xxxxxxxxxxxxx> wrote:
> >
> >> Hi Luis, Petr, Daniel, Sami, Aaron,
> >>
> >> I'm writing to ask about what looks like a generic module-init failure
> >> lifetime problem in the module loader. I ran into it while working on
> >> the SMC networking module (net/smc/), but after several patch
> >> iterations, it seems the root issue may belong in kernel/module/main.c
> >> rather than in SMC itself. I'd appreciate your guidance on whether this
> >> reading is correct, and if so, what fix direction would be preferred.
> >>
> >> THE ISSUE IN do_init_module()
> >> =============================
> >>
> >> include/linux/module.h has a long-standing FIXME in module_is_live():
> >>
> >> /* FIXME: It'd be nice to isolate modules during init, too, so they
> >> aren't used before they (may) fail. But presently too much code
> >> (IDE & SCSI) require entry into the module during init. */
> >> static inline bool module_is_live(struct module *mod)
> >> {
> >> return mod->state != MODULE_STATE_GOING;
> >> }
> >>
> >> Because MODULE_STATE_COMING is not MODULE_STATE_GOING, try_module_get()
> >> can succeed once a module's __init is executing. If __init makes the
> >> module externally reachable partway through and then later fails, the
> >> failure path in do_init_module() appears to do:
> >
> > It is rather worse that that.
> > If sock_create() auto-loads a module (eg sctp) then nothing stops a second
> > sock_create() entering the protocol code before the initialisation completes.
> > That can be hit by two separate applications, I hit it from an out of tree
> > kernel module and avoided the problem by putting a mutex() around the
> > sock_create() call.
> >
> > It might help by letting try_module_get(THIS_MODULE) always succeed
> > while blocking other requests until initialisation completes.
> > The code making the call must own a reference (otherwise the code could
> > just disappear), and that reference stops the module being unloaded.
> > That would let the initialisation code grab extra references (eg for
> > a worker thread) without allowing other codes paths enter the
> > part-initialised driver.
>
> Thanks David — you're right that the race is broader. This patch
> addresses only the UAF on the __init failure path: once we set
> MODULE_STATE_GOING and call synchronize_rcu(), new callers see GOING and
> fail; we then drain existing refs before free_module().
>
> The concurrent-init race you describe — two callers entering
> MODULE_STATE_COMING simultaneously during a successful init — is not
> addressed here and would require changes to try_module_get() itself, as
> you suggest. That is the long-standing FIXME in module_is_live() and is
> a separate, larger change.
I suspect it is also much more common.
Module load doesn't normally fail, but if you can persuade the system to
unload an unused module I'd expect a non-root user can hit the concurrent
init race.
David