* [PATCH v2] module: Fix use-after-free in module_put() tracepoint
@ 2026-10-22 18:45 Aaron Tomlin
2026-10-22 18:52 ` sashiko-bot
0 siblings, 1 reply; 3+ messages in thread
From: Aaron Tomlin @ 2026-10-22 18:45 UTC (permalink / raw)
To: mcgrof, petr.pavlu, da.gomez, samitolvanen
Cc: atomlin, da.anzani, linux-modules, linux-kernel
A use-after-free condition can arise in module_put() should a thread be
preempted immediately after decrementing the module's reference count
while the module is concurrently being unloaded.
In module_put(), the module's reference count is decremented via
atomic_dec_if_positive() before the module pointer is passed to
trace_module_put(). Consider a scenario where CPU 0 decrements the
reference count without reaching the baseline MODULE_REF_BASE level and
is immediately preempted: it relinquishes its reference while still
retaining a local pointer to the module. If a concurrent CPU 1
subsequently drops the final active reference, the module's reference
count reaches MODULE_REF_BASE. This permits the module unload sequence
(via delete_module() or the initialisation-failure tear-down path) to
proceed and invoke free_module().
Function free_module() invokes synchronize_rcu() and subsequently
releases the memory backing struct module via free_mod_mem(). Because
CPU 0 was preempted outside an RCU read-side critical section,
synchronize_rcu() does not await CPU 0. When CPU 0 eventually resumes
execution, it passes the dangling module pointer to trace_module_put(),
which dereferences mod->name and mod->refcnt, culminating in a
use-after-free. This sequence of events is illustrated below:
CPU 0 CPU 1
----- -----
module_put(module)
atomic_dec_if_positive()
[preempted]
module_put(module)
atomic_dec_if_positive()
// drops final reference
free_module(module)
synchronize_rcu()
free_mod_mem(module)
trace_module_put(module, ...)
mod->name
Resolve this by moving trace_module_put() prior to
atomic_dec_if_positive(). Because the caller holds an active reference
to the module at this point, the module structure and its name are
guaranteed to remain valid throughout the tracepoint invocation without
requiring preemption disabling or RCU synchronisation.
Fixes: cb0b50b813f6 ("module: Remove preempt_disable() from module reference counting.")
Cc: stable@vger.kernel.org
Signed-off-by: Aaron Tomlin <atomlin@atomlin.com>
---
Changes since v1:
- Drop guard(rcu)() and relocate trace_module_put() before the atomic
decrement instead, avoiding RCU overhead on every module_put() while
safely relying on the caller's held reference (Petr Pavlu)
- Link to v1: https://lore.kernel.org/all/20261019034857.654569-1-atomlin@atomlin.com/
---
kernel/module/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index c1b34dc1e89a..0c8df0984bc2 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -953,9 +953,9 @@ void module_put(struct module *module)
int ret;
if (module) {
+ trace_module_put(module, _RET_IP_);
ret = atomic_dec_if_positive(&module->refcnt);
WARN_ON(ret < 0); /* Failed to put refcount */
- trace_module_put(module, _RET_IP_);
}
}
EXPORT_SYMBOL(module_put);
--
2.55.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH v2] module: Fix use-after-free in module_put() tracepoint
2026-10-22 18:45 [PATCH v2] module: Fix use-after-free in module_put() tracepoint Aaron Tomlin
@ 2026-10-22 18:52 ` sashiko-bot
2026-10-22 19:04 ` Aaron Tomlin
0 siblings, 1 reply; 3+ messages in thread
From: sashiko-bot @ 2026-10-22 18:52 UTC (permalink / raw)
To: Aaron Tomlin; +Cc: linux-modules, Petr Pavlu
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] module: trace_module_put() records pre-decrement refcnt in module_put()
--
commit 2c168275e42fc7a4482d549cb0c9f1fc9f71e395
Author: Aaron Tomlin <atomlin@atomlin.com>
module: Fix use-after-free in module_put() tracepoint
This commit moves trace_module_put() before atomic_dec_if_positive() in
module_put() to prevent a use-after-free if the thread is preempted after
decrementing the module reference count while the module is being unloaded.
> diff --git a/kernel/module/main.c b/kernel/module/main.c
> index f1392c10907a2..70063fea52d03 100644
> --- a/kernel/module/main.c
> +++ b/kernel/module/main.c
> @@ -954,9 +954,9 @@ void module_put(struct module *module)
> int ret;
>
> if (module) {
> + trace_module_put(module, _RET_IP_);
> ret = atomic_dec_if_positive(&module->refcnt);
> WARN_ON(ret < 0); /* Failed to put refcount */
> - trace_module_put(module, _RET_IP_);
[Severity: Medium]
Does moving trace_module_put() before atomic_dec_if_positive() in
module_put() cause the module_put trace event to record a reference count
that is off by one?
In include/trace/events/module.h, both module_get and module_put use the
module_refcnt event class, which reads mod->refcnt directly inside
TP_fast_assign():
include/trace/events/module.h:
DECLARE_EVENT_CLASS(module_refcnt,
...
TP_fast_assign(
__entry->ip = ip;
__entry->refcnt = atomic_read(&mod->refcnt);
__assign_str(name);
),
In kernel/module/main.c, __module_get() and try_module_get() call
trace_module_get() after incrementing module->refcnt, recording the
post-increment value:
kernel/module/main.c:__module_get() {
if (module) {
atomic_inc(&module->refcnt);
trace_module_get(module, _RET_IP_);
}
}
With trace_module_put() now invoked before atomic_dec_if_positive() in
module_put() when a non-null module pointer is passed and the module_put
tracepoint is enabled, TP_fast_assign() reads atomic_read(&mod->refcnt)
before the decrement occurs. As a result, a matched get and put pair on a
live module logs the pre-decrement refcnt on module_put instead of the
post-decrement refcnt.
> }
> }
> EXPORT_SYMBOL(module_put);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261022184517.66438-1-atomlin@atomlin.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH v2] module: Fix use-after-free in module_put() tracepoint
2026-10-22 18:52 ` sashiko-bot
@ 2026-10-22 19:04 ` Aaron Tomlin
0 siblings, 0 replies; 3+ messages in thread
From: Aaron Tomlin @ 2026-10-22 19:04 UTC (permalink / raw)
To: sashiko-reviews; +Cc: linux-modules, Petr Pavlu
On Thu, Oct 22, 2026 at 06:52:48PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] module: trace_module_put() records pre-decrement refcnt in module_put()
> --
>
> commit 2c168275e42fc7a4482d549cb0c9f1fc9f71e395
> Author: Aaron Tomlin <atomlin@atomlin.com>
>
> module: Fix use-after-free in module_put() tracepoint
>
> This commit moves trace_module_put() before atomic_dec_if_positive() in
> module_put() to prevent a use-after-free if the thread is preempted after
> decrementing the module reference count while the module is being unloaded.
>
> > diff --git a/kernel/module/main.c b/kernel/module/main.c
> > index f1392c10907a2..70063fea52d03 100644
> > --- a/kernel/module/main.c
> > +++ b/kernel/module/main.c
> > @@ -954,9 +954,9 @@ void module_put(struct module *module)
> > int ret;
> >
> > if (module) {
> > + trace_module_put(module, _RET_IP_);
> > ret = atomic_dec_if_positive(&module->refcnt);
> > WARN_ON(ret < 0); /* Failed to put refcount */
> > - trace_module_put(module, _RET_IP_);
>
> [Severity: Medium]
> Does moving trace_module_put() before atomic_dec_if_positive() in
> module_put() cause the module_put trace event to record a reference count
> that is off by one?
Yes, moving trace_module_put() prior to atomic_dec_if_positive() means it
records the pre-decrement reference count rather than the post-decrement
count. Introducing unconditional RCU read-side locks on every call across
the kernel solely to keep an inactive debug tracepoint post-decrement
introduces unnecessary overhead. Relocating the tracepoint compiles down to
a zero-overhead static jump label when tracing is disabled.
--
Aaron Tomlin
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-22 19:04 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22 18:45 [PATCH v2] module: Fix use-after-free in module_put() tracepoint Aaron Tomlin
2026-10-22 18:52 ` sashiko-bot
2026-10-22 19:04 ` Aaron Tomlin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.