Merge patch series "can: skb: make echo skb freeing safe in any IRQ context"

Cunhao Lu <1579567540@qq.com> says:

can_put_echo_skb() and the CAN skb allocation helpers may release skbs in
hardware interrupt context or while hardware interrupts are disabled. This
series makes the affected public helper paths safe in either context and
fixes the invalid echo-index skb leak.

Link: https://patch.msgid.link/tencent_CD05F020BAFB2537F5D1F4CBB425588EA80A@qq.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
Marc Kleine-Budde 2026-09-28 13:01:30 +02:00
commit d3592ab8a1
3 changed files with 10 additions and 9 deletions

View File

@ -55,6 +55,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
__func__, idx, priv->echo_skb_max);
dev_kfree_skb_any(skb);
return -EINVAL;
}
@ -63,7 +64,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
(skb->protocol != htons(ETH_P_CAN) &&
skb->protocol != htons(ETH_P_CANFD) &&
skb->protocol != htons(ETH_P_CANXL))) {
kfree_skb(skb);
dev_kfree_skb_any(skb);
return 0;
}
@ -91,7 +92,7 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
} else {
/* locking problem with netif_stop_queue() ?? */
netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
kfree_skb(skb);
dev_kfree_skb_any(skb);
return -EBUSY;
}
@ -228,7 +229,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
csx = can_skb_ext_add(skb);
if (!csx) {
kfree_skb(skb);
dev_kfree_skb_any(skb);
goto out_error_cc;
}
@ -259,7 +260,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
csx = can_skb_ext_add(skb);
if (!csx) {
kfree_skb(skb);
dev_kfree_skb_any(skb);
goto out_error_fd;
}
@ -297,7 +298,7 @@ struct sk_buff *alloc_canxl_skb(struct net_device *dev,
csx = can_skb_ext_add(skb);
if (!csx) {
kfree_skb(skb);
dev_kfree_skb_any(skb);
goto out_error_xl;
}
@ -403,7 +404,7 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
return false;
inval_skb:
kfree_skb(skb);
dev_kfree_skb_any(skb);
dev->stats.tx_dropped++;
return true;
}

View File

@ -176,7 +176,7 @@ static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *s
return can_dropped_invalid_skb(dev, skb);
invalid_skb:
kfree_skb(skb);
dev_kfree_skb_any(skb);
dev->stats.tx_dropped++;
return true;
}

View File

@ -78,12 +78,12 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
nskb = skb_clone(skb, GFP_ATOMIC);
if (unlikely(!nskb)) {
kfree_skb(skb);
dev_kfree_skb_any(skb);
return NULL;
}
can_skb_set_owner(nskb, skb->sk);
consume_skb(skb);
dev_consume_skb_any(skb);
return nskb;
}