In the Linux kernel, the following vulnerability has been resolved:
tcp: cdg: allow tcpcdgrelease() to be called multiple times
Apparently, mptcp is able to call tcp_disconnect() on an already disconnected flow. This is generally fine, unless current congestion control is CDG, because it might trigger a double-free [1]
Instead of fixing MPTCP, and future bugs, we can make tcp_disconnect() more resilient.
[1] BUG: KASAN: double-free in slab_free mm/slub.c:3539 [inline] BUG: KASAN: double-free in kfree+0xe2/0x580 mm/slub.c:4567
CPU: 0 PID: 3645 Comm: kworker/0:7 Not tainted 6.0.0-syzkaller-02734-g0326074ff465 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/22/2022 Workqueue: events mptcpworker Call Trace: <TASK> dumpstack lib/dumpstack.c:88 [inline] dumpstacklvl+0xcd/0x134 lib/dumpstack.c:106 printaddressdescription mm/kasan/report.c:317 [inline] printreport.cold+0x2ba/0x719 mm/kasan/report.c:433 kasanreportinvalidfree+0x81/0x190 mm/kasan/report.c:462 kasanslabfree+0x18b/0x1c0 mm/kasan/common.c:356 kasanslabfree include/linux/kasan.h:200 [inline] slabfreehook mm/slub.c:1759 [inline] slabfreefreelisthook+0x8b/0x1c0 mm/slub.c:1785 slabfree mm/slub.c:3539 [inline] kfree+0xe2/0x580 mm/slub.c:4567 tcpdisconnect+0x980/0x1e20 net/ipv4/tcp.c:3145 _mptcpclosessk+0x5ca/0x7e0 net/mptcp/protocol.c:2327 mptcpdofastclose net/mptcp/protocol.c:2592 [inline] mptcpworker+0x78c/0xff0 net/mptcp/protocol.c:2627 processonework+0x991/0x1610 kernel/workqueue.c:2289 workerthread+0x665/0x1080 kernel/workqueue.c:2436 kthread+0x2e4/0x3a0 kernel/kthread.c:376 retfromfork+0x1f/0x30 arch/x86/entry/entry_64.S:306 </TASK>
Allocated by task 3671: kasansavestack+0x1e/0x40 mm/kasan/common.c:38 kasansettrack mm/kasan/common.c:45 [inline] setallocinfo mm/kasan/common.c:437 [inline] _kasankmalloc mm/kasan/common.c:516 [inline] kasankmalloc mm/kasan/common.c:475 [inline] _kasankmalloc+0xa9/0xd0 mm/kasan/common.c:525 kmallocarray include/linux/slab.h:640 [inline] kcalloc include/linux/slab.h:671 [inline] tcpcdginit+0x10d/0x170 net/ipv4/tcpcdg.c:380 tcpinitcongestioncontrol+0xab/0x550 net/ipv4/tcpcong.c:193 tcpreinitcongestioncontrol net/ipv4/tcpcong.c:217 [inline] tcpsetcongestioncontrol+0x96c/0xaa0 net/ipv4/tcpcong.c:391 dotcpsetsockopt+0x505/0x2320 net/ipv4/tcp.c:3513 tcpsetsockopt+0xd4/0x100 net/ipv4/tcp.c:3801 mptcpsetsockopt+0x35f/0x2570 net/mptcp/sockopt.c:844 _syssetsockopt+0x2d6/0x690 net/socket.c:2252 _dosyssetsockopt net/socket.c:2263 [inline] _sesyssetsockopt net/socket.c:2260 [inline] _x64syssetsockopt+0xba/0x150 net/socket.c:2260 dosyscallx64 arch/x86/entry/common.c:50 [inline] dosyscall64+0x35/0xb0 arch/x86/entry/common.c:80 entrySYSCALL64afterhwframe+0x63/0xcd
Freed by task 16: kasansavestack+0x1e/0x40 mm/kasan/common.c:38 kasansettrack+0x21/0x30 mm/kasan/common.c:45 kasansetfreeinfo+0x20/0x30 mm/kasan/generic.c:370 kasanslabfree mm/kasan/common.c:367 [inline] _kasanslabfree+0x166/0x1c0 mm/kasan/common.c:329 kasanslabfree include/linux/kasan.h:200 [inline] slabfreehook mm/slub.c:1759 [inline] slabfreefreelisthook+0x8b/0x1c0 mm/slub.c:1785 slabfree mm/slub.c:3539 [inline] kfree+0xe2/0x580 mm/slub.c:4567 tcpcleanupcongestioncontrol+0x70/0x120 net/ipv4/tcpcong.c:226 tcpv4destroysock+0xdd/0x750 net/ipv4/tcpipv4.c:2254 tcpv6destroysock+0x11/0x20 net/ipv6/tcpipv6.c:1969 inetcskdestroysock+0x196/0x440 net/ipv4/inetconnectionsock.c:1157 tcpdone+0x23b/0x340 net/ipv4/tcp.c:4649 tcprcvstateprocess+0x40e7/0x4990 net/ipv4/tcpinput.c:6624 tcpv6dorcv+0x3fc/0x13c0 net/ipv6/tcpipv6.c:1525 tcpv6rcv+0x2e8e/0x3830 net/ipv6/tcpipv6.c:1759 ip6protocoldeliverrcu+0x2db/0x1950 net/ipv6/ip6input.c:439 ip6inputfinish+0x14c/0x2c0 net/ipv6/ip6input.c:484 NFHOOK include/linux/netfilter.h:302 [inline] NFHOOK include/linux/netfilter.h:296 [inline] ip6_input+0x9c/0xd ---truncated---