Kuniyuki Iwashima
92aaa5e8fe
tcp/udp: Fix memory leak in ipv6_renew_options().
...
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: Meena Shanmugam <meenashanmugam@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2022-11-10 17:57:54 +01:00
..
2021-09-15 09:47:31 +02:00
2022-08-25 11:18:17 +02:00
2021-07-31 08:19:38 +02:00
2021-12-01 09:23:34 +01:00
2021-04-07 14:47:41 +02:00
2022-10-29 10:20:35 +02:00
2022-04-20 09:19:40 +02:00
2022-05-18 09:47:24 +02:00
2022-11-10 17:57:54 +01:00
2022-09-05 10:27:46 +02:00
2021-07-14 16:53:33 +02:00
2022-09-28 11:04:07 +02:00
2021-09-22 12:26:40 +02:00
2022-11-03 23:56:52 +09:00
2020-11-05 11:43:34 +01:00
2022-11-10 17:57:52 +01:00
2022-03-08 19:07:51 +01:00
2022-08-25 11:17:49 +02:00
2021-07-28 13:30:56 +02:00
2020-04-23 10:36:45 +02:00
2022-03-23 09:12:07 +01:00
2020-01-09 10:20:06 +01:00
2021-05-14 09:44:10 +02:00
2022-11-03 23:56:54 +09:00
2019-09-26 08:56:17 +02:00
2022-11-03 23:56:56 +09:00
2022-11-10 17:57:54 +01:00
2021-03-07 12:20:42 +01:00
2022-11-03 23:56:55 +09:00
2022-09-05 10:27:40 +02:00
2022-06-22 14:11:21 +02:00
2022-04-27 13:50:47 +02:00
2021-02-10 09:25:28 +01:00
2022-03-28 08:46:48 +02:00
2022-10-26 13:22:22 +02:00
2022-11-03 23:56:53 +09:00
2021-12-08 09:01:12 +01:00
2022-01-05 12:37:45 +01:00
2022-11-10 17:57:51 +01:00
2022-04-15 14:18:35 +02:00
2022-05-18 09:47:25 +02:00
2021-07-28 13:30:56 +02:00
2022-06-14 18:11:33 +02:00
2022-11-03 23:56:56 +09:00
2022-09-05 10:27:48 +02:00
2022-01-11 15:23:33 +01:00
2019-12-04 22:30:54 +01:00
2021-09-03 10:08:12 +02:00
2022-10-26 13:22:26 +02:00
2020-11-24 13:29:05 +01:00
2022-11-10 17:57:51 +01:00
2022-09-28 11:03:58 +02:00
2022-11-10 17:57:50 +01:00
2022-10-26 13:22:26 +02:00
2022-09-15 12:04:50 +02:00
2021-11-17 09:48:48 +01:00
2022-09-05 10:27:40 +02:00
2021-10-27 09:54:24 +02:00
2022-11-03 23:56:55 +09:00
2022-07-29 17:14:12 +02:00
2022-10-26 13:22:59 +02:00
2022-10-26 13:22:25 +02:00
2022-10-15 07:54:41 +02:00
2022-04-15 14:18:21 +02:00
2021-12-22 09:29:40 +01:00
2022-10-26 13:22:49 +02:00
2021-06-18 09:59:00 +02:00
2020-04-01 11:02:18 +02:00
2022-09-05 10:27:42 +02:00