mirror of
https://github.com/armbian/linux-cix.git
synced 2026-01-06 12:30:45 -08:00
can: dev: fix skb drop check
In commita6d190f8c7("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:a6d190f8c7("can: skb: drop tx skb if in listen only mode") Reported-by: Dariusz Stojaczyk <Dariusz.Stojaczyk@opensynergy.com> Cc: Vincent Mailhol <mailhol.vincent@wanadoo.fr> Cc: Max Staudt <max@enpas.org> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> Acked-by: Vincent 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: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
committed by
Marc Kleine-Budde
parent
3eb3d283e8
commit
ae64438be1
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#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)
|
||||
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
|
||||
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
||||
switch (ntohs(skb->protocol)) {
|
||||
case ETH_P_CAN:
|
||||
if (!can_is_can_skb(skb))
|
||||
@@ -359,13 +356,8 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
|
||||
goto inval_skb;
|
||||
}
|
||||
|
||||
if (!can_skb_headroom_valid(dev, skb)) {
|
||||
if (!can_skb_headroom_valid(dev, skb))
|
||||
goto inval_skb;
|
||||
} else if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
|
||||
netdev_info_once(dev,
|
||||
"interface in listen only mode, dropping skb\n");
|
||||
goto inval_skb;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
||||
@@ -742,7 +742,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
|
||||
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16);
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
@@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
|
||||
unsigned long flags;
|
||||
u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* Trying to transmit in silent mode will generate error interrupts, but
|
||||
|
||||
@@ -860,7 +860,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb,
|
||||
u32 txst, txid, txdlc;
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* Check if the TX buffer is full */
|
||||
|
||||
@@ -1693,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
void __iomem *desc_addr;
|
||||
unsigned long flags;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
spin_lock_irqsave(&mod->lock, flags);
|
||||
|
||||
@@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
|
||||
int nwords;
|
||||
u8 count;
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
|
||||
|
||||
@@ -1721,7 +1721,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
|
||||
{
|
||||
struct m_can_classdev *cdev = netdev_priv(dev);
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (cdev->is_peripheral) {
|
||||
|
||||
@@ -191,7 +191,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
int i, rtr, buf_id;
|
||||
u32 can_id;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
out_8(®s->cantier, 0);
|
||||
|
||||
@@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
int i;
|
||||
u32 id2;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
tx_obj_no = priv->tx_obj;
|
||||
|
||||
@@ -651,7 +651,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
|
||||
int room_left;
|
||||
u8 len;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
msg_size = ALIGN(sizeof(*msg) + cf->len, 4);
|
||||
|
||||
@@ -590,7 +590,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
|
||||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
u32 data, i;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
|
||||
|
||||
@@ -1481,7 +1481,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
|
||||
unsigned long flags;
|
||||
u32 ch = priv->channel;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (cf->can_id & CAN_EFF_FLAG) {
|
||||
|
||||
@@ -291,7 +291,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
|
||||
u8 cmd_reg_val = 0x00;
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
||||
@@ -594,7 +594,7 @@ static netdev_tx_t slcan_netdev_xmit(struct sk_buff *skb,
|
||||
{
|
||||
struct slcan *sl = netdev_priv(dev);
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
spin_lock(&sl->lock);
|
||||
|
||||
@@ -60,7 +60,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
uint8_t buf[DPRAM_TX_SIZE];
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
spin_lock(&card->spin);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user