aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2011-08-31 04:03:29 -0400
committerDavid S. Miller <davem@davemloft.net>2011-09-15 14:49:44 -0400
commit48c830120f2a20b44220aa26feda9ed15f49eaab (patch)
tree5a9bfdf7493cf53e59350b82d5c3c9017fe403a5 /net
parent0542b69e2c57fc9668ce6a03155bea6e1f557901 (diff)
net: copy userspace buffers on device forwarding
dev_forward_skb loops an skb back into host networking stack which might hang on the memory indefinitely. In particular, this can happen in macvtap in bridged mode. Copy the userspace fragments to avoid blocking the sender in that case. As this patch makes skb_copy_ubufs extern now, I also added some documentation and made it clear the SKBTX_DEV_ZEROCOPY flag automatically instead of doing it in all callers. This can be made into a separate patch if people feel it's worth it. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c8
-rw-r--r--net/core/skbuff.c22
2 files changed, 25 insertions, 5 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 17d67b579beb..b10ff0a71855 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1515,6 +1515,14 @@ static inline bool is_skb_forwardable(struct net_device *dev,
1515 */ 1515 */
1516int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) 1516int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1517{ 1517{
1518 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
1519 if (skb_copy_ubufs(skb, GFP_ATOMIC)) {
1520 atomic_long_inc(&dev->rx_dropped);
1521 kfree_skb(skb);
1522 return NET_RX_DROP;
1523 }
1524 }
1525
1518 skb_orphan(skb); 1526 skb_orphan(skb);
1519 nf_reset(skb); 1527 nf_reset(skb);
1520 1528
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 27002dffe7ed..387703f56fce 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -611,8 +611,21 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
611} 611}
612EXPORT_SYMBOL_GPL(skb_morph); 612EXPORT_SYMBOL_GPL(skb_morph);
613 613
614/* skb frags copy userspace buffers to kernel */ 614/* skb_copy_ubufs - copy userspace skb frags buffers to kernel
615static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) 615 * @skb: the skb to modify
616 * @gfp_mask: allocation priority
617 *
618 * This must be called on SKBTX_DEV_ZEROCOPY skb.
619 * It will copy all frags into kernel and drop the reference
620 * to userspace pages.
621 *
622 * If this function is called from an interrupt gfp_mask() must be
623 * %GFP_ATOMIC.
624 *
625 * Returns 0 on success or a negative error code on failure
626 * to allocate kernel memory to copy to.
627 */
628int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
616{ 629{
617 int i; 630 int i;
618 int num_frags = skb_shinfo(skb)->nr_frags; 631 int num_frags = skb_shinfo(skb)->nr_frags;
@@ -652,6 +665,8 @@ static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
652 skb_shinfo(skb)->frags[i - 1].page = head; 665 skb_shinfo(skb)->frags[i - 1].page = head;
653 head = (struct page *)head->private; 666 head = (struct page *)head->private;
654 } 667 }
668
669 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
655 return 0; 670 return 0;
656} 671}
657 672
@@ -677,7 +692,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
677 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { 692 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
678 if (skb_copy_ubufs(skb, gfp_mask)) 693 if (skb_copy_ubufs(skb, gfp_mask))
679 return NULL; 694 return NULL;
680 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
681 } 695 }
682 696
683 n = skb + 1; 697 n = skb + 1;
@@ -803,7 +817,6 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
803 n = NULL; 817 n = NULL;
804 goto out; 818 goto out;
805 } 819 }
806 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
807 } 820 }
808 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 821 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
809 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; 822 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
@@ -896,7 +909,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
896 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { 909 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
897 if (skb_copy_ubufs(skb, gfp_mask)) 910 if (skb_copy_ubufs(skb, gfp_mask))
898 goto nofrags; 911 goto nofrags;
899 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
900 } 912 }
901 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 913 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
902 get_page(skb_shinfo(skb)->frags[i].page); 914 get_page(skb_shinfo(skb)->frags[i].page);