]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
virtio-net: keep vnet header zeroed after processing XDP
authorJason Wang <jasowang@redhat.com>
Thu, 29 Nov 2018 05:53:16 +0000 (13:53 +0800)
committerSultan Alsawaf <sultan.alsawaf@canonical.com>
Wed, 24 Jul 2019 15:45:07 +0000 (09:45 -0600)
BugLink: https://bugs.launchpad.net/bugs/1837161
[ Upstream commit 436c9453a1ac0944b82870ef2e0d9be956b396d9 ]

We copy vnet header unconditionally in page_to_skb() this is wrong
since XDP may modify the packet data. So let's keep a zeroed vnet
header for not confusing the conversion between vnet header and skb
metadata.

In the future, we should able to detect whether or not the packet was
modified and keep using the vnet header when packet was not touched.

Fixes: f600b6905015 ("virtio_net: Add XDP support")
Reported-by: Pavel Popa <pashinho1990@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/net/virtio_net.c

index f6c83e95ecbfc02a78893014446c57d5a3803f22..58f8423974d5d625eb3cb4ee6f7ae5d4e3e7536c 100644 (file)
@@ -310,7 +310,8 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx)
 static struct sk_buff *page_to_skb(struct virtnet_info *vi,
                                   struct receive_queue *rq,
                                   struct page *page, unsigned int offset,
-                                  unsigned int len, unsigned int truesize)
+                                  unsigned int len, unsigned int truesize,
+                                  bool hdr_valid)
 {
        struct sk_buff *skb;
        struct virtio_net_hdr_mrg_rxbuf *hdr;
@@ -332,7 +333,8 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
        else
                hdr_padded_len = sizeof(struct padded_vnet_hdr);
 
-       memcpy(hdr, p, hdr_len);
+       if (hdr_valid)
+               memcpy(hdr, p, hdr_len);
 
        len -= hdr_len;
        offset += hdr_padded_len;
@@ -627,7 +629,8 @@ static struct sk_buff *receive_big(struct net_device *dev,
                                   unsigned int len)
 {
        struct page *page = buf;
-       struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE);
+       struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len,
+                                         PAGE_SIZE, true);
 
        if (unlikely(!skb))
                goto err;
@@ -718,7 +721,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
                                rcu_read_unlock();
                                put_page(page);
                                head_skb = page_to_skb(vi, rq, xdp_page,
-                                                      offset, len, PAGE_SIZE);
+                                                      offset, len,
+                                                      PAGE_SIZE, false);
                                return head_skb;
                        }
                        break;
@@ -761,7 +765,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
                goto err_skb;
        }
 
-       head_skb = page_to_skb(vi, rq, page, offset, len, truesize);
+       head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog);
        curr_skb = head_skb;
 
        if (unlikely(!curr_skb))