From: Cunhao Lu <1579567540@qq.com> can_put_echo_skb() consumes the skb on all paths except when the echo index is out of bounds. This leaves ownership with the caller on -EINVAL, unlike the other error paths, and can leak the skb if the caller expects consistent semantics. Free the skb before returning -EINVAL so that all return paths consume it. Fixes: 6411959c10fe ("can: dev: can_put_echo_skb(): don't crash kernel if can_priv::echo_skb is accessed out of bounds") Cc: stable@vger.kernel.org Reviewed-by: Vincent Mailhol Signed-off-by: Cunhao Lu <1579567540@qq.com> Link: https://patch.msgid.link/tencent_683AA16E643DE00211CD2FB62991264DC605@qq.com Signed-off-by: Marc Kleine-Budde --- FAQ: Q: `can_skb_init_valid()` directly modifies `skb->data` without checking if the SKB is cloned or shared. Is this violating SKB shared buffer rules and causing data corruption? A: The finding about can_skb_init_valid() modifying skb->data on a potentially shared buffer is not relevant for this (correct) patch. The FDF-flag write in can_skb_init_valid() only matters for PF_PACKET use: PF_CAN allocators already set CANFD_FDF. The write exists to normalize frames for PF_PACKET observers (tcpdump/Wireshark) so they can distinguish classic CAN from CAN FD at the netdev level, and to compensate for PF_PACKET senders that omit the bit. That normalization is functionally required. The shared-buffer concern only becomes realistic through a specific chain: a PF_PACKET sender injects a CANFD-sized frame, the CAN driver's loopback puts an echo skb back into can_rcv(), and cgw (without modfuncs) clones it for forwarding to another interface. Only on that second can_skb_init_valid() call is the skb cloned. By then the bit was already set on the exclusive skb during the initial xmit path, so the flags |= CANFD_FDF write is strictly idempotent for any parallel consumer of the shared buffer - no memory-safety or information-disclosure consequence. It's a formal violation of the skb sharing rules without an observable effect, so the current code can stay as-is. Link: https://lore.kernel.org/all/54a3cc01-abcf-4a33-b932-39bb1f68cdd5@hartkopp.net/ [mkl: convert Oliver's mail to FAQ section] --- drivers/net/can/dev/skb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c index 3e36c0368bae..738d5968dfa6 100644 --- a/drivers/net/can/dev/skb.c +++ b/drivers/net/can/dev/skb.c @@ -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; } -- 2.53.0