diff mbox series

[1/1] spi: spi-fsl-dspi: Fix crash when not using GPIO chip select

Message ID 20241023203032.1388491-1-Frank.Li@nxp.com (mailing list archive)
State Accepted
Commit 25f00a13dccf8e45441265768de46c8bf58e08f6
Headers show
Series [1/1] spi: spi-fsl-dspi: Fix crash when not using GPIO chip select | expand

Commit Message

Frank Li Oct. 23, 2024, 8:30 p.m. UTC
Add check for the return value of spi_get_csgpiod() to avoid passing a NULL
pointer to gpiod_direction_output(), preventing a crash when GPIO chip
select is not used.

Fix below crash:
[    4.251960] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[    4.260762] Mem abort info:
[    4.263556]   ESR = 0x0000000096000004
[    4.267308]   EC = 0x25: DABT (current EL), IL = 32 bits
[    4.272624]   SET = 0, FnV = 0
[    4.275681]   EA = 0, S1PTW = 0
[    4.278822]   FSC = 0x04: level 0 translation fault
[    4.283704] Data abort info:
[    4.286583]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[    4.292074]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[    4.297130]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[    4.302445] [0000000000000000] user address but active_mm is swapper
[    4.308805] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
[    4.315072] Modules linked in:
[    4.318124] CPU: 2 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.0-rc4-next-20241023-00008-ga20ec42c5fc1 #359
[    4.328130] Hardware name: LS1046A QDS Board (DT)
[    4.332832] pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[    4.339794] pc : gpiod_direction_output+0x34/0x5c
[    4.344505] lr : gpiod_direction_output+0x18/0x5c
[    4.349208] sp : ffff80008003b8f0
[    4.352517] x29: ffff80008003b8f0 x28: 0000000000000000 x27: ffffc96bcc7e9068
[    4.359659] x26: ffffc96bcc6e00b0 x25: ffffc96bcc598398 x24: ffff447400132810
[    4.366800] x23: 0000000000000000 x22: 0000000011e1a300 x21: 0000000000020002
[    4.373940] x20: 0000000000000000 x19: 0000000000000000 x18: ffffffffffffffff
[    4.381081] x17: ffff44740016e600 x16: 0000000500000003 x15: 0000000000000007
[    4.388221] x14: 0000000000989680 x13: 0000000000020000 x12: 000000000000001e
[    4.395362] x11: 0044b82fa09b5a53 x10: 0000000000000019 x9 : 0000000000000008
[    4.402502] x8 : 0000000000000002 x7 : 0000000000000007 x6 : 0000000000000000
[    4.409641] x5 : 0000000000000200 x4 : 0000000002000000 x3 : 0000000000000000
[    4.416781] x2 : 0000000000022202 x1 : 0000000000000000 x0 : 0000000000000000
[    4.423921] Call trace:
[    4.426362]  gpiod_direction_output+0x34/0x5c (P)
[    4.431067]  gpiod_direction_output+0x18/0x5c (L)
[    4.435771]  dspi_setup+0x220/0x334

Fixes: 9e264f3f85a5 ("spi: Replace all spi->chip_select and spi->cs_gpiod references with function call")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/spi/spi-fsl-dspi.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Comments

Vladimir Oltean Oct. 24, 2024, 7:52 a.m. UTC | #1
Hi Frank,

On Wed, Oct 23, 2024 at 04:30:32PM -0400, Frank Li wrote:
> Add check for the return value of spi_get_csgpiod() to avoid passing a NULL
> pointer to gpiod_direction_output(), preventing a crash when GPIO chip
> select is not used.
> 
> Fix below crash:
> [    4.251960] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
> [    4.260762] Mem abort info:
> [    4.263556]   ESR = 0x0000000096000004
> [    4.267308]   EC = 0x25: DABT (current EL), IL = 32 bits
> [    4.272624]   SET = 0, FnV = 0
> [    4.275681]   EA = 0, S1PTW = 0
> [    4.278822]   FSC = 0x04: level 0 translation fault
> [    4.283704] Data abort info:
> [    4.286583]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> [    4.292074]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> [    4.297130]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [    4.302445] [0000000000000000] user address but active_mm is swapper
> [    4.308805] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
> [    4.315072] Modules linked in:
> [    4.318124] CPU: 2 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.0-rc4-next-20241023-00008-ga20ec42c5fc1 #359
> [    4.328130] Hardware name: LS1046A QDS Board (DT)
> [    4.332832] pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [    4.339794] pc : gpiod_direction_output+0x34/0x5c
> [    4.344505] lr : gpiod_direction_output+0x18/0x5c
> [    4.349208] sp : ffff80008003b8f0
> [    4.352517] x29: ffff80008003b8f0 x28: 0000000000000000 x27: ffffc96bcc7e9068
> [    4.359659] x26: ffffc96bcc6e00b0 x25: ffffc96bcc598398 x24: ffff447400132810
> [    4.366800] x23: 0000000000000000 x22: 0000000011e1a300 x21: 0000000000020002
> [    4.373940] x20: 0000000000000000 x19: 0000000000000000 x18: ffffffffffffffff
> [    4.381081] x17: ffff44740016e600 x16: 0000000500000003 x15: 0000000000000007
> [    4.388221] x14: 0000000000989680 x13: 0000000000020000 x12: 000000000000001e
> [    4.395362] x11: 0044b82fa09b5a53 x10: 0000000000000019 x9 : 0000000000000008
> [    4.402502] x8 : 0000000000000002 x7 : 0000000000000007 x6 : 0000000000000000
> [    4.409641] x5 : 0000000000000200 x4 : 0000000002000000 x3 : 0000000000000000
> [    4.416781] x2 : 0000000000022202 x1 : 0000000000000000 x0 : 0000000000000000
> [    4.423921] Call trace:
> [    4.426362]  gpiod_direction_output+0x34/0x5c (P)
> [    4.431067]  gpiod_direction_output+0x18/0x5c (L)
> [    4.435771]  dspi_setup+0x220/0x334
> 
> Fixes: 9e264f3f85a5 ("spi: Replace all spi->chip_select and spi->cs_gpiod references with function call")
> Cc: stable@vger.kernel.org
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---

Sadly I do not reproduce this NULL pointer dereference. I also know from
hearsay that the GPIO consumer API is more or less NULL-tolerant. Could
you "make drivers/gpio/gpiolib.lst" and see what's at offsets 0x18 and
0x34 into gpiod_direction_output()? The first thing in that function is
the VALIDATE_DESC() macro, which does:

static int validate_desc(const struct gpio_desc *desc, const char *func)
{
	if (!desc)
		return 0;

	if (IS_ERR(desc)) {
		pr_warn("%s: invalid GPIO (errorpointer)\n", func);
		return PTR_ERR(desc);
	}

	return 1;
}

#define VALIDATE_DESC(desc) do { \
	int __valid = validate_desc(desc, __func__); \
	if (__valid <= 0) \
		return __valid; \
	} while (0)
Mark Brown Oct. 25, 2024, 11:40 a.m. UTC | #2
On Wed, 23 Oct 2024 16:30:32 -0400, Frank Li wrote:
> Add check for the return value of spi_get_csgpiod() to avoid passing a NULL
> pointer to gpiod_direction_output(), preventing a crash when GPIO chip
> select is not used.
> 
> Fix below crash:
> [    4.251960] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
> [    4.260762] Mem abort info:
> [    4.263556]   ESR = 0x0000000096000004
> [    4.267308]   EC = 0x25: DABT (current EL), IL = 32 bits
> [    4.272624]   SET = 0, FnV = 0
> [    4.275681]   EA = 0, S1PTW = 0
> [    4.278822]   FSC = 0x04: level 0 translation fault
> [    4.283704] Data abort info:
> [    4.286583]   ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
> [    4.292074]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
> [    4.297130]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
> [    4.302445] [0000000000000000] user address but active_mm is swapper
> [    4.308805] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
> [    4.315072] Modules linked in:
> [    4.318124] CPU: 2 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.12.0-rc4-next-20241023-00008-ga20ec42c5fc1 #359
> [    4.328130] Hardware name: LS1046A QDS Board (DT)
> [    4.332832] pstate: 40000005 (nZcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [    4.339794] pc : gpiod_direction_output+0x34/0x5c
> [    4.344505] lr : gpiod_direction_output+0x18/0x5c
> [    4.349208] sp : ffff80008003b8f0
> [    4.352517] x29: ffff80008003b8f0 x28: 0000000000000000 x27: ffffc96bcc7e9068
> [    4.359659] x26: ffffc96bcc6e00b0 x25: ffffc96bcc598398 x24: ffff447400132810
> [    4.366800] x23: 0000000000000000 x22: 0000000011e1a300 x21: 0000000000020002
> [    4.373940] x20: 0000000000000000 x19: 0000000000000000 x18: ffffffffffffffff
> [    4.381081] x17: ffff44740016e600 x16: 0000000500000003 x15: 0000000000000007
> [    4.388221] x14: 0000000000989680 x13: 0000000000020000 x12: 000000000000001e
> [    4.395362] x11: 0044b82fa09b5a53 x10: 0000000000000019 x9 : 0000000000000008
> [    4.402502] x8 : 0000000000000002 x7 : 0000000000000007 x6 : 0000000000000000
> [    4.409641] x5 : 0000000000000200 x4 : 0000000002000000 x3 : 0000000000000000
> [    4.416781] x2 : 0000000000022202 x1 : 0000000000000000 x0 : 0000000000000000
> [    4.423921] Call trace:
> [    4.426362]  gpiod_direction_output+0x34/0x5c (P)
> [    4.431067]  gpiod_direction_output+0x18/0x5c (L)
> [    4.435771]  dspi_setup+0x220/0x334
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: spi-fsl-dspi: Fix crash when not using GPIO chip select
      commit: 25f00a13dccf8e45441265768de46c8bf58e08f6

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 mbox series

Patch

diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index b52950a0f5f92..067c954cb6ea0 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1003,6 +1003,7 @@  static int dspi_setup(struct spi_device *spi)
 	u32 cs_sck_delay = 0, sck_cs_delay = 0;
 	struct fsl_dspi_platform_data *pdata;
 	unsigned char pasc = 0, asc = 0;
+	struct gpio_desc *gpio_cs;
 	struct chip_data *chip;
 	unsigned long clkrate;
 	bool cs = true;
@@ -1077,7 +1078,10 @@  static int dspi_setup(struct spi_device *spi)
 			chip->ctar_val |= SPI_CTAR_LSBFE;
 	}
 
-	gpiod_direction_output(spi_get_csgpiod(spi, 0), false);
+	gpio_cs = spi_get_csgpiod(spi, 0);
+	if (gpio_cs)
+		gpiod_direction_output(gpio_cs, false);
+
 	dspi_deassert_cs(spi, &cs);
 
 	spi_set_ctldata(spi, chip);