Message ID | 20200618032125.4650-1-zhenzhong.duan@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | abd42781c3d2155868821f1b947ae45bbc33330d |
Headers | show |
Series | [1/2] spi: spidev: fix a race between spidev_release and spidev_remove | expand |
On Thu, 18 Jun 2020 11:21:24 +0800, Zhenzhong Duan wrote: > Imagine below scene, spidev is referenced after it's freed. > > spidev_release() spidev_remove() > ... > spin_lock_irq(&spidev->spi_lock); > spidev->spi = NULL; > spin_unlock_irq(&spidev->spi_lock); > mutex_lock(&device_list_lock); > dofree = (spidev->spi == NULL); > if (dofree) > kfree(spidev); > mutex_unlock(&device_list_lock); > mutex_lock(&device_list_lock); > list_del(&spidev->device_entry); > device_destroy(spidev_class, spidev->devt); > clear_bit(MINOR(spidev->devt), minors); > if (spidev->users == 0) > kfree(spidev); > mutex_unlock(&device_list_lock); > > [...] Applied to https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next Thanks! [1/2] spi: spidev: fix a race between spidev_release and spidev_remove commit: abd42781c3d2155868821f1b947ae45bbc33330d [2/2] spi: spidev: fix a potential use-after-free in spidev_release() commit: 06096cc6c5a84ced929634b0d79376b94c65a4bd All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index d753df7..f74ea26 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -787,13 +787,13 @@ static int spidev_remove(struct spi_device *spi) { struct spidev_data *spidev = spi_get_drvdata(spi); + /* prevent new opens */ + mutex_lock(&device_list_lock); /* make sure ops on existing fds can abort cleanly */ spin_lock_irq(&spidev->spi_lock); spidev->spi = NULL; spin_unlock_irq(&spidev->spi_lock); - /* prevent new opens */ - mutex_lock(&device_list_lock); list_del(&spidev->device_entry); device_destroy(spidev_class, spidev->devt); clear_bit(MINOR(spidev->devt), minors);
Imagine below scene, spidev is referenced after it's freed. spidev_release() spidev_remove() ... spin_lock_irq(&spidev->spi_lock); spidev->spi = NULL; spin_unlock_irq(&spidev->spi_lock); mutex_lock(&device_list_lock); dofree = (spidev->spi == NULL); if (dofree) kfree(spidev); mutex_unlock(&device_list_lock); mutex_lock(&device_list_lock); list_del(&spidev->device_entry); device_destroy(spidev_class, spidev->devt); clear_bit(MINOR(spidev->devt), minors); if (spidev->users == 0) kfree(spidev); mutex_unlock(&device_list_lock); Fix it by resetting spidev->spi in device_list_lock's protection. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@gmail.com> --- drivers/spi/spidev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)