* [PATCH] misc: mei: fix race condition between client teardown and read completion
@ 2026-08-23 13:26 nirbhayykumarr
2026-08-23 17:09 ` gregkh
0 siblings, 1 reply; 2+ messages in thread
From: nirbhayykumarr @ 2026-08-23 13:26 UTC (permalink / raw)
To: alexander.usyskin, arnd, gregkh; +Cc: linux-kernel, w, stable
[-- Attachment #1: Type: text/plain, Size: 2945 bytes --]
In mei_release(), a host client is torn down upon close(). During this
teardown sequence, mei_cl_disconnect() is invoked, which releases
dev->device_lock while waiting for the firmware response.
If an in-flight read request was previously submitted, an incoming
completion interrupt processed concurrently by the MEI interrupt
handler can add a completed callback into cl->rd_completed via
mei_cl_add_rd_completed().
Because mei_cl_flush_queues(cl, NULL) was invoked before mei_cl_unlink(cl),
an incoming completion callback can slip into cl->rd_completed after the
flush has completed but before the client is unlinked from dev->file_list.
When mei_cl_unlink() is subsequently called, the invariant check at
drivers/misc/mei/client.c:698 triggers:
WARN_ON(!list_empty(&cl->rd_completed) ||
!list_empty(&cl->rd_pending) ||
!list_empty(&cl->link));
Call trace:
WARNING: CPU: 2 PID: 5056 at drivers/misc/mei/client.c:698 mei_cl_unlink+0xaa/0x140 [mei]
RIP: 0010:mei_cl_unlink+0xaa/0x140 [mei]
Call Trace:
<TASK>
mei_release+0x202/0x270 [mei]
__fput+0x105/0x2e0
__x64_sys_close+0x90/0x140
do_syscall_64+0xaa/0x660
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Immediately following mei_cl_unlink(), mei_release() calls kfree(cl).
If any remaining or deferred callback references the freed client, a
use-after-free occurs.
Fix this by flushing queues after unlinking the client from dev->file_list
inside mei_cl_unlink(), preventing concurrent IRQ completions from
populating the client's completed queue during teardown.
Reported-by: Nirbhay Kumar <nirbhayykumarr@proton.me>
Signed-off-by: Nirbhay Kumar <nirbhayykumarr@proton.me>
Cc: stable@vger.kernel.org
---
Thanks to Willy Tarreau and Greg Kroah-Hartman for their review and guidance
on the initial report.
Note: Sent via webmail; I have also attached the raw .patch file as a backup
in case webmail clients introduce any subtle whitespace wrapping.
drivers/misc/mei/client.c | 2 ++
drivers/misc/mei/main.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 643b003..38b5792 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -695,6 +695,8 @@ int mei_cl_unlink(struct mei_cl *cl)
cl->state = MEI_FILE_UNINITIALIZED;
cl->writing_state = MEI_IDLE;
+ mei_cl_flush_queues(cl, NULL);
+
WARN_ON(!list_empty(&cl->rd_completed) ||
!list_empty(&cl->rd_pending) ||
!list_empty(&cl->link));
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 4fbf0b3..9e14ab4 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -148,7 +148,6 @@ static int mei_release(struct inode *inode, struct file *file)
goto out;
}
- mei_cl_flush_queues(cl, NULL);
cl_dbg(dev, cl, "removing\n");
mei_cl_unlink(cl);
--
2.55.0
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-misc-mei-fix-race-condition-between-client-teardown.patch --]
[-- Type: text/x-patch; name=0001-misc-mei-fix-race-condition-between-client-teardown.patch, Size: 3115 bytes --]
From 0c86e967996e49cf6818b643e41dff66504c7f07 Mon Sep 17 00:00:00 2001
From: Nirbhay Kumar <nirbhayykumarr@proton.me>
Date: Sun, 23 Aug 2026 18:37:53 +0530
Subject: [PATCH] misc: mei: fix race condition between client teardown and
read completion
In mei_release(), a host client is torn down upon close(). During this
teardown sequence, mei_cl_disconnect() is invoked, which releases
dev->device_lock while waiting for the firmware response.
If an in-flight read request was previously submitted, an incoming
completion interrupt processed concurrently by the MEI interrupt
handler can add a completed callback into cl->rd_completed via
mei_cl_add_rd_completed().
Because mei_cl_flush_queues(cl, NULL) was invoked before mei_cl_unlink(cl),
an incoming completion callback can slip into cl->rd_completed after the
flush has completed but before the client is unlinked from dev->file_list.
When mei_cl_unlink() is subsequently called, the invariant check at
drivers/misc/mei/client.c:698 triggers:
WARN_ON(!list_empty(&cl->rd_completed) ||
!list_empty(&cl->rd_pending) ||
!list_empty(&cl->link));
Call trace:
WARNING: CPU: 2 PID: 5056 at drivers/misc/mei/client.c:698 mei_cl_unlink+0xaa/0x140 [mei]
RIP: 0010:mei_cl_unlink+0xaa/0x140 [mei]
Call Trace:
<TASK>
mei_release+0x202/0x270 [mei]
__fput+0x105/0x2e0
__x64_sys_close+0x90/0x140
do_syscall_64+0xaa/0x660
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Immediately following mei_cl_unlink(), mei_release() calls kfree(cl).
If any remaining or deferred callback references the freed client, a
use-after-free occurs.
Fix this by flushing queues after unlinking the client from dev->file_list
inside mei_cl_unlink(), preventing concurrent IRQ completions from
populating the client's completed queue during teardown.
Reported-by: Nirbhay Kumar <nirbhayykumarr@proton.me>
Signed-off-by: Nirbhay Kumar <nirbhayykumarr@proton.me>
Cc: stable@vger.kernel.org
---
Thanks to Willy Tarreau and Greg Kroah-Hartman for their review and guidance
on the initial report.
Note: Sent via webmail; I have also attached the raw .patch file as a backup
in case webmail clients introduce any subtle whitespace wrapping.
drivers/misc/mei/client.c | 2 ++
drivers/misc/mei/main.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 643b003..38b5792 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -695,6 +695,8 @@ int mei_cl_unlink(struct mei_cl *cl)
cl->state = MEI_FILE_UNINITIALIZED;
cl->writing_state = MEI_IDLE;
+ mei_cl_flush_queues(cl, NULL);
+
WARN_ON(!list_empty(&cl->rd_completed) ||
!list_empty(&cl->rd_pending) ||
!list_empty(&cl->link));
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 4fbf0b3..9e14ab4 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -148,7 +148,6 @@ static int mei_release(struct inode *inode, struct file *file)
goto out;
}
- mei_cl_flush_queues(cl, NULL);
cl_dbg(dev, cl, "removing\n");
mei_cl_unlink(cl);
--
2.55.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] misc: mei: fix race condition between client teardown and read completion
2026-08-23 13:26 [PATCH] misc: mei: fix race condition between client teardown and read completion nirbhayykumarr
@ 2026-08-23 17:09 ` gregkh
0 siblings, 0 replies; 2+ messages in thread
From: gregkh @ 2026-08-23 17:09 UTC (permalink / raw)
To: nirbhayykumarr; +Cc: alexander.usyskin, arnd, linux-kernel, w, stable
On Sun, Aug 23, 2026 at 01:26:09PM +0000, nirbhayykumarr@proton.me wrote:
> In mei_release(), a host client is torn down upon close(). During this
> teardown sequence, mei_cl_disconnect() is invoked, which releases
> dev->device_lock while waiting for the firmware response.
>
> If an in-flight read request was previously submitted, an incoming
> completion interrupt processed concurrently by the MEI interrupt
> handler can add a completed callback into cl->rd_completed via
> mei_cl_add_rd_completed().
>
> Because mei_cl_flush_queues(cl, NULL) was invoked before mei_cl_unlink(cl),
> an incoming completion callback can slip into cl->rd_completed after the
> flush has completed but before the client is unlinked from dev->file_list.
> When mei_cl_unlink() is subsequently called, the invariant check at
> drivers/misc/mei/client.c:698 triggers:
>
> WARN_ON(!list_empty(&cl->rd_completed) ||
> !list_empty(&cl->rd_pending) ||
> !list_empty(&cl->link));
>
> Call trace:
> WARNING: CPU: 2 PID: 5056 at drivers/misc/mei/client.c:698 mei_cl_unlink+0xaa/0x140 [mei]
> RIP: 0010:mei_cl_unlink+0xaa/0x140 [mei]
> Call Trace:
> <TASK>
> mei_release+0x202/0x270 [mei]
> __fput+0x105/0x2e0
> __x64_sys_close+0x90/0x140
> do_syscall_64+0xaa/0x660
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> </TASK>
>
> Immediately following mei_cl_unlink(), mei_release() calls kfree(cl).
> If any remaining or deferred callback references the freed client, a
> use-after-free occurs.
>
> Fix this by flushing queues after unlinking the client from dev->file_list
> inside mei_cl_unlink(), preventing concurrent IRQ completions from
> populating the client's completed queue during teardown.
>
> Reported-by: Nirbhay Kumar <nirbhayykumarr@proton.me>
> Signed-off-by: Nirbhay Kumar <nirbhayykumarr@proton.me>
No need for Reported-by as you authored and signed off on this.
And did you forget an Assisted-by: tag?
and what commit id does this fix?
Also, no need to attach this at all, just send it using git send-email
as-is.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-23 17:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-23 13:26 [PATCH] misc: mei: fix race condition between client teardown and read completion nirbhayykumarr
2026-08-23 17:09 ` gregkh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®