]> git.baikalelectronics.ru Git - kernel.git/commitdiff
can: gs_usb: gs_can_open(): initialize time counter before starting device
authorMarc Kleine-Budde <mkl@pengutronix.de>
Tue, 20 Sep 2022 09:46:12 +0000 (11:46 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 23 Sep 2022 11:55:00 +0000 (13:55 +0200)
On busy networks the CAN controller might receive CAN frames directly
after starting it but before the timecounter is setup. This will lead
to NULL pointer deref while converting the converting the CAN frame's
timestamp with the timecounter.

Close the race window by setting up the timecounter before starting
the CAN controller.

Fixes: c351fac8f5e8 ("can: gs_usb: add RX and TX hardware timestamp support")
Link: https://lore.kernel.org/all/20220921081329.385509-1-mkl@pengutronix.de
Cc: John Whittington <git@jbrengineering.co.uk
Tested-by: John Whittington <git@jbrengineering.co.uk>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/usb/gs_usb.c

index 9a8a7f1b200214f3559b806cfd5dc5012c90ee55..aa619dfc3ff2ab8d713b7f15a89b137553ec1c85 100644 (file)
@@ -972,6 +972,10 @@ static int gs_can_open(struct net_device *netdev)
        if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
                flags |= GS_CAN_MODE_HW_TIMESTAMP;
 
+       /* start polling timestamp */
+       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+               gs_usb_timestamp_init(dev);
+
        /* finally start device */
        dev->can.state = CAN_STATE_ERROR_ACTIVE;
        dm->mode = cpu_to_le32(GS_CAN_MODE_START);
@@ -985,16 +989,14 @@ static int gs_can_open(struct net_device *netdev)
        if (rc < 0) {
                netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
                kfree(dm);
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_stop(dev);
                dev->can.state = CAN_STATE_STOPPED;
                return rc;
        }
 
        kfree(dm);
 
-       /* start polling timestamp */
-       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
-               gs_usb_timestamp_init(dev);
-
        parent->active_channels++;
        if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
                netif_start_queue(netdev);