VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46083

CVE-2026-46083

Description

In the Linux kernel, the following vulnerability has been resolved:

spi: fix resource leaks on device setup failure

Make sure to call controller cleanup() if spi_setup() fails while registering a device to avoid leaking any resources allocated by setup().

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Linux kernel SPI subsystem has a resource leak when spi_setup() fails during device registration; call cleanup() to prevent leaks.

Vulnerability

In the Linux kernel SPI subsystem, a resource leak occurs when spi_setup() fails during device registration. The controller's cleanup() function is not called in the error path, leaking resources allocated by setup(). Affected versions are Linux kernels prior to the commit dbcead54b12468d9aa54c0e1f0042d838ec3b0ae [1].

Exploitation

An attacker must trigger a failure in spi_setup() while a SPI device is being registered. This could be achieved by providing invalid parameters via sysfs or device tree entries. No special privileges are required if the attacker can control SPI device configuration.

Impact

Successful exploitation leads to kernel memory and resource leaks, potentially causing denial of service through resource exhaustion. The severity depends on the resources allocated by the specific spi_setup() implementation.

Mitigation

The vulnerability is fixed in Linux kernel commit dbcead54b12468d9aa54c0e1f0042d838ec3b0ae [1]. Users should apply this patch or update to a kernel version that includes it. No workaround is available.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
db357034f7e0

spi: fix resource leaks on device setup failure

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJohan HovoldApr 10, 2026Fixed in 7.1-rc1via kernel-cna
1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index a0b2bd3b818650..3e434a9885bc3c 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_controller_idr);
     
     static void spidev_release(struct device *dev)
    @@ -743,7 +745,7 @@ static int __spi_add_device(struct spi_device *spi, struct spi_device *parent)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -4049,27 +4051,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -4154,7 +4136,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -4163,7 +4145,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4199,6 +4181,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
11baa8b24bcb

spi: fix resource leaks on device setup failure

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJohan HovoldApr 10, 2026Fixed in 6.18.27via kernel-cna
1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 03b5d9a6d1ffdf..ac4de4703a6f04 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_controller_idr);
     
     static void spidev_release(struct device *dev)
    @@ -729,7 +731,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3854,27 +3856,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -3959,7 +3941,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -3968,7 +3950,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4004,6 +3986,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
dbcead54b124

spi: fix resource leaks on device setup failure

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJohan HovoldApr 10, 2026Fixed in 7.0.4via kernel-cna
1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 91dd831d2d3b1a..2001757fe31c02 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_controller_idr);
     
     static void spidev_release(struct device *dev)
    @@ -729,7 +731,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3993,27 +3995,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -4098,7 +4080,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -4107,7 +4089,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4143,6 +4125,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
1e774294b2f9

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 60ff547dcf0ab7..5a6c2f5672ae96 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -42,6 +42,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_master_idr);
     
     static void spidev_release(struct device *dev)
    @@ -735,7 +737,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3879,27 +3881,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -3984,7 +3966,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -3993,7 +3975,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4030,6 +4012,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
a2c817c62943

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 216a9378f0d620..bb7e5e56f6dca6 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -42,6 +42,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_master_idr);
     
     static void spidev_release(struct device *dev)
    @@ -677,7 +679,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3734,27 +3736,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status = 0;
    @@ -3833,7 +3815,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -3842,7 +3824,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -3879,6 +3861,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
11baa8b24bcb

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 03b5d9a6d1ffdf..ac4de4703a6f04 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_controller_idr);
     
     static void spidev_release(struct device *dev)
    @@ -729,7 +731,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3854,27 +3856,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -3959,7 +3941,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -3968,7 +3950,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4004,6 +3986,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
db357034f7e0

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index a0b2bd3b818650..3e434a9885bc3c 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_controller_idr);
     
     static void spidev_release(struct device *dev)
    @@ -743,7 +745,7 @@ static int __spi_add_device(struct spi_device *spi, struct spi_device *parent)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -4049,27 +4051,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -4154,7 +4136,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -4163,7 +4145,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4199,6 +4181,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
dbcead54b124

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 91dd831d2d3b1a..2001757fe31c02 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_controller_idr);
     
     static void spidev_release(struct device *dev)
    @@ -729,7 +731,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3993,27 +3995,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -4098,7 +4080,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -4107,7 +4089,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4143,6 +4125,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
1e774294b2f9

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 60ff547dcf0ab7..5a6c2f5672ae96 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -42,6 +42,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_master_idr);
     
     static void spidev_release(struct device *dev)
    @@ -735,7 +737,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3879,27 +3881,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status;
    @@ -3984,7 +3966,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -3993,7 +3975,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -4030,6 +4012,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    
a2c817c62943

spi: fix resource leaks on device setup failure

1 file changed · +37 25
  • drivers/spi/spi.c+37 25 modified
    diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
    index 216a9378f0d620..bb7e5e56f6dca6 100644
    --- a/drivers/spi/spi.c
    +++ b/drivers/spi/spi.c
    @@ -42,6 +42,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_stop);
     
     #include "internals.h"
     
    +static int __spi_setup(struct spi_device *spi, bool initial_setup);
    +
     static DEFINE_IDR(spi_master_idr);
     
     static void spidev_release(struct device *dev)
    @@ -677,7 +679,7 @@ static int __spi_add_device(struct spi_device *spi)
     	 * normally rely on the device being setup.  Devices
     	 * using SPI_CS_HIGH can't coexist well otherwise...
     	 */
    -	status = spi_setup(spi);
    +	status = __spi_setup(spi, true);
     	if (status < 0) {
     		dev_err(dev, "can't setup %s, status %d\n",
     				dev_name(&spi->dev), status);
    @@ -3734,27 +3736,7 @@ static int spi_set_cs_timing(struct spi_device *spi)
     	return status;
     }
     
    -/**
    - * spi_setup - setup SPI mode and clock rate
    - * @spi: the device whose settings are being modified
    - * Context: can sleep, and no requests are queued to the device
    - *
    - * SPI protocol drivers may need to update the transfer mode if the
    - * device doesn't work with its default.  They may likewise need
    - * to update clock rates or word sizes from initial values.  This function
    - * changes those settings, and must be called from a context that can sleep.
    - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    - * effect the next time the device is selected and data is transferred to
    - * or from it.  When this function returns, the SPI device is deselected.
    - *
    - * Note that this call will fail if the protocol driver specifies an option
    - * that the underlying controller or its driver does not support.  For
    - * example, not all hardware supports wire transfers using nine bit words,
    - * LSB-first wire encoding, or active-high chipselects.
    - *
    - * Return: zero on success, else a negative error code.
    - */
    -int spi_setup(struct spi_device *spi)
    +static int __spi_setup(struct spi_device *spi, bool initial_setup)
     {
     	unsigned	bad_bits, ugly_bits;
     	int		status = 0;
    @@ -3833,7 +3815,7 @@ int spi_setup(struct spi_device *spi)
     	status = spi_set_cs_timing(spi);
     	if (status) {
     		mutex_unlock(&spi->controller->io_mutex);
    -		return status;
    +		goto err_cleanup;
     	}
     
     	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
    @@ -3842,7 +3824,7 @@ int spi_setup(struct spi_device *spi)
     			mutex_unlock(&spi->controller->io_mutex);
     			dev_err(&spi->controller->dev, "Failed to power device: %d\n",
     				status);
    -			return status;
    +			goto err_cleanup;
     		}
     
     		/*
    @@ -3879,6 +3861,37 @@ int spi_setup(struct spi_device *spi)
     			status);
     
     	return status;
    +
    +err_cleanup:
    +	if (initial_setup)
    +		spi_cleanup(spi);
    +
    +	return status;
    +}
    +
    +/**
    + * spi_setup - setup SPI mode and clock rate
    + * @spi: the device whose settings are being modified
    + * Context: can sleep, and no requests are queued to the device
    + *
    + * SPI protocol drivers may need to update the transfer mode if the
    + * device doesn't work with its default.  They may likewise need
    + * to update clock rates or word sizes from initial values.  This function
    + * changes those settings, and must be called from a context that can sleep.
    + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
    + * effect the next time the device is selected and data is transferred to
    + * or from it.  When this function returns, the SPI device is deselected.
    + *
    + * Note that this call will fail if the protocol driver specifies an option
    + * that the underlying controller or its driver does not support.  For
    + * example, not all hardware supports wire transfers using nine bit words,
    + * LSB-first wire encoding, or active-high chipselects.
    + *
    + * Return: zero on success, else a negative error code.
    + */
    +int spi_setup(struct spi_device *spi)
    +{
    +	return __spi_setup(spi, false);
     }
     EXPORT_SYMBOL_GPL(spi_setup);
     
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing cleanup call in the error path of __spi_add_device() when spi_setup() fails, causing resources allocated by setup() to be leaked."

Attack vector

An attacker who can trigger a failure in `spi_setup()` during SPI device registration — for example by providing an unsupported SPI mode, clock rate, or word size that the controller or its driver does not support — causes the kernel to leak resources allocated by the setup function. The failure path in `__spi_add_device()` (in `drivers/spi/spi.c`) previously returned the error without calling `spi_cleanup()`, leaving resources dangling. No special network path or authentication is required; the precondition is that a SPI device registration attempt fails after some setup resources have been allocated.

Affected code

The vulnerability is in the `__spi_add_device()` function in `drivers/spi/spi.c`. When `spi_setup()` (now `__spi_setup()`) fails during device registration, the error path did not call `spi_cleanup()`, leaking resources allocated by the setup routine [patch_id=2659848][patch_id=2659847][patch_id=2659849][patch_id=2659845][patch_id=2659846][patch_id=2659844][patch_id=2659843][patch_id=2659840][patch_id=2659842][patch_id=2659841].

What the fix does

The patch refactors `spi_setup()` into an internal `__spi_setup()` that accepts a `bool initial_setup` parameter. When `initial_setup` is true (i.e., called from `__spi_add_device()`), a new `err_cleanup` label calls `spi_cleanup(spi)` before returning on failure. The public `spi_setup()` wrapper calls `__spi_setup(spi, false)`, preserving existing behavior for protocol drivers that call `spi_setup()` after registration. This ensures that any resources allocated during the initial device setup are properly freed if setup fails, closing the leak [patch_id=2659848][patch_id=2659847][patch_id=2659849][patch_id=2659845][patch_id=2659846][patch_id=2659844][patch_id=2659843][patch_id=2659840][patch_id=2659842][patch_id=2659841].

Preconditions

  • inputA SPI device registration must fail after spi_setup() has allocated resources (e.g., due to unsupported mode/clock/word size).
  • inputThe attacker must be able to trigger such a registration failure, typically via kernel-level interaction with SPI device configuration.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.