[PATCH net 04/22] can: dev: can_put_echo_skb(): free skb on invalid echo index
flat view
COLD16d
REVIEWED: 2 (2M)
From: Marc Kleine-Budde <mkl@pengutronix.de>
Date: 2026-09-28 19:33:26
Also in:
linux-can, stable
Subsystem:
can network drivers, the rest · Maintainers:
Marc Kleine-Budde, Vincent Mailhol, Linus Torvalds
1 review trailer (1 from subsystem maintainers).
From: Cunhao Lu <redacted>
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 <mailhol@kernel.org>
Signed-off-by: Cunhao Lu <redacted>
Link: https://patch.msgid.link/tencent_683AA16E643DE00211CD2FB62991264DC605@qq.com (local)
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
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/ (local)
[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 d1f797d3778d..f414b75b5c0d 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