]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/net/virtio_net.c
net: add skb frag size accessors
[mirror_ubuntu-zesty-kernel.git] / drivers / net / virtio_net.c
index d6e93ba9ff473161d229ddac3cd2ca0d5232ee50..0d4841bed0f97da9329c9882ecf5d587db49d80e 100644 (file)
@@ -147,14 +147,14 @@ static void set_skb_frag(struct sk_buff *skb, struct page *page,
        skb_frag_t *f;
 
        f = &skb_shinfo(skb)->frags[i];
-       f->size = min((unsigned)PAGE_SIZE - offset, *len);
+       skb_frag_size_set(f, min((unsigned)PAGE_SIZE - offset, *len));
        f->page_offset = offset;
        __skb_frag_set_page(f, page);
 
-       skb->data_len += f->size;
-       skb->len += f->size;
+       skb->data_len += skb_frag_size(f);
+       skb->len += skb_frag_size(f);
        skb_shinfo(skb)->nr_frags++;
-       *len -= f->size;
+       *len -= skb_frag_size(f);
 }
 
 static struct sk_buff *page_to_skb(struct virtnet_info *vi,
@@ -195,6 +195,19 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
        len -= copy;
        offset += copy;
 
+       /*
+        * Verify that we can indeed put this data into a skb.
+        * This is here to handle cases when the device erroneously
+        * tries to receive more than is possible. This is usually
+        * the case of a broken device.
+        */
+       if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) {
+               if (net_ratelimit())
+                       pr_debug("%s: too much data\n", skb->dev->name);
+               dev_kfree_skb(skb);
+               return NULL;
+       }
+
        while (len) {
                set_skb_frag(skb, page, offset, &len);
                page = (struct page *)page->private;