serial: max310x: Fix invalid memory access during GPIO init
authorJan Kundrát <jan.kundrat@cesnet.cz>
Fri, 8 Dec 2017 19:36:29 +0000 (20:36 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 Dec 2017 19:29:59 +0000 (20:29 +0100)
The `max310x_spi_probe` function attempted to setup the GPIO bits before
the corresponding structs for each serial port were initialized. If the
DTS file specified a GPIO hog, this led to a crash because the GPIO
stack ended up calling `max310x_gpio_direction_output` which referenced
uninitialized memory:

 [<c04598c0>] (max310x_gpio_direction_output) from [<c03f5a2c>] (_gpiod_direction_output_raw+0x94/0x2d4)
 [<c03f5a2c>] (_gpiod_direction_output_raw) from [<c03f991c>] (gpiod_hog+0x6c/0x154)
 [<c03f991c>] (gpiod_hog) from [<c03fa2d8>] (of_gpiochip_add+0x28c/0x444)
 [<c03fa2d8>] (of_gpiochip_add) from [<c03f6b2c>] (gpiochip_add_data+0x4f8/0x760)
 [<c03f6b2c>] (gpiochip_add_data) from [<c03f6dd4>] (devm_gpiochip_add_data+0x40/0x7c)
 [<c03f6dd4>] (devm_gpiochip_add_data) from [<c0459fec>] (max310x_spi_probe+0x530/0x894)
 [<c0459fec>] (max310x_spi_probe) from [<c0503294>] (spi_drv_probe+0x7c/0xac)
 [<c0503294>] (spi_drv_probe) from [<c046628c>] (driver_probe_device+0x234/0x2e8)
 [<c046628c>] (driver_probe_device) from [<c0464890>] (bus_for_each_drv+0x60/0x94)
 [<c0464890>] (bus_for_each_drv) from [<c0465f78>] (__device_attach+0xb0/0x114)
 [<c0465f78>] (__device_attach) from [<c0465548>] (bus_probe_device+0x84/0x8c)
 [<c0465548>] (bus_probe_device) from [<c0463a00>] (device_add+0x3f4/0x580)
 [<c0463a00>] (device_add) from [<c0504164>] (spi_add_device+0x9c/0x134)
 [<c0504164>] (spi_add_device) from [<c0504c18>] (spi_register_controller+0x484/0x910)
 [<c0504c18>] (spi_register_controller) from [<c0506ee0>] (orion_spi_probe+0x2f4/0x3b4)
 [<c0506ee0>] (orion_spi_probe) from [<c0467dac>] (platform_drv_probe+0x50/0xb0)
 [<c0467dac>] (platform_drv_probe) from [<c046628c>] (driver_probe_device+0x234/0x2e8)
 [<c046628c>] (driver_probe_device) from [<c04663f8>] (__driver_attach+0xb8/0xbc)
 [<c04663f8>] (__driver_attach) from [<c04647e8>] (bus_for_each_dev+0x68/0x9c)
 [<c04647e8>] (bus_for_each_dev) from [<c046574c>] (bus_add_driver+0x104/0x210)
 [<c046574c>] (bus_add_driver) from [<c0466f14>] (driver_register+0x78/0xf4)
 [<c0466f14>] (driver_register) from [<c0101bdc>] (do_one_initcall+0x44/0x168)
 [<c0101bdc>] (do_one_initcall) from [<c0a00dc0>] (kernel_init_freeable+0x140/0x1cc)
 [<c0a00dc0>] (kernel_init_freeable) from [<c078c590>] (kernel_init+0x8/0x108)
 [<c078c590>] (kernel_init) from [<c0107a50>] (ret_from_fork+0x14/0x24)

This can be easily fixed by moving the corresponding code below. And
because the UARTs are already there by the time we reach this point, the
`goto` needs changing so that more stuff is freed. (I have not tested
this error path.)

Signed-off-by: Jan Kundrát <jan.kundrat@cesnet.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/serial/max310x.c

index ecb6513a65053b2105c78ec300fc905bd424f850..8971828d1f21621d0d7939fc935561eeee96cf59 100644 (file)
@@ -1169,23 +1169,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
        uartclk = max310x_set_ref_clk(s, freq, xtal);
        dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
 
-#ifdef CONFIG_GPIOLIB
-       /* Setup GPIO cotroller */
-       s->gpio.owner           = THIS_MODULE;
-       s->gpio.parent          = dev;
-       s->gpio.label           = dev_name(dev);
-       s->gpio.direction_input = max310x_gpio_direction_input;
-       s->gpio.get             = max310x_gpio_get;
-       s->gpio.direction_output= max310x_gpio_direction_output;
-       s->gpio.set             = max310x_gpio_set;
-       s->gpio.base            = -1;
-       s->gpio.ngpio           = devtype->nr * 4;
-       s->gpio.can_sleep       = 1;
-       ret = devm_gpiochip_add_data(dev, &s->gpio, s);
-       if (ret)
-               goto out_clk;
-#endif
-
        mutex_init(&s->mutex);
 
        for (i = 0; i < devtype->nr; i++) {
@@ -1237,6 +1220,23 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
                devtype->power(&s->p[i].port, 0);
        }
 
+#ifdef CONFIG_GPIOLIB
+       /* Setup GPIO cotroller */
+       s->gpio.owner           = THIS_MODULE;
+       s->gpio.parent          = dev;
+       s->gpio.label           = dev_name(dev);
+       s->gpio.direction_input = max310x_gpio_direction_input;
+       s->gpio.get             = max310x_gpio_get;
+       s->gpio.direction_output= max310x_gpio_direction_output;
+       s->gpio.set             = max310x_gpio_set;
+       s->gpio.base            = -1;
+       s->gpio.ngpio           = devtype->nr * 4;
+       s->gpio.can_sleep       = 1;
+       ret = devm_gpiochip_add_data(dev, &s->gpio, s);
+       if (ret)
+               goto out_uart;
+#endif
+
        /* Setup interrupt */
        ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
                                        IRQF_ONESHOT | flags, dev_name(dev), s);