lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <20221006171038.68453-1-kuniyu@amazon.com> Date: Thu, 6 Oct 2022 10:10:38 -0700 From: Kuniyuki Iwashima <kuniyu@...zon.com> To: <pabeni@...hat.com> CC: <davem@...emloft.net>, <dsahern@...nel.org>, <edumazet@...gle.com>, <kuba@...nel.org>, <kuni1840@...il.com>, <kuniyu@...zon.com>, <linux-kernel@...r.kernel.org>, <netdev@...r.kernel.org>, <syzkaller-bugs@...glegroups.com>, <vyasevic@...hat.com>, <yoshfuji@...ux-ipv6.org> Subject: Re: [PATCH v4 net 3/5] tcp/udp: Call inet6_destroy_sock() in IPv6 sk->sk_destruct(). From: Paolo Abeni <pabeni@...hat.com> Date: Thu, 06 Oct 2022 11:19:53 +0200 > On Tue, 2022-10-04 at 10:18 -0700, Kuniyuki Iwashima wrote: > > 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 03485f2adcde ("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, ...) > > - lock_sock(sk) ^._ called via udpv6_prot > > - WRITE_ONCE(sk->sk_prot, &tcp_prot) before WRITE_ONCE() > > - inet6_destroy_sock() > > - release_sock(sk) - ip6_make_skb(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. > > > > - lock_sock(sk) > > > > For now, rxpmtu is only the case, but not to miss the future change > > and a similar bug fixed in commit e27326009a3d ("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: 03485f2adcde ("udpv6: Add lockless sendmsg() support") > > Signed-off-by: Kuniyuki Iwashima <kuniyu@...zon.com> > > --- > > Cc: Vladislav Yasevich <vyasevic@...hat.com> > > --- > > include/net/ipv6.h | 1 + > > include/net/udp.h | 2 +- > > include/net/udplite.h | 8 -------- > > net/ipv4/udp.c | 9 ++++++--- > > net/ipv4/udplite.c | 8 ++++++++ > > net/ipv6/af_inet6.c | 9 ++++++++- > > net/ipv6/udp.c | 15 ++++++++++++++- > > net/ipv6/udp_impl.h | 1 + > > net/ipv6/udplite.c | 9 ++++++++- > > 9 files changed, 47 insertions(+), 15 deletions(-) > > > > diff --git a/include/net/ipv6.h b/include/net/ipv6.h > > index dfa70789b771..e7ec3e8cd52e 100644 > > --- a/include/net/ipv6.h > > +++ b/include/net/ipv6.h > > @@ -1179,6 +1179,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info); > > void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu); > > > > void inet6_cleanup_sock(struct sock *sk); > > +void inet6_sock_destruct(struct sock *sk); > > int inet6_release(struct socket *sock); > > int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len); > > int inet6_getname(struct socket *sock, struct sockaddr *uaddr, > > diff --git a/include/net/udp.h b/include/net/udp.h > > index 5ee88ddf79c3..fee053bcd17c 100644 > > --- a/include/net/udp.h > > +++ b/include/net/udp.h > > @@ -247,7 +247,7 @@ static inline bool udp_sk_bound_dev_eq(struct net *net, int bound_dev_if, > > } > > > > /* net/ipv4/udp.c */ > > -void udp_destruct_sock(struct sock *sk); > > +void udp_destruct_common(struct sock *sk); > > void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len); > > int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb); > > void udp_skb_destructor(struct sock *sk, struct sk_buff *skb); > > diff --git a/include/net/udplite.h b/include/net/udplite.h > > index 0143b373602e..299c14ce2bb9 100644 > > --- a/include/net/udplite.h > > +++ b/include/net/udplite.h > > @@ -25,14 +25,6 @@ static __inline__ int udplite_getfrag(void *from, char *to, int offset, > > return copy_from_iter_full(to, len, &msg->msg_iter) ? 0 : -EFAULT; > > } > > > > -/* Designate sk as UDP-Lite socket */ > > -static inline int udplite_sk_init(struct sock *sk) > > -{ > > - udp_init_sock(sk); > > - udp_sk(sk)->pcflag = UDPLITE_BIT; > > - return 0; > > -} > > - > > /* > > * Checksumming routines > > */ > > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > > index 560d9eadeaa5..48adb418e404 100644 > > --- a/net/ipv4/udp.c > > +++ b/net/ipv4/udp.c > > @@ -1598,7 +1598,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) > > } > > EXPORT_SYMBOL_GPL(__udp_enqueue_schedule_skb); > > > > -void udp_destruct_sock(struct sock *sk) > > +void udp_destruct_common(struct sock *sk) > > { > > /* reclaim completely the forward allocated memory */ > > struct udp_sock *up = udp_sk(sk); > > @@ -1611,10 +1611,14 @@ void udp_destruct_sock(struct sock *sk) > > kfree_skb(skb); > > } > > udp_rmem_release(sk, total, 0, true); > > +} > > +EXPORT_SYMBOL_GPL(udp_destruct_common); > > > > +static void udp_destruct_sock(struct sock *sk) > > +{ > > + udp_destruct_common(sk); > > inet_sock_destruct(sk); > > } > > -EXPORT_SYMBOL_GPL(udp_destruct_sock); > > > > int udp_init_sock(struct sock *sk) > > { > > @@ -1622,7 +1626,6 @@ int udp_init_sock(struct sock *sk) > > sk->sk_destruct = udp_destruct_sock; > > return 0; > > } > > -EXPORT_SYMBOL_GPL(udp_init_sock); > > > > void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len) > > { > > diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c > > index 6e08a76ae1e7..4785ac4a8719 100644 > > --- a/net/ipv4/udplite.c > > +++ b/net/ipv4/udplite.c > > @@ -17,6 +17,14 @@ > > struct udp_table udplite_table __read_mostly; > > EXPORT_SYMBOL(udplite_table); > > > > +/* Designate sk as UDP-Lite socket */ > > +static inline int udplite_sk_init(struct sock *sk) > > You should avoid the 'inline' specifier in c files. I'll fix it. > > +{ > > + udp_init_sock(sk); > > + udp_sk(sk)->pcflag = UDPLITE_BIT; > > + return 0; > > +} > > + > > static int udplite_rcv(struct sk_buff *skb) > > { > > return __udp4_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE); > > diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c > > index 83b9e432f3df..ce5378b78ec9 100644 > > --- a/net/ipv6/af_inet6.c > > +++ b/net/ipv6/af_inet6.c > > @@ -109,6 +109,13 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) > > return (struct ipv6_pinfo *)(((u8 *)sk) + offset); > > } > > > > +void inet6_sock_destruct(struct sock *sk) > > +{ > > + inet6_cleanup_sock(sk); > > + inet_sock_destruct(sk); > > +} > > +EXPORT_SYMBOL_GPL(inet6_sock_destruct); > > I'm sorry for not noticing this before, but it looks like the above > export is not needed? only used by udp, which is in the same binary > (either kernel of ipv6 module) as af_inet6 Ah, please don't be sorry, I appreciate your review! Exactly, it compiled without exporting the symbol, I'll remove it in v5.
Powered by blists - more mailing lists