diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2012-07-20 09:23:17 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-22 12:39:33 -0700 |
commit | 1080e512d44d4f67b8beb8edf25a1bbcb1066dc7 (patch) | |
tree | 02cecc2d69f820ac082578daa228cdbe2a4503dd /net | |
parent | 868eefeb17d40f6acde00ad8165a268529cf6d24 (diff) | |
download | linux-3.10-1080e512d44d4f67b8beb8edf25a1bbcb1066dc7.tar.gz linux-3.10-1080e512d44d4f67b8beb8edf25a1bbcb1066dc7.tar.bz2 linux-3.10-1080e512d44d4f67b8beb8edf25a1bbcb1066dc7.zip |
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')
-rw-r--r-- | net/core/dev.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index d70e4a3a49f..cca02ae7a84 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); |