| From 99d7ab8db9d8230b243f5ed20ba0229e54cc0dfa Mon Sep 17 00:00:00 2001 |
| From: Jiayi Li <lijiayi@kylinos.cn> |
| Date: Mon, 4 Aug 2025 09:36:04 +0800 |
| Subject: memstick: Fix deadlock by moving removing flag earlier |
| |
| From: Jiayi Li <lijiayi@kylinos.cn> |
| |
| commit 99d7ab8db9d8230b243f5ed20ba0229e54cc0dfa upstream. |
| |
| The existing memstick core patch: commit 62c59a8786e6 ("memstick: Skip |
| allocating card when removing host") sets host->removing in |
| memstick_remove_host(),but still exists a critical time window where |
| memstick_check can run after host->eject is set but before removing is set. |
| |
| In the rtsx_usb_ms driver, the problematic sequence is: |
| |
| rtsx_usb_ms_drv_remove: memstick_check: |
| host->eject = true |
| cancel_work_sync(handle_req) if(!host->removing) |
| ... memstick_alloc_card() |
| memstick_set_rw_addr() |
| memstick_new_req() |
| rtsx_usb_ms_request() |
| if(!host->eject) |
| skip schedule_work |
| wait_for_completion() |
| memstick_remove_host: [blocks indefinitely] |
| host->removing = true |
| flush_workqueue() |
| [block] |
| |
| 1. rtsx_usb_ms_drv_remove sets host->eject = true |
| 2. cancel_work_sync(&host->handle_req) runs |
| 3. memstick_check work may be executed here <-- danger window |
| 4. memstick_remove_host sets removing = 1 |
| |
| During this window (step 3), memstick_check calls memstick_alloc_card, |
| which may indefinitely waiting for mrq_complete completion that will |
| never occur because rtsx_usb_ms_request sees eject=true and skips |
| scheduling work, memstick_set_rw_addr waits forever for completion. |
| |
| This causes a deadlock when memstick_remove_host tries to flush_workqueue, |
| waiting for memstick_check to complete, while memstick_check is blocked |
| waiting for mrq_complete completion. |
| |
| Fix this by setting removing=true at the start of rtsx_usb_ms_drv_remove, |
| before any work cancellation. This ensures memstick_check will see the |
| removing flag immediately and exit early, avoiding the deadlock. |
| |
| Fixes: 62c59a8786e6 ("memstick: Skip allocating card when removing host") |
| Signed-off-by: Jiayi Li <lijiayi@kylinos.cn> |
| Cc: stable@vger.kernel.org |
| Link: https://lore.kernel.org/r/20250804013604.1311218-1-lijiayi@kylinos.cn |
| Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/memstick/core/memstick.c | 1 - |
| drivers/memstick/host/rtsx_usb_ms.c | 1 + |
| 2 files changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/drivers/memstick/core/memstick.c |
| +++ b/drivers/memstick/core/memstick.c |
| @@ -548,7 +548,6 @@ EXPORT_SYMBOL(memstick_add_host); |
| */ |
| void memstick_remove_host(struct memstick_host *host) |
| { |
| - host->removing = 1; |
| flush_workqueue(workqueue); |
| mutex_lock(&host->lock); |
| if (host->card) |
| --- a/drivers/memstick/host/rtsx_usb_ms.c |
| +++ b/drivers/memstick/host/rtsx_usb_ms.c |
| @@ -812,6 +812,7 @@ static int rtsx_usb_ms_drv_remove(struct |
| int err; |
| |
| host->eject = true; |
| + msh->removing = true; |
| cancel_work_sync(&host->handle_req); |
| cancel_delayed_work_sync(&host->poll_card); |
| |