[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH net-next 4/9] xen/netfront: check for failure when pulling in xennet_fill_frags()



When the skb already has MAX_SKB_FRAGS frags, xennet_fill_frags() pulls
the start of the packet into the head to try to free up a frag slot.
It ignores the return value of __pskb_pull_tail(), which works out only
because the nr_frags check right after it drops the packet if no slot
was freed.

Use pskb_may_pull() and take the error path explicitly if it 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 <josef@xxxxxxxxxxxxxx>
---
 drivers/net/xen-netfront.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 2ed673649c48..6e01a883cc64 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1174,18 +1174,11 @@ 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;
-               }
+               if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS &&
+                   unlikely(!pskb_may_pull(skb, 
NETFRONT_SKB_CB(skb)->pull_to)))
+                       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 +1191,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




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.