From: Wyatt Feng <redacted>
loopback_xmit() calls eth_type_trans(), which reads the Ethernet header
from skb->data and consumes ETH_HLEN bytes. This requires at least
ETH_HLEN bytes in the skb's linear area.
An earlier transformation can leave a non-linear skb with fewer than
ETH_HLEN bytes in the linear area, even when skb->len is at least
ETH_HLEN. Pulling the header then makes skb->len smaller than
skb->data_len and triggers the BUG in __skb_pull().
Check skb_headlen(skb) before calling eth_type_trans(). Reject skbs
whose linear area is too short, including those whose total length is
less than ETH_HLEN, without attempting to pull bytes from fragments.
Free rejected skbs, account them as TX drops and return NETDEV_TX_OK.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Vega <redacted>
Link: https://lore.kernel.org/all/2d4e79d252a57bdad83435999dddf2c4b708dcfa.1785049236.git.bronzed_45_vested@icloud.com/ (local)
Suggested-by: Jamal Hadi Salim <jhs@mojatatu.com>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Wyatt Feng <redacted>
Signed-off-by: Ren Wei <redacted>
---
Changes in v4:
- Replace pskb_may_pull() with a direct skb_headlen() check, as
requested by Jamal after considering the Sashiko feedback.
- Update the commit message to match the linear-length check.
- Correct the Fixes tag to the earliest tracked occurrence of the
unchecked eth_type_trans() call and the skb pull invariant.
drivers/net/loopback.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 1fb6ce6843ad..eaa9a5a8542a 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -72,6 +72,12 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb,
{
int len;
+ if (unlikely(skb_headlen(skb) < ETH_HLEN)) {
+ kfree_skb(skb);
+ dev_core_stats_tx_dropped_inc(dev);
+ return NETDEV_TX_OK;
+ }
+
skb_tx_timestamp(skb);
/* do not fool net_timestamp_check() with various clock bases */