Commit ae64438b authored by Oliver Hartkopp's avatar Oliver Hartkopp Committed by Marc Kleine-Budde
Browse files

can: dev: fix skb drop check



In commit a6d190f8 ("can: skb: drop tx skb if in listen only
mode") the priv->ctrlmode element is read even on virtual CAN
interfaces that do not create the struct can_priv at startup. This
out-of-bounds read may lead to CAN frame drops for virtual CAN
interfaces like vcan and vxcan.

This patch mainly reverts the original commit and adds a new helper
for CAN interface drivers that provide the required information in
struct can_priv.

Fixes: a6d190f8 ("can: skb: drop tx skb if in listen only mode")
Reported-by: default avatarDariusz Stojaczyk <Dariusz.Stojaczyk@opensynergy.com>
Cc: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Cc: Max Staudt <max@enpas.org>
Signed-off-by: default avatarOliver Hartkopp <socketcan@hartkopp.net>
Acked-by: default avatarVincent Mailhol <mailhol.vincent@wanadoo.fr>
Link: https://lore.kernel.org/all/20221102095431.36831-1-socketcan@hartkopp.net


Cc: stable@vger.kernel.org # 6.0.x
[mkl: patch pch_can, too]
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 3eb3d283
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
	unsigned int mb, prio;
	u32 reg_mid, reg_mcr;

	if (can_dropped_invalid_skb(dev, skb))
	if (can_dev_dropped_skb(dev, skb))
		return NETDEV_TX_OK;

	mb = get_tx_next_mb(priv);
+1 −1
Original line number Diff line number Diff line
@@ -457,7 +457,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
	struct c_can_tx_ring *tx_ring = &priv->tx;
	u32 idx, obj, cmd = IF_COMM_TX;

	if (can_dropped_invalid_skb(dev, skb))
	if (can_dev_dropped_skb(dev, skb))
		return NETDEV_TX_OK;

	if (c_can_tx_busy(priv, tx_ring))
+1 −1
Original line number Diff line number Diff line
@@ -813,7 +813,7 @@ static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb,
	struct can327 *elm = netdev_priv(dev);
	struct can_frame *frame = (struct can_frame *)skb->data;

	if (can_dropped_invalid_skb(dev, skb))
	if (can_dev_dropped_skb(dev, skb))
		return NETDEV_TX_OK;

	/* We shouldn't get here after a hardware fault:
+1 −1
Original line number Diff line number Diff line
@@ -429,7 +429,7 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
	struct cc770_priv *priv = netdev_priv(dev);
	unsigned int mo = obj2msgobj(CC770_OBJ_TX);

	if (can_dropped_invalid_skb(dev, skb))
	if (can_dev_dropped_skb(dev, skb))
		return NETDEV_TX_OK;

	netif_stop_queue(dev);
+1 −1
Original line number Diff line number Diff line
@@ -600,7 +600,7 @@ static netdev_tx_t ctucan_start_xmit(struct sk_buff *skb, struct net_device *nde
	bool ok;
	unsigned long flags;

	if (can_dropped_invalid_skb(ndev, skb))
	if (can_dev_dropped_skb(ndev, skb))
		return NETDEV_TX_OK;

	if (unlikely(!CTU_CAN_FD_TXTNF(priv))) {
Loading