]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.132/gpio-fix-crash-due-to-registration-race.patch
Linux 4.14.95
[thirdparty/kernel/stable-queue.git] / releases / 4.9.132 / gpio-fix-crash-due-to-registration-race.patch
CommitLineData
12eb7899
GKH
1From foo@baz Thu Oct 4 12:38:43 PDT 2018
2From: Vincent Whitchurch <vincent.whitchurch@axis.com>
3Date: Fri, 31 Aug 2018 09:04:18 +0200
4Subject: gpio: Fix crash due to registration race
5
6From: Vincent Whitchurch <vincent.whitchurch@axis.com>
7
8[ Upstream commit d49b48f088c323dbacae44dfbe56d9c985c8a2a1 ]
9
10gpiochip_add_data_with_key() adds the gpiochip to the gpio_devices list
11before of_gpiochip_add() is called, but it's only the latter which sets
12the ->of_xlate function pointer. gpiochip_find() can be called by
13someone else between these two actions, and it can find the chip and
14call of_gpiochip_match_node_and_xlate() which leads to the following
15crash due to a NULL ->of_xlate().
16
17 Unhandled prefetch abort: page domain fault (0x01b) at 0x00000000
18 Modules linked in: leds_gpio(+) gpio_generic(+)
19 CPU: 0 PID: 830 Comm: insmod Not tainted 4.18.0+ #43
20 Hardware name: ARM-Versatile Express
21 PC is at (null)
22 LR is at of_gpiochip_match_node_and_xlate+0x2c/0x38
23 Process insmod (pid: 830, stack limit = 0x(ptrval))
24 (of_gpiochip_match_node_and_xlate) from (gpiochip_find+0x48/0x84)
25 (gpiochip_find) from (of_get_named_gpiod_flags+0xa8/0x238)
26 (of_get_named_gpiod_flags) from (gpiod_get_from_of_node+0x2c/0xc8)
27 (gpiod_get_from_of_node) from (devm_fwnode_get_index_gpiod_from_child+0xb8/0x144)
28 (devm_fwnode_get_index_gpiod_from_child) from (gpio_led_probe+0x208/0x3c4 [leds_gpio])
29 (gpio_led_probe [leds_gpio]) from (platform_drv_probe+0x48/0x9c)
30 (platform_drv_probe) from (really_probe+0x1d0/0x3d4)
31 (really_probe) from (driver_probe_device+0x78/0x1c0)
32 (driver_probe_device) from (__driver_attach+0x120/0x13c)
33 (__driver_attach) from (bus_for_each_dev+0x68/0xb4)
34 (bus_for_each_dev) from (bus_add_driver+0x1a8/0x268)
35 (bus_add_driver) from (driver_register+0x78/0x10c)
36 (driver_register) from (do_one_initcall+0x54/0x1fc)
37 (do_one_initcall) from (do_init_module+0x64/0x1f4)
38 (do_init_module) from (load_module+0x2198/0x26ac)
39 (load_module) from (sys_finit_module+0xe0/0x110)
40 (sys_finit_module) from (ret_fast_syscall+0x0/0x54)
41
42One way to fix this would be to rework the hairy registration sequence
43in gpiochip_add_data_with_key(), but since I'd probably introduce a
44couple of new bugs if I attempted that, simply add a check for a
45non-NULL of_xlate function pointer in
46of_gpiochip_match_node_and_xlate(). This works since the driver looking
47for the gpio will simply fail to find the gpio and defer its probe and
48be reprobed when the driver which is registering the gpiochip has fully
49completed its probe.
50
51Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
52Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
53Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
54Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
55---
56 drivers/gpio/gpiolib-of.c | 1 +
57 1 file changed, 1 insertion(+)
58
59--- a/drivers/gpio/gpiolib-of.c
60+++ b/drivers/gpio/gpiolib-of.c
61@@ -31,6 +31,7 @@ static int of_gpiochip_match_node_and_xl
62 struct of_phandle_args *gpiospec = data;
63
64 return chip->gpiodev->dev.of_node == gpiospec->np &&
65+ chip->of_xlate &&
66 chip->of_xlate(chip, gpiospec, NULL) >= 0;
67 }
68