]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mmc: tmio: avoid concurrent runs of mmc_request_done()
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Tue, 5 Mar 2024 10:42:56 +0000 (11:42 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 13 Apr 2024 10:58:18 +0000 (12:58 +0200)
[ Upstream commit e8d1b41e69d72c62865bebe8f441163ec00b3d44 ]

With the to-be-fixed commit, the reset_work handler cleared 'host->mrq'
outside of the spinlock protected critical section. That leaves a small
race window during execution of 'tmio_mmc_reset()' where the done_work
handler could grab a pointer to the now invalid 'host->mrq'. Both would
use it to call mmc_request_done() causing problems (see link below).

However, 'host->mrq' cannot simply be cleared earlier inside the
critical section. That would allow new mrqs to come in asynchronously
while the actual reset of the controller still needs to be done. So,
like 'tmio_mmc_set_ios()', an ERR_PTR is used to prevent new mrqs from
coming in but still avoiding concurrency between work handlers.

Reported-by: Dirk Behme <dirk.behme@de.bosch.com>
Closes: https://lore.kernel.org/all/20240220061356.3001761-1-dirk.behme@de.bosch.com/
Fixes: df3ef2d3c92c ("mmc: protect the tmio_mmc driver against a theoretical race")
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
Reviewed-by: Dirk Behme <dirk.behme@de.bosch.com>
Cc: stable@vger.kernel.org # 3.0+
Link: https://lore.kernel.org/r/20240305104423.3177-2-wsa+renesas@sang-engineering.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/mmc/host/tmio_mmc_core.c

index abf36acb2641f1010b2d023bd28dcbc9e873b538..0482920a796811e7a942c0b21e424d4ccf6dbda3 100644 (file)
@@ -216,6 +216,8 @@ static void tmio_mmc_reset_work(struct work_struct *work)
        else
                mrq->cmd->error = -ETIMEDOUT;
 
+       /* No new calls yet, but disallow concurrent tmio_mmc_done_work() */
+       host->mrq = ERR_PTR(-EBUSY);
        host->cmd = NULL;
        host->data = NULL;