mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
spi: spidev: fix a potential use-after-free in spidev_release()
If an spi device is unbounded from the driver before the release process, there will be an NULL pointer reference when it's referenced in spi_slave_abort(). Fix it by checking it's already freed before reference. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@gmail.com> Link: https://lore.kernel.org/r/20200618032125.4650-2-zhenzhong.duan@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
abd42781c3
commit
06096cc6c5
@ -609,15 +609,20 @@ err_find_dev:
|
|||||||
static int spidev_release(struct inode *inode, struct file *filp)
|
static int spidev_release(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
struct spidev_data *spidev;
|
struct spidev_data *spidev;
|
||||||
|
int dofree;
|
||||||
|
|
||||||
mutex_lock(&device_list_lock);
|
mutex_lock(&device_list_lock);
|
||||||
spidev = filp->private_data;
|
spidev = filp->private_data;
|
||||||
filp->private_data = NULL;
|
filp->private_data = NULL;
|
||||||
|
|
||||||
|
spin_lock_irq(&spidev->spi_lock);
|
||||||
|
/* ... after we unbound from the underlying device? */
|
||||||
|
dofree = (spidev->spi == NULL);
|
||||||
|
spin_unlock_irq(&spidev->spi_lock);
|
||||||
|
|
||||||
/* last close? */
|
/* last close? */
|
||||||
spidev->users--;
|
spidev->users--;
|
||||||
if (!spidev->users) {
|
if (!spidev->users) {
|
||||||
int dofree;
|
|
||||||
|
|
||||||
kfree(spidev->tx_buffer);
|
kfree(spidev->tx_buffer);
|
||||||
spidev->tx_buffer = NULL;
|
spidev->tx_buffer = NULL;
|
||||||
@ -625,19 +630,14 @@ static int spidev_release(struct inode *inode, struct file *filp)
|
|||||||
kfree(spidev->rx_buffer);
|
kfree(spidev->rx_buffer);
|
||||||
spidev->rx_buffer = NULL;
|
spidev->rx_buffer = NULL;
|
||||||
|
|
||||||
spin_lock_irq(&spidev->spi_lock);
|
|
||||||
if (spidev->spi)
|
|
||||||
spidev->speed_hz = spidev->spi->max_speed_hz;
|
|
||||||
|
|
||||||
/* ... after we unbound from the underlying device? */
|
|
||||||
dofree = (spidev->spi == NULL);
|
|
||||||
spin_unlock_irq(&spidev->spi_lock);
|
|
||||||
|
|
||||||
if (dofree)
|
if (dofree)
|
||||||
kfree(spidev);
|
kfree(spidev);
|
||||||
|
else
|
||||||
|
spidev->speed_hz = spidev->spi->max_speed_hz;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_SPI_SLAVE
|
#ifdef CONFIG_SPI_SLAVE
|
||||||
spi_slave_abort(spidev->spi);
|
if (!dofree)
|
||||||
|
spi_slave_abort(spidev->spi);
|
||||||
#endif
|
#endif
|
||||||
mutex_unlock(&device_list_lock);
|
mutex_unlock(&device_list_lock);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user