aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2019-05-15 09:10:15 -0700
committerDavid S. Miller <davem@davemloft.net>2019-05-15 09:22:41 -0700
commit858f5017446764e8bca0b29589a3b164186ae471 (patch)
tree373f0ffe2041cc465d0c0582b27da70f6179d7ee
parentenetc: Add missing link state info for ethtool (diff)
downloadlinux-dev-858f5017446764e8bca0b29589a3b164186ae471.tar.xz
linux-dev-858f5017446764e8bca0b29589a3b164186ae471.zip
tcp: do not recycle cloned skbs
It is illegal to change arbitrary fields in skb_shared_info if the skb is cloned. Before calling skb_zcopy_clear() we need to ensure this rule, therefore we need to move the test from sk_stream_alloc_skb() to sk_wmem_free_skb() Fixes: 4f661542a402 ("tcp: fix zerocopy and notsent_lowat issues") Signed-off-by: Eric Dumazet <edumazet@google.com> Diagnosed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sock.h2
-rw-r--r--net/ipv4/tcp.c2
2 files changed, 2 insertions, 2 deletions
diff --git a/include/net/sock.h b/include/net/sock.h
index 4d208c0f9c14..0680fa988497 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1473,7 +1473,7 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb)
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
sk->sk_wmem_queued -= skb->truesize;
sk_mem_uncharge(sk, skb->truesize);
- if (!sk->sk_tx_skb_cache) {
+ if (!sk->sk_tx_skb_cache && !skb_cloned(skb)) {
skb_zcopy_clear(skb, true);
sk->sk_tx_skb_cache = skb;
return;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1fa15beb8380..53d61ca3ac4b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -855,7 +855,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp,
if (likely(!size)) {
skb = sk->sk_tx_skb_cache;
- if (skb && !skb_cloned(skb)) {
+ if (skb) {
skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
sk->sk_tx_skb_cache = NULL;
pskb_trim(skb, 0);