When the skb already has MAX_SKB_FRAGS frags, xennet_fill_frags() calls __pskb_pull_tail() to free up a frag slot. That frees slots in two ways: it pulls the start of the packet into the head, and it releases empty frags, even when there's nothing left to pull. The second part is what commit d81c5054a5d1 ("xen/netfront: tolerate frags with no data") relies on. The return value is ignored, which works out only because the nr_frags check right after it drops the packet if no slot was freed. Use pskb_may_pull() followed by skb_drop_empty_frags(), and take the error path explicitly if either fails. pskb_may_pull() does nothing if the head already holds pull_to bytes, so the BUG_ON() for pull_to < skb_headlen(skb), which protected the subtraction, can go. Assisted-by: LLM Signed-off-by: Josef Bacik --- drivers/net/xen-netfront.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 2ed673649c48..007fa3bbc9e6 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1174,18 +1174,15 @@ static int xennet_fill_frags(struct netfront_queue *queue, RING_COPY_RESPONSE(&queue->rx, ++cons, &rx); - if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) { - unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; - - BUG_ON(pull_to < skb_headlen(skb)); - __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); - } - if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) { - xennet_set_rx_rsp_cons(queue, - ++cons + skb_queue_len(list)); - kfree_skb(nskb); - return -ENOENT; - } + /* Out of frag slots: pull the start of the packet into the + * head and drop empty frags to make room. + */ + if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS && + unlikely(!pskb_may_pull(skb, NETFRONT_SKB_CB(skb)->pull_to) || + skb_drop_empty_frags(skb, GFP_ATOMIC))) + goto err; + if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) + goto err; skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, skb_frag_page(nfrag), @@ -1198,6 +1195,11 @@ static int xennet_fill_frags(struct netfront_queue *queue, xennet_set_rx_rsp_cons(queue, cons); return 0; + +err: + xennet_set_rx_rsp_cons(queue, ++cons + skb_queue_len(list)); + kfree_skb(nskb); + return -ENOENT; } static int checksum_setup(struct net_device *dev, struct sk_buff *skb) -- 2.55.0