ftmac100_rx_packet() uses __pskb_pull_tail() to pull either the Ethernet header or, for small frames, the whole frame into the skb head, and ignores the return value. If that pull ever failed, eth_type_trans() would find less than ETH_HLEN in the head and BUG() in __skb_pull().
It doesn't fail today because the skb is freshly allocated, isn't shared and has room in the head, but that's only true because of how this driver allocates. Use pskb_may_pull() for the header and __skb_linearize() for small frames, which is what the two pulls are doing, and drop the frame if either fails. Assisted-by: LLM Signed-off-by: Josef Bacik <[email protected]> --- drivers/net/ethernet/faraday/ftmac100.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index 40ba001d4b3f..a1eb04ead2d8 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -469,15 +469,21 @@ static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed) if (length > 128) { skb->truesize += PAGE_SIZE; /* We pull the minimum amount into linear part */ - __pskb_pull_tail(skb, ETH_HLEN); + ret = pskb_may_pull(skb, ETH_HLEN); } else { /* Small frames are copied into linear part to free one page */ - __pskb_pull_tail(skb, length); + ret = !__skb_linearize(skb); } ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC); ftmac100_rx_pointer_advance(priv); + if (unlikely(!ret)) { + netdev->stats.rx_dropped++; + kfree_skb(skb); + return true; + } + skb->protocol = eth_type_trans(skb, netdev); netdev->stats.rx_packets++; -- 2.55.0
