diff options
author | Eric Dumazet <edumazet@google.com> | 2015-11-01 18:36:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-11-02 16:28:49 -0500 |
commit | 9e17f8a475fca81950fdddc08df428ed66cf441f (patch) | |
tree | 417a79910266f08806f78be2dd970102afa3356f /net/core/sock.c | |
parent | eca1e006cf6f6f66a1a90c055a8a6d393475c3f9 (diff) |
net: make skb_set_owner_w() more robust
skb_set_owner_w() is called from various places that assume
skb->sk always point to a full blown socket (as it changes
sk->sk_wmem_alloc)
We'd like to attach skb to request sockets, and in the future
to timewait sockets as well. For these kind of pseudo sockets,
we need to take a traditional refcount and use sock_edemux()
as the destructor.
It is now time to un-inline skb_set_owner_w(), being too big.
Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Bisected-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 0ef30aa90132..7529eb9463be 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1656,6 +1656,28 @@ void sock_wfree(struct sk_buff *skb) | |||
1656 | } | 1656 | } |
1657 | EXPORT_SYMBOL(sock_wfree); | 1657 | EXPORT_SYMBOL(sock_wfree); |
1658 | 1658 | ||
1659 | void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | ||
1660 | { | ||
1661 | skb_orphan(skb); | ||
1662 | skb->sk = sk; | ||
1663 | #ifdef CONFIG_INET | ||
1664 | if (unlikely(!sk_fullsock(sk))) { | ||
1665 | skb->destructor = sock_edemux; | ||
1666 | sock_hold(sk); | ||
1667 | return; | ||
1668 | } | ||
1669 | #endif | ||
1670 | skb->destructor = sock_wfree; | ||
1671 | skb_set_hash_from_sk(skb, sk); | ||
1672 | /* | ||
1673 | * We used to take a refcount on sk, but following operation | ||
1674 | * is enough to guarantee sk_free() wont free this sock until | ||
1675 | * all in-flight packets are completed | ||
1676 | */ | ||
1677 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); | ||
1678 | } | ||
1679 | EXPORT_SYMBOL(skb_set_owner_w); | ||
1680 | |||
1659 | void skb_orphan_partial(struct sk_buff *skb) | 1681 | void skb_orphan_partial(struct sk_buff *skb) |
1660 | { | 1682 | { |
1661 | /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc, | 1683 | /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc, |