]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tcp: do not recycle cloned skbs
authorEric Dumazet <edumazet@google.com>
Wed, 15 May 2019 16:10:15 +0000 (09:10 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 15 May 2019 16:22:41 +0000 (09:22 -0700)
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>
include/net/sock.h
net/ipv4/tcp.c

index 4d208c0f9c14b7c8f5975dcc69e13d89d1880df5..0680fa98849761d187c0149a57fa2d5d683a9a76 100644 (file)
@@ -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;
index 1fa15beb83806696a6b4f5eddb7e45c13a2dea45..53d61ca3ac4b4ee8992742247629bce7f71ee659 100644 (file)
@@ -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);