]> git.baikalelectronics.ru Git - kernel.git/commit
tcp/udp: Call inet6_destroy_sock() in IPv6 sk->sk_destruct().
authorKuniyuki Iwashima <kuniyu@amazon.com>
Thu, 6 Oct 2022 18:53:47 +0000 (11:53 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 26 Apr 2023 09:24:05 +0000 (11:24 +0200)
commitb113ce7370681dde2faba7ddef40b38f3d7c9ba7
treebd6508b8f774f775513824e75266fb4a95e76958
parent4364ced1973250f696e96bec9153b9255a1aa742
tcp/udp: Call inet6_destroy_sock() in IPv6 sk->sk_destruct().

commit 48385351c5983a690736d08a6b2a43c50e6e63a2 upstream.

Originally, inet6_sk(sk)->XXX were changed under lock_sock(), so we were
able to clean them up by calling inet6_destroy_sock() during the IPv6 ->
IPv4 conversion by IPV6_ADDRFORM.  However, commit dda734d2f56d ("udpv6:
Add lockless sendmsg() support") added a lockless memory allocation path,
which could cause a memory leak:

setsockopt(IPV6_ADDRFORM)                 sendmsg()
+-----------------------+                 +-------+
- do_ipv6_setsockopt(sk, ...)             - udpv6_sendmsg(sk, ...)
  - sockopt_lock_sock(sk)                   ^._ called via udpv6_prot
    - lock_sock(sk)                             before WRITE_ONCE()
  - WRITE_ONCE(sk->sk_prot, &tcp_prot)
  - inet6_destroy_sock()                    - if (!corkreq)
  - sockopt_release_sock(sk)                  - ip6_make_skb(sk, ...)
    - release_sock(sk)                          ^._ lockless fast path for
                                                    the non-corking case

                                                - __ip6_append_data(sk, ...)
                                                  - ipv6_local_rxpmtu(sk, ...)
                                                    - xchg(&np->rxpmtu, skb)
                                                      ^._ rxpmtu is never freed.

                                                - goto out_no_dst;

                                            - lock_sock(sk)

For now, rxpmtu is only the case, but not to miss the future change
and a similar bug fixed in commit 77971fcf30ea ("net: ping6: Fix
memleak in ipv6_renew_options()."), let's set a new function to IPv6
sk->sk_destruct() and call inet6_cleanup_sock() there.  Since the
conversion does not change sk->sk_destruct(), we can guarantee that
we can clean up IPv6 resources finally.

We can now remove all inet6_destroy_sock() calls from IPv6 protocol
specific ->destroy() functions, but such changes are invasive to
backport.  So they can be posted as a follow-up later for net-next.

Fixes: dda734d2f56d ("udpv6: Add lockless sendmsg() support")
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Ziyang Xuan <william.xuanziyang@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/net/ipv6.h
include/net/udp.h
include/net/udplite.h
net/ipv4/udp.c
net/ipv4/udplite.c
net/ipv6/af_inet6.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udplite.c