summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2012-07-20 09:23:17 (GMT)
committerDavid S. Miller <davem@davemloft.net>2012-07-22 19:39:33 (GMT)
commit1080e512d44d4f67b8beb8edf25a1bbcb1066dc7 (patch)
tree02cecc2d69f820ac082578daa228cdbe2a4503dd /net/core
parent868eefeb17d40f6acde00ad8165a268529cf6d24 (diff)
downloadlinux-1080e512d44d4f67b8beb8edf25a1bbcb1066dc7.tar.xz
net: orphan frags on receive
zero copy packets are normally sent to the outside network, but bridging, tun etc might loop them back to host networking stack. If this happens destructors will never be called, so orphan the frags immediately on receive. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index d70e4a3a..cca02ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1632,6 +1632,8 @@ static inline int deliver_skb(struct sk_buff *skb,
struct packet_type *pt_prev,
struct net_device *orig_dev)
{
+ if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+ return -ENOMEM;
atomic_inc(&skb->users);
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}
@@ -3262,7 +3264,10 @@ ncls:
}
if (pt_prev) {
- ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
+ if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+ ret = -ENOMEM;
+ else
+ ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
} else {
atomic_long_inc(&skb->dev->rx_dropped);
kfree_skb(skb);