Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95c5637d authored by Marc Kleine-Budde's avatar Marc Kleine-Budde Committed by Greg Kroah-Hartman
Browse files

can: gs_usb: gs_can_open(): fix race dev->can.state condition

[ Upstream commit 5440428b3da65408dba0241985acb7a05258b85e ]

The dev->can.state is set to CAN_STATE_ERROR_ACTIVE, after the device
has been started. On busy networks the CAN controller might receive
CAN frame between and go into an error state before the dev->can.state
is assigned.

Assign dev->can.state before starting the controller to close the race
window.

Fixes: d08e973a ("can: gs_usb: Added support for the GS_USB CAN devices")
Link: https://lore.kernel.org/all/20220920195216.232481-1-mkl@pengutronix.de


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 11ebf32f
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -678,6 +678,7 @@ static int gs_can_open(struct net_device *netdev)
		flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
		flags |= GS_CAN_MODE_TRIPLE_SAMPLE;


	/* finally start device */
	/* finally start device */
	dev->can.state = CAN_STATE_ERROR_ACTIVE;
	dm->mode = cpu_to_le32(GS_CAN_MODE_START);
	dm->mode = cpu_to_le32(GS_CAN_MODE_START);
	dm->flags = cpu_to_le32(flags);
	dm->flags = cpu_to_le32(flags);
	rc = usb_control_msg(interface_to_usbdev(dev->iface),
	rc = usb_control_msg(interface_to_usbdev(dev->iface),
@@ -694,13 +695,12 @@ static int gs_can_open(struct net_device *netdev)
	if (rc < 0) {
	if (rc < 0) {
		netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
		netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
		kfree(dm);
		kfree(dm);
		dev->can.state = CAN_STATE_STOPPED;
		return rc;
		return rc;
	}
	}


	kfree(dm);
	kfree(dm);


	dev->can.state = CAN_STATE_ERROR_ACTIVE;

	parent->active_channels++;
	parent->active_channels++;
	if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
	if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
		netif_start_queue(netdev);
		netif_start_queue(netdev);