diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2011-08-31 12:03:29 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-09-15 22:49:44 +0400 |
commit | 48c830120f2a20b44220aa26feda9ed15f49eaab (patch) | |
tree | 5a9bfdf7493cf53e59350b82d5c3c9017fe403a5 /net/core/dev.c | |
parent | 0542b69e2c57fc9668ce6a03155bea6e1f557901 (diff) | |
download | linux-48c830120f2a20b44220aa26feda9ed15f49eaab.tar.xz |
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/core/dev.c')
-rw-r--r-- | net/core/dev.c | 8 |
1 files changed, 8 insertions, 0 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, */ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) { + if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { + if (skb_copy_ubufs(skb, GFP_ATOMIC)) { + atomic_long_inc(&dev->rx_dropped); + kfree_skb(skb); + return NET_RX_DROP; + } + } + skb_orphan(skb); nf_reset(skb); |