* [PATCH 4.14 1/1] tcp/udp: Fix memory leak in ipv6_renew_options().
@ 2022-11-24 9:42 Ovidiu Panait
2022-12-04 15:44 ` Greg KH
0 siblings, 1 reply; 2+ messages in thread
From: Ovidiu Panait @ 2022-11-24 9:42 UTC (permalink / raw)
To: stable; +Cc: Kuniyuki Iwashima, syzbot, Jakub Kicinski, Ovidiu Panait
From: Kuniyuki Iwashima <kuniyu@amazon.com>
commit 3c52c6bb831f6335c176a0fc7214e26f43adbd11 upstream.
syzbot reported a memory leak [0] related to IPV6_ADDRFORM.
The scenario is that while one thread is converting an IPv6 socket into
IPv4 with IPV6_ADDRFORM, another thread calls do_ipv6_setsockopt() and
allocates memory to inet6_sk(sk)->XXX after conversion.
Then, the converted sk with (tcp|udp)_prot never frees the IPv6 resources,
which inet6_destroy_sock() should have cleaned up.
setsockopt(IPV6_ADDRFORM) setsockopt(IPV6_DSTOPTS)
+-----------------------+ +----------------------+
- do_ipv6_setsockopt(sk, ...)
- sockopt_lock_sock(sk) - do_ipv6_setsockopt(sk, ...)
- lock_sock(sk) ^._ called via tcpv6_prot
- WRITE_ONCE(sk->sk_prot, &tcp_prot) before WRITE_ONCE()
- xchg(&np->opt, NULL)
- txopt_put(opt)
- sockopt_release_sock(sk)
- release_sock(sk) - sockopt_lock_sock(sk)
- lock_sock(sk)
- ipv6_set_opt_hdr(sk, ...)
- ipv6_update_options(sk, opt)
- xchg(&inet6_sk(sk)->opt, opt)
^._ opt is never freed.
- sockopt_release_sock(sk)
- release_sock(sk)
Since IPV6_DSTOPTS allocates options under lock_sock(), we can avoid this
memory leak by testing whether sk_family is changed by IPV6_ADDRFORM after
acquiring the lock.
This issue exists from the initial commit between IPV6_ADDRFORM and
IPV6_PKTOPTIONS.
[0]:
BUG: memory leak
unreferenced object 0xffff888009ab9f80 (size 96):
comm "syz-executor583", pid 328, jiffies 4294916198 (age 13.034s)
hex dump (first 32 bytes):
01 00 00 00 48 00 00 00 08 00 00 00 00 00 00 00 ....H...........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<000000002ee98ae1>] kmalloc include/linux/slab.h:605 [inline]
[<000000002ee98ae1>] sock_kmalloc+0xb3/0x100 net/core/sock.c:2566
[<0000000065d7b698>] ipv6_renew_options+0x21e/0x10b0 net/ipv6/exthdrs.c:1318
[<00000000a8c756d7>] ipv6_set_opt_hdr net/ipv6/ipv6_sockglue.c:354 [inline]
[<00000000a8c756d7>] do_ipv6_setsockopt.constprop.0+0x28b7/0x4350 net/ipv6/ipv6_sockglue.c:668
[<000000002854d204>] ipv6_setsockopt+0xdf/0x190 net/ipv6/ipv6_sockglue.c:1021
[<00000000e69fdcf8>] tcp_setsockopt+0x13b/0x2620 net/ipv4/tcp.c:3789
[<0000000090da4b9b>] __sys_setsockopt+0x239/0x620 net/socket.c:2252
[<00000000b10d192f>] __do_sys_setsockopt net/socket.c:2263 [inline]
[<00000000b10d192f>] __se_sys_setsockopt net/socket.c:2260 [inline]
[<00000000b10d192f>] __x64_sys_setsockopt+0xbe/0x160 net/socket.c:2260
[<000000000a80d7aa>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
[<000000000a80d7aa>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80
[<000000004562b5c6>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
---
net/ipv6/ipv6_sockglue.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 3f44316db51b..3c099742c58e 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -166,6 +166,12 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
rtnl_lock();
lock_sock(sk);
+ /* Another thread has converted the socket into IPv4 with
+ * IPV6_ADDRFORM concurrently.
+ */
+ if (unlikely(sk->sk_family != AF_INET6))
+ goto unlock;
+
switch (optname) {
case IPV6_ADDRFORM:
@@ -905,6 +911,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
break;
}
+unlock:
release_sock(sk);
if (needs_rtnl)
rtnl_unlock();
--
2.38.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 4.14 1/1] tcp/udp: Fix memory leak in ipv6_renew_options().
2022-11-24 9:42 [PATCH 4.14 1/1] tcp/udp: Fix memory leak in ipv6_renew_options() Ovidiu Panait
@ 2022-12-04 15:44 ` Greg KH
0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2022-12-04 15:44 UTC (permalink / raw)
To: Ovidiu Panait; +Cc: stable, Kuniyuki Iwashima, syzbot, Jakub Kicinski
On Thu, Nov 24, 2022 at 11:42:26AM +0200, Ovidiu Panait wrote:
> From: Kuniyuki Iwashima <kuniyu@amazon.com>
>
> commit 3c52c6bb831f6335c176a0fc7214e26f43adbd11 upstream.
>
> syzbot reported a memory leak [0] related to IPV6_ADDRFORM.
>
> The scenario is that while one thread is converting an IPv6 socket into
> IPv4 with IPV6_ADDRFORM, another thread calls do_ipv6_setsockopt() and
> allocates memory to inet6_sk(sk)->XXX after conversion.
>
> Then, the converted sk with (tcp|udp)_prot never frees the IPv6 resources,
> which inet6_destroy_sock() should have cleaned up.
>
> setsockopt(IPV6_ADDRFORM) setsockopt(IPV6_DSTOPTS)
> +-----------------------+ +----------------------+
> - do_ipv6_setsockopt(sk, ...)
> - sockopt_lock_sock(sk) - do_ipv6_setsockopt(sk, ...)
> - lock_sock(sk) ^._ called via tcpv6_prot
> - WRITE_ONCE(sk->sk_prot, &tcp_prot) before WRITE_ONCE()
> - xchg(&np->opt, NULL)
> - txopt_put(opt)
> - sockopt_release_sock(sk)
> - release_sock(sk) - sockopt_lock_sock(sk)
> - lock_sock(sk)
> - ipv6_set_opt_hdr(sk, ...)
> - ipv6_update_options(sk, opt)
> - xchg(&inet6_sk(sk)->opt, opt)
> ^._ opt is never freed.
>
> - sockopt_release_sock(sk)
> - release_sock(sk)
>
> Since IPV6_DSTOPTS allocates options under lock_sock(), we can avoid this
> memory leak by testing whether sk_family is changed by IPV6_ADDRFORM after
> acquiring the lock.
>
> This issue exists from the initial commit between IPV6_ADDRFORM and
> IPV6_PKTOPTIONS.
>
> [0]:
> BUG: memory leak
> unreferenced object 0xffff888009ab9f80 (size 96):
> comm "syz-executor583", pid 328, jiffies 4294916198 (age 13.034s)
> hex dump (first 32 bytes):
> 01 00 00 00 48 00 00 00 08 00 00 00 00 00 00 00 ....H...........
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
> backtrace:
> [<000000002ee98ae1>] kmalloc include/linux/slab.h:605 [inline]
> [<000000002ee98ae1>] sock_kmalloc+0xb3/0x100 net/core/sock.c:2566
> [<0000000065d7b698>] ipv6_renew_options+0x21e/0x10b0 net/ipv6/exthdrs.c:1318
> [<00000000a8c756d7>] ipv6_set_opt_hdr net/ipv6/ipv6_sockglue.c:354 [inline]
> [<00000000a8c756d7>] do_ipv6_setsockopt.constprop.0+0x28b7/0x4350 net/ipv6/ipv6_sockglue.c:668
> [<000000002854d204>] ipv6_setsockopt+0xdf/0x190 net/ipv6/ipv6_sockglue.c:1021
> [<00000000e69fdcf8>] tcp_setsockopt+0x13b/0x2620 net/ipv4/tcp.c:3789
> [<0000000090da4b9b>] __sys_setsockopt+0x239/0x620 net/socket.c:2252
> [<00000000b10d192f>] __do_sys_setsockopt net/socket.c:2263 [inline]
> [<00000000b10d192f>] __se_sys_setsockopt net/socket.c:2260 [inline]
> [<00000000b10d192f>] __x64_sys_setsockopt+0xbe/0x160 net/socket.c:2260
> [<000000000a80d7aa>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
> [<000000000a80d7aa>] do_syscall_64+0x38/0x90 arch/x86/entry/common.c:80
> [<000000004562b5c6>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Reported-by: syzbot <syzkaller@googlegroups.com>
> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
> ---
> net/ipv6/ipv6_sockglue.c | 7 +++++++
> 1 file changed, 7 insertions(+)
All now queued up, thanks.
greg k-h
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-12-04 15:44 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-24 9:42 [PATCH 4.14 1/1] tcp/udp: Fix memory leak in ipv6_renew_options() Ovidiu Panait
2022-12-04 15:44 ` Greg KH
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.