mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®