This is a note to let you know that I've just added the patch titled sh: push-switch: Reorder cleanup operations to avoid use-after-free bug to the 6.5-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: sh-push-switch-reorder-cleanup-operations-to-avoid-u.patch and it can be found in the queue-6.5 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit e272121a7e99c8609a1ab93af553333485a1948a Author: Duoming Zhou <duoming@xxxxxxxxxx> Date: Wed Aug 2 11:37:37 2023 +0800 sh: push-switch: Reorder cleanup operations to avoid use-after-free bug [ Upstream commit 246f80a0b17f8f582b2c0996db02998239057c65 ] The original code puts flush_work() before timer_shutdown_sync() in switch_drv_remove(). Although we use flush_work() to stop the worker, it could be rescheduled in switch_timer(). As a result, a use-after-free bug can occur. The details are shown below: (cpu 0) | (cpu 1) switch_drv_remove() | flush_work() | ... | switch_timer // timer | schedule_work(&psw->work) timer_shutdown_sync() | ... | switch_work_handler // worker kfree(psw) // free | | psw->state = 0 // use This patch puts timer_shutdown_sync() before flush_work() to mitigate the bugs. As a result, the worker and timer will be stopped safely before the deallocate operations. Fixes: 9f5e8eee5cfe ("sh: generic push-switch framework.") Signed-off-by: Duoming Zhou <duoming@xxxxxxxxxx> Reviewed-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx> Reviewed-by: John Paul Adrian Glaubitz <glaubitz@xxxxxxxxxxxxxxxxxxx> Link: https://lore.kernel.org/r/20230802033737.9738-1-duoming@xxxxxxxxxx Signed-off-by: John Paul Adrian Glaubitz <glaubitz@xxxxxxxxxxxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c index c95f48ff3f6fb..6ecba5f521eb6 100644 --- a/arch/sh/drivers/push-switch.c +++ b/arch/sh/drivers/push-switch.c @@ -101,8 +101,8 @@ static int switch_drv_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &dev_attr_switch); platform_set_drvdata(pdev, NULL); - flush_work(&psw->work); timer_shutdown_sync(&psw->debounce); + flush_work(&psw->work); free_irq(irq, pdev); kfree(psw);