Skip to content

Commit ae64438

Browse files
hartkoppmarckleinebudde
authored andcommitted
can: dev: fix skb drop check
In commit a6d190f ("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: a6d190f ("can: skb: drop tx skb if in listen only mode") Reported-by: Dariusz Stojaczyk <[email protected]> Cc: Vincent Mailhol <[email protected]> Cc: Max Staudt <[email protected]> Signed-off-by: Oliver Hartkopp <[email protected]> Acked-by: Vincent Mailhol <[email protected]> Link: https://lore.kernel.org/all/[email protected] Cc: [email protected] # 6.0.x [mkl: patch pch_can, too] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 3eb3d28 commit ae64438

36 files changed

+51
-43
lines changed

drivers/net/can/at91_can.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
452452
unsigned int mb, prio;
453453
u32 reg_mid, reg_mcr;
454454

455-
if (can_dropped_invalid_skb(dev, skb))
455+
if (can_dev_dropped_skb(dev, skb))
456456
return NETDEV_TX_OK;
457457

458458
mb = get_tx_next_mb(priv);

drivers/net/can/c_can/c_can_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
457457
struct c_can_tx_ring *tx_ring = &priv->tx;
458458
u32 idx, obj, cmd = IF_COMM_TX;
459459

460-
if (can_dropped_invalid_skb(dev, skb))
460+
if (can_dev_dropped_skb(dev, skb))
461461
return NETDEV_TX_OK;
462462

463463
if (c_can_tx_busy(priv, tx_ring))

drivers/net/can/can327.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb,
813813
struct can327 *elm = netdev_priv(dev);
814814
struct can_frame *frame = (struct can_frame *)skb->data;
815815

816-
if (can_dropped_invalid_skb(dev, skb))
816+
if (can_dev_dropped_skb(dev, skb))
817817
return NETDEV_TX_OK;
818818

819819
/* We shouldn't get here after a hardware fault:

drivers/net/can/cc770/cc770.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
429429
struct cc770_priv *priv = netdev_priv(dev);
430430
unsigned int mo = obj2msgobj(CC770_OBJ_TX);
431431

432-
if (can_dropped_invalid_skb(dev, skb))
432+
if (can_dev_dropped_skb(dev, skb))
433433
return NETDEV_TX_OK;
434434

435435
netif_stop_queue(dev);

drivers/net/can/ctucanfd/ctucanfd_base.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ static netdev_tx_t ctucan_start_xmit(struct sk_buff *skb, struct net_device *nde
600600
bool ok;
601601
unsigned long flags;
602602

603-
if (can_dropped_invalid_skb(ndev, skb))
603+
if (can_dev_dropped_skb(ndev, skb))
604604
return NETDEV_TX_OK;
605605

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

drivers/net/can/dev/skb.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66

77
#include <linux/can/dev.h>
8-
#include <linux/can/netlink.h>
98
#include <linux/module.h>
109

1110
#define MOD_DESC "CAN device driver interface"
@@ -337,8 +336,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
337336
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
338337
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
339338
{
340-
struct can_priv *priv = netdev_priv(dev);
341-
342339
switch (ntohs(skb->protocol)) {
343340
case ETH_P_CAN:
344341
if (!can_is_can_skb(skb))
@@ -359,13 +356,8 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
359356
goto inval_skb;
360357
}
361358

362-
if (!can_skb_headroom_valid(dev, skb)) {
359+
if (!can_skb_headroom_valid(dev, skb))
363360
goto inval_skb;
364-
} else if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
365-
netdev_info_once(dev,
366-
"interface in listen only mode, dropping skb\n");
367-
goto inval_skb;
368-
}
369361

370362
return false;
371363

drivers/net/can/flexcan/flexcan-core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
742742
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16);
743743
int i;
744744

745-
if (can_dropped_invalid_skb(dev, skb))
745+
if (can_dev_dropped_skb(dev, skb))
746746
return NETDEV_TX_OK;
747747

748748
netif_stop_queue(dev);

drivers/net/can/grcan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
13451345
unsigned long flags;
13461346
u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
13471347

1348-
if (can_dropped_invalid_skb(dev, skb))
1348+
if (can_dev_dropped_skb(dev, skb))
13491349
return NETDEV_TX_OK;
13501350

13511351
/* Trying to transmit in silent mode will generate error interrupts, but

drivers/net/can/ifi_canfd/ifi_canfd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb,
860860
u32 txst, txid, txdlc;
861861
int i;
862862

863-
if (can_dropped_invalid_skb(ndev, skb))
863+
if (can_dev_dropped_skb(ndev, skb))
864864
return NETDEV_TX_OK;
865865

866866
/* Check if the TX buffer is full */

drivers/net/can/janz-ican3.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1693,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
16931693
void __iomem *desc_addr;
16941694
unsigned long flags;
16951695

1696-
if (can_dropped_invalid_skb(ndev, skb))
1696+
if (can_dev_dropped_skb(ndev, skb))
16971697
return NETDEV_TX_OK;
16981698

16991699
spin_lock_irqsave(&mod->lock, flags);

drivers/net/can/kvaser_pciefd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
772772
int nwords;
773773
u8 count;
774774

775-
if (can_dropped_invalid_skb(netdev, skb))
775+
if (can_dev_dropped_skb(netdev, skb))
776776
return NETDEV_TX_OK;
777777

778778
nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);

drivers/net/can/m_can/m_can.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
17211721
{
17221722
struct m_can_classdev *cdev = netdev_priv(dev);
17231723

1724-
if (can_dropped_invalid_skb(dev, skb))
1724+
if (can_dev_dropped_skb(dev, skb))
17251725
return NETDEV_TX_OK;
17261726

17271727
if (cdev->is_peripheral) {

drivers/net/can/mscan/mscan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
191191
int i, rtr, buf_id;
192192
u32 can_id;
193193

194-
if (can_dropped_invalid_skb(dev, skb))
194+
if (can_dev_dropped_skb(dev, skb))
195195
return NETDEV_TX_OK;
196196

197197
out_8(&regs->cantier, 0);

drivers/net/can/pch_can.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
882882
int i;
883883
u32 id2;
884884

885-
if (can_dropped_invalid_skb(ndev, skb))
885+
if (can_dev_dropped_skb(ndev, skb))
886886
return NETDEV_TX_OK;
887887

888888
tx_obj_no = priv->tx_obj;

drivers/net/can/peak_canfd/peak_canfd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
651651
int room_left;
652652
u8 len;
653653

654-
if (can_dropped_invalid_skb(ndev, skb))
654+
if (can_dev_dropped_skb(ndev, skb))
655655
return NETDEV_TX_OK;
656656

657657
msg_size = ALIGN(sizeof(*msg) + cf->len, 4);

drivers/net/can/rcar/rcar_can.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
590590
struct can_frame *cf = (struct can_frame *)skb->data;
591591
u32 data, i;
592592

593-
if (can_dropped_invalid_skb(ndev, skb))
593+
if (can_dev_dropped_skb(ndev, skb))
594594
return NETDEV_TX_OK;
595595

596596
if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */

drivers/net/can/rcar/rcar_canfd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
14811481
unsigned long flags;
14821482
u32 ch = priv->channel;
14831483

1484-
if (can_dropped_invalid_skb(ndev, skb))
1484+
if (can_dev_dropped_skb(ndev, skb))
14851485
return NETDEV_TX_OK;
14861486

14871487
if (cf->can_id & CAN_EFF_FLAG) {

drivers/net/can/sja1000/sja1000.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
291291
u8 cmd_reg_val = 0x00;
292292
int i;
293293

294-
if (can_dropped_invalid_skb(dev, skb))
294+
if (can_dev_dropped_skb(dev, skb))
295295
return NETDEV_TX_OK;
296296

297297
netif_stop_queue(dev);

drivers/net/can/slcan/slcan-core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ static netdev_tx_t slcan_netdev_xmit(struct sk_buff *skb,
594594
{
595595
struct slcan *sl = netdev_priv(dev);
596596

597-
if (can_dropped_invalid_skb(dev, skb))
597+
if (can_dev_dropped_skb(dev, skb))
598598
return NETDEV_TX_OK;
599599

600600
spin_lock(&sl->lock);

drivers/net/can/softing/softing_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
6060
struct can_frame *cf = (struct can_frame *)skb->data;
6161
uint8_t buf[DPRAM_TX_SIZE];
6262

63-
if (can_dropped_invalid_skb(dev, skb))
63+
if (can_dev_dropped_skb(dev, skb))
6464
return NETDEV_TX_OK;
6565

6666
spin_lock(&card->spin);

drivers/net/can/spi/hi311x.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
373373
return NETDEV_TX_BUSY;
374374
}
375375

376-
if (can_dropped_invalid_skb(net, skb))
376+
if (can_dev_dropped_skb(net, skb))
377377
return NETDEV_TX_OK;
378378

379379
netif_stop_queue(net);

drivers/net/can/spi/mcp251x.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
789789
return NETDEV_TX_BUSY;
790790
}
791791

792-
if (can_dropped_invalid_skb(net, skb))
792+
if (can_dev_dropped_skb(net, skb))
793793
return NETDEV_TX_OK;
794794

795795
netif_stop_queue(net);

drivers/net/can/spi/mcp251xfd/mcp251xfd-tx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
172172
u8 tx_head;
173173
int err;
174174

175-
if (can_dropped_invalid_skb(ndev, skb))
175+
if (can_dev_dropped_skb(ndev, skb))
176176
return NETDEV_TX_OK;
177177

178178
if (mcp251xfd_tx_busy(priv, tx_ring))

drivers/net/can/sun4i_can.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d
429429
canid_t id;
430430
int i;
431431

432-
if (can_dropped_invalid_skb(dev, skb))
432+
if (can_dev_dropped_skb(dev, skb))
433433
return NETDEV_TX_OK;
434434

435435
netif_stop_queue(dev);

drivers/net/can/ti_hecc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
470470
u32 mbxno, mbx_mask, data;
471471
unsigned long flags;
472472

473-
if (can_dropped_invalid_skb(ndev, skb))
473+
if (can_dev_dropped_skb(ndev, skb))
474474
return NETDEV_TX_OK;
475475

476476
mbxno = get_tx_head_mb(priv);

drivers/net/can/usb/ems_usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
747747
size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
748748
+ sizeof(struct cpc_can_msg);
749749

750-
if (can_dropped_invalid_skb(netdev, skb))
750+
if (can_dev_dropped_skb(netdev, skb))
751751
return NETDEV_TX_OK;
752752

753753
/* create a URB, and a buffer for it, and copy the data to the URB */

drivers/net/can/usb/esd_usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
725725
int ret = NETDEV_TX_OK;
726726
size_t size = sizeof(struct esd_usb_msg);
727727

728-
if (can_dropped_invalid_skb(netdev, skb))
728+
if (can_dev_dropped_skb(netdev, skb))
729729
return NETDEV_TX_OK;
730730

731731
/* create a URB, and a buffer for it, and copy the data to the URB */

drivers/net/can/usb/etas_es58x/es58x_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1913,7 +1913,7 @@ static netdev_tx_t es58x_start_xmit(struct sk_buff *skb,
19131913
unsigned int frame_len;
19141914
int ret;
19151915

1916-
if (can_dropped_invalid_skb(netdev, skb)) {
1916+
if (can_dev_dropped_skb(netdev, skb)) {
19171917
if (priv->tx_urb)
19181918
goto xmit_commit;
19191919
return NETDEV_TX_OK;

drivers/net/can/usb/gs_usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
723723
unsigned int idx;
724724
struct gs_tx_context *txc;
725725

726-
if (can_dropped_invalid_skb(netdev, skb))
726+
if (can_dev_dropped_skb(netdev, skb))
727727
return NETDEV_TX_OK;
728728

729729
/* find an empty context to keep track of transmission */

drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
570570
unsigned int i;
571571
unsigned long flags;
572572

573-
if (can_dropped_invalid_skb(netdev, skb))
573+
if (can_dev_dropped_skb(netdev, skb))
574574
return NETDEV_TX_OK;
575575

576576
urb = usb_alloc_urb(0, GFP_ATOMIC);

drivers/net/can/usb/mcba_usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
311311
.cmd_id = MBCA_CMD_TRANSMIT_MESSAGE_EV
312312
};
313313

314-
if (can_dropped_invalid_skb(netdev, skb))
314+
if (can_dev_dropped_skb(netdev, skb))
315315
return NETDEV_TX_OK;
316316

317317
ctx = mcba_usb_get_free_ctx(priv, cf);

drivers/net/can/usb/peak_usb/pcan_usb_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb,
351351
int i, err;
352352
size_t size = dev->adapter->tx_buffer_size;
353353

354-
if (can_dropped_invalid_skb(netdev, skb))
354+
if (can_dev_dropped_skb(netdev, skb))
355355
return NETDEV_TX_OK;
356356

357357
for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++)

drivers/net/can/usb/ucan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1120,7 +1120,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
11201120
struct can_frame *cf = (struct can_frame *)skb->data;
11211121

11221122
/* check skb */
1123-
if (can_dropped_invalid_skb(netdev, skb))
1123+
if (can_dev_dropped_skb(netdev, skb))
11241124
return NETDEV_TX_OK;
11251125

11261126
/* allocate a context and slow down tx path, if fifo state is low */

drivers/net/can/usb/usb_8dev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
602602
int i, err;
603603
size_t size = sizeof(struct usb_8dev_tx_msg);
604604

605-
if (can_dropped_invalid_skb(netdev, skb))
605+
if (can_dev_dropped_skb(netdev, skb))
606606
return NETDEV_TX_OK;
607607

608608
/* create a URB, and a buffer for it, and copy the data to the URB */

drivers/net/can/xilinx_can.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ static netdev_tx_t xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev)
743743
struct xcan_priv *priv = netdev_priv(ndev);
744744
int ret;
745745

746-
if (can_dropped_invalid_skb(ndev, skb))
746+
if (can_dev_dropped_skb(ndev, skb))
747747
return NETDEV_TX_OK;
748748

749749
if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES)

include/linux/can/dev.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,22 @@ static inline bool can_is_canxl_dev_mtu(unsigned int mtu)
152152
return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU);
153153
}
154154

155+
/* drop skb if it does not contain a valid CAN frame for sending */
156+
static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb)
157+
{
158+
struct can_priv *priv = netdev_priv(dev);
159+
160+
if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
161+
netdev_info_once(dev,
162+
"interface in listen only mode, dropping skb\n");
163+
kfree_skb(skb);
164+
dev->stats.tx_dropped++;
165+
return true;
166+
}
167+
168+
return can_dropped_invalid_skb(dev, skb);
169+
}
170+
155171
void can_setup(struct net_device *dev);
156172

157173
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,

0 commit comments

Comments
 (0)