From: DENG Qingfang Date: Thu, 19 Sep 2019 09:44:48 +0000 (+0200) Subject: kernel: 4.19: fix crash when setting up spi-gpio X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=1979af10ca9286b04f601bc7f00a37cdc8f7c4f1;p=openwrt%2Fstaging%2Fxback.git kernel: 4.19: fix crash when setting up spi-gpio If an spi-gpio was specified with num-chipselects = <0> in dts, kernel will crash: Unable to handle kernel paging request at virtual address 32697073 pgd = (ptrval) [32697073] *pgd=00000000 Internal error: Oops: 5 [# 1] SMP ARM Modules linked in: CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.72 #0 Hardware name: Generic DT based system PC is at validate_desc+0x28/0x80 LR is at gpiod_direction_output+0x14/0x128 ... [] (validate_desc) from [] (gpiod_direction_output+0x14/0x128) [] (gpiod_direction_output) from [] (spi_gpio_setup+0x58/0x64) [] (spi_gpio_setup) from [] (spi_setup+0x12c/0x148) [] (spi_setup) from [] (spi_add_device+0xbc/0x12c) [] (spi_add_device) from [] (spi_register_controller+0x838/0x924) [] (spi_register_controller) from [] (spi_bitbang_start+0x108/0x120) [] (spi_bitbang_start) from [] (spi_gpio_probe+0x314/0x338) [] (spi_gpio_probe) from [] (platform_drv_probe+0x34/0x70) The cause is spi_gpio_setup() did not check if the spi-gpio has chipselect pins before setting their direction and results in derefing an invalid pointer. The bug is spotted in kernel 4.19.72 and does not occur in 4.14. There is a similar fix upstream in kernel 5.2 in commit 249e2632dcd0 ("spi: gpio: Don't request CS GPIO in DT use-case"). Ref: https://patchwork.kernel.org/patch/11150619/ Signed-off-by: DENG Qingfang [use upstream patch, moved from hack to pending dir, commit facelift] Signed-off-by: Petr Štetiar --- diff --git a/target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch b/target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch new file mode 100644 index 0000000000..7c171745c2 --- /dev/null +++ b/target/linux/generic/pending-4.19/132-spi-spi-gpio-fix-crash-when-num-chipselects-is-0.patch @@ -0,0 +1,66 @@ +From 0f76408d8c1cb0979f4286dd23912e6e59784b35 Mon Sep 17 00:00:00 2001 +From: DENG Qingfang +Date: Thu, 19 Sep 2019 11:42:55 +0200 +Subject: [PATCH] spi: spi-gpio: fix crash when num-chipselects is 0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If an spi-gpio was specified with num-chipselects = <0> in dts, kernel will crash: + +Unable to handle kernel paging request at virtual address 32697073 +pgd = (ptrval) +[32697073] *pgd=00000000 +Internal error: Oops: 5 [# 1] SMP ARM +Modules linked in: +CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.19.72 #0 +Hardware name: Generic DT based system +PC is at validate_desc+0x28/0x80 +LR is at gpiod_direction_output+0x14/0x128 +... +[] (validate_desc) from [] (gpiod_direction_output+0x14/0x128) +[] (gpiod_direction_output) from [] (spi_gpio_setup+0x58/0x64) +[] (spi_gpio_setup) from [] (spi_setup+0x12c/0x148) +[] (spi_setup) from [] (spi_add_device+0xbc/0x12c) +[] (spi_add_device) from [] (spi_register_controller+0x838/0x924) +[] (spi_register_controller) from [] (spi_bitbang_start+0x108/0x120) +[] (spi_bitbang_start) from [] (spi_gpio_probe+0x314/0x338) +[] (spi_gpio_probe) from [] (platform_drv_probe+0x34/0x70) + +The cause is spi_gpio_setup() did not check if the spi-gpio has chipselect pins +before setting their direction and results in derefing an invalid pointer. + +The bug is spotted in kernel 4.19.72 on OpenWrt, and does not occur in 4.14. + +There is a similar fix upstream 249e2632dcd0509b8f8f296f5aabf4d48dfd6da8. + +Ref: https://patchwork.kernel.org/patch/11150619/ +Cc: Linus Walleij +Cc: stable@vger.kernel.org +Signed-off-by: DENG Qingfang +Signed-off-by: Petr Å tetiar +--- + drivers/spi/spi-gpio.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c +index 088772ebef9b..57d5b6dc0dd0 100644 +--- a/drivers/spi/spi-gpio.c ++++ b/drivers/spi/spi-gpio.c +@@ -242,10 +242,12 @@ static int spi_gpio_setup(struct spi_device *spi) + * The CS GPIOs have already been + * initialized from the descriptor lookup. + */ +- cs = spi_gpio->cs_gpios[spi->chip_select]; +- if (!spi->controller_state && cs) +- status = gpiod_direction_output(cs, +- !(spi->mode & SPI_CS_HIGH)); ++ if (spi_gpio->has_cs) { ++ cs = spi_gpio->cs_gpios[spi->chip_select]; ++ if (!spi->controller_state && cs) ++ status = gpiod_direction_output(cs, ++ !(spi->mode & SPI_CS_HIGH)); ++ } + + if (!status) + status = spi_bitbang_setup(spi);