Message ID | a1503ab571c8c076de62b872437d220a2260d2a5.1706094997.git.pabeni@redhat.com (mailing list archive) |
---|---|
State | Mainlined, archived |
Delegated to: | Matthieu Baerts |
Headers | show |
Series | [mptcp-stable] mptcp: introduce explicit flag for first subflow disposal | expand |
Hello Paolo, > On Jan 24, 2024, at 3:35 AM, Paolo Abeni <pabeni@redhat.com> wrote: > > This is a partial backport of the upstram commit 39880bd808ad ("mptcp: > get rid of msk->subflow"). It's partial to avoid a long a complex > dependency chain not suitable for stable. > > The only bit remaning from the original commit is the introduction of a > new field avoid a race at close time causing an UaF: > > BUG: KASAN: use-after-free in mptcp_subflow_queue_clean+0x2c9/0x390 include/net/mptcp.h:104 > Read of size 1 at addr ffff88803bf72884 by task syz-executor.6/23092 > > CPU: 0 PID: 23092 Comm: syz-executor.6 Not tainted 6.1.65-gc6114c845984 #50 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014 > Call Trace: > <TASK> > __dump_stack lib/dump_stack.c:88 [inline] > dump_stack_lvl+0x125/0x18f lib/dump_stack.c:106 > print_report+0x163/0x4f0 mm/kasan/report.c:284 > kasan_report+0xc4/0x100 mm/kasan/report.c:495 > mptcp_subflow_queue_clean+0x2c9/0x390 include/net/mptcp.h:104 > mptcp_check_listen_stop+0x190/0x2a0 net/mptcp/protocol.c:3009 > __mptcp_close+0x9a/0x970 net/mptcp/protocol.c:3024 > mptcp_close+0x2a/0x130 net/mptcp/protocol.c:3089 > inet_release+0x13d/0x190 net/ipv4/af_inet.c:429 > sock_close+0xcf/0x230 net/socket.c:652 > __fput+0x3a2/0x870 fs/file_table.c:320 > task_work_run+0x24e/0x300 kernel/task_work.c:179 > resume_user_mode_work include/linux/resume_user_mode.h:49 [inline] > exit_to_user_mode_loop+0xa4/0xc0 kernel/entry/common.c:171 > exit_to_user_mode_prepare+0x51/0x90 kernel/entry/common.c:204 > syscall_exit_to_user_mode+0x26/0x140 kernel/entry/common.c:286 > do_syscall_64+0x53/0xa0 arch/x86/entry/common.c:86 > entry_SYSCALL_64_after_hwframe+0x64/0xce > RIP: 0033:0x41d791 > Code: 75 14 b8 03 00 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 74 2a 00 00 c3 48 83 ec 08 e8 9a fc ff ff 48 89 04 24 b8 03 00 00 00 0f 05 <48> 8b 3c 24 48 89 c2 e8 e3 fc ff ff 48 89 d0 48 83 c4 08 48 3d 01 > RSP: 002b:00000000008bfb90 EFLAGS: 00000293 ORIG_RAX: 0000000000000003 > RAX: 0000000000000000 RBX: 0000000000000004 RCX: 000000000041d791 > RDX: 0000001b33920000 RSI: ffffffff8139adff RDI: 0000000000000003 > RBP: 000000000079d980 R08: 0000001b33d20000 R09: 0000000000000951 > R10: 000000008139a955 R11: 0000000000000293 R12: 00000000000c739b > R13: 000000000079bf8c R14: 00007fa301053000 R15: 00000000000c705a > </TASK> > > Allocated by task 22528: > kasan_save_stack mm/kasan/common.c:45 [inline] > kasan_set_track+0x40/0x70 mm/kasan/common.c:52 > ____kasan_kmalloc mm/kasan/common.c:374 [inline] > __kasan_kmalloc+0xa0/0xb0 mm/kasan/common.c:383 > kasan_kmalloc include/linux/kasan.h:211 [inline] > __do_kmalloc_node mm/slab_common.c:955 [inline] > __kmalloc+0xaa/0x1c0 mm/slab_common.c:968 > kmalloc include/linux/slab.h:558 [inline] > sk_prot_alloc+0xac/0x200 net/core/sock.c:2038 > sk_clone_lock+0x56/0x1090 net/core/sock.c:2236 > inet_csk_clone_lock+0x26/0x420 net/ipv4/inet_connection_sock.c:1141 > tcp_create_openreq_child+0x30/0x1910 net/ipv4/tcp_minisocks.c:474 > tcp_v6_syn_recv_sock+0x413/0x1a90 net/ipv6/tcp_ipv6.c:1283 > subflow_syn_recv_sock+0x621/0x1300 net/mptcp/subflow.c:730 > tcp_get_cookie_sock+0xf0/0x5f0 net/ipv4/syncookies.c:201 > cookie_v6_check+0x130f/0x1c50 net/ipv6/syncookies.c:261 > tcp_v6_do_rcv+0x7e0/0x12b0 net/ipv6/tcp_ipv6.c:1147 > tcp_v6_rcv+0x2494/0x2f50 net/ipv6/tcp_ipv6.c:1743 > ip6_protocol_deliver_rcu+0xba3/0x1620 net/ipv6/ip6_input.c:438 > ip6_input+0x1bc/0x470 net/ipv6/ip6_input.c:483 > ipv6_rcv+0xef/0x2c0 include/linux/netfilter.h:302 > __netif_receive_skb+0x1ea/0x6a0 net/core/dev.c:5525 > process_backlog+0x353/0x660 net/core/dev.c:5967 > __napi_poll+0xc6/0x5a0 net/core/dev.c:6534 > net_rx_action+0x652/0xea0 net/core/dev.c:6601 > __do_softirq+0x176/0x525 kernel/softirq.c:571 > > Freed by task 23093: > kasan_save_stack mm/kasan/common.c:45 [inline] > kasan_set_track+0x40/0x70 mm/kasan/common.c:52 > kasan_save_free_info+0x2b/0x50 mm/kasan/generic.c:516 > ____kasan_slab_free+0x13a/0x1b0 mm/kasan/common.c:236 > kasan_slab_free include/linux/kasan.h:177 [inline] > slab_free_hook mm/slub.c:1724 [inline] > slab_free_freelist_hook mm/slub.c:1750 [inline] > slab_free mm/slub.c:3661 [inline] > __kmem_cache_free+0x1eb/0x340 mm/slub.c:3674 > sk_prot_free net/core/sock.c:2074 [inline] > __sk_destruct+0x4ad/0x620 net/core/sock.c:2160 > tcp_v6_rcv+0x269c/0x2f50 net/ipv6/tcp_ipv6.c:1761 > ip6_protocol_deliver_rcu+0xba3/0x1620 net/ipv6/ip6_input.c:438 > ip6_input+0x1bc/0x470 net/ipv6/ip6_input.c:483 > ipv6_rcv+0xef/0x2c0 include/linux/netfilter.h:302 > __netif_receive_skb+0x1ea/0x6a0 net/core/dev.c:5525 > process_backlog+0x353/0x660 net/core/dev.c:5967 > __napi_poll+0xc6/0x5a0 net/core/dev.c:6534 > net_rx_action+0x652/0xea0 net/core/dev.c:6601 > __do_softirq+0x176/0x525 kernel/softirq.c:571 > > The buggy address belongs to the object at ffff88803bf72000 > which belongs to the cache kmalloc-4k of size 4096 > The buggy address is located 2180 bytes inside of > 4096-byte region [ffff88803bf72000, ffff88803bf73000) > > The buggy address belongs to the physical page: > page:00000000a72e4e51 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3bf70 > head:00000000a72e4e51 order:3 compound_mapcount:0 compound_pincount:0 > flags: 0x100000000010200(slab|head|node=0|zone=1) > raw: 0100000000010200 ffffea0000a0ea00 dead000000000002 ffff888100042140 > raw: 0000000000000000 0000000000040004 00000001ffffffff 0000000000000000 > page dumped because: kasan: bad access detected > > Memory state around the buggy address: > ffff88803bf72780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ffff88803bf72800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >> ffff88803bf72880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ^ > ffff88803bf72900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ffff88803bf72980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > > Prevent the MPTCP worker from freeing the first subflow for unaccepted > socket when such sockets transition to TCP_CLOSE state, and let that > happen at accept() or listener close() time. > > Fixes: b6985b9b8295 ("mptcp: use the workqueue to destroy unaccepted sockets") > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > --- > This is targeting _stable_ and specifically 6.1.65. > I tested vs the repro in: > > https://github.com/multipath-tcp/mptcp_net-next/issues/466 > > and WFM. @Christoph could you please validate this in your testbed, too? Yes, this fixes both #466 and #465. I’m updating syzkaller and if it’s happy I can push it to upstream. Thanks a lot! Christoph > > If pass the testing it would be great if you could take over the > upstream submission. > > The hash blamed above is the upstream/vanilla. I'm unsure if it's more > relevant to tag the corresponding stable one > --- > net/mptcp/protocol.c | 9 ++++----- > net/mptcp/protocol.h | 3 ++- > 2 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c > index 76539d1004eb..db5369b6442d 100644 > --- a/net/mptcp/protocol.c > +++ b/net/mptcp/protocol.c > @@ -2422,7 +2422,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, > goto out_release; > } > > - dispose_it = !msk->subflow || ssk != msk->subflow->sk; > + dispose_it = msk->free_first || ssk != msk->first; > if (dispose_it) > list_del(&subflow->node); > > @@ -2440,7 +2440,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, > need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk); > if (!dispose_it) { > __mptcp_subflow_disconnect(ssk, subflow, flags); > - msk->subflow->state = SS_UNCONNECTED; > release_sock(ssk); > > goto out; > @@ -3341,10 +3340,10 @@ static void mptcp_destroy(struct sock *sk) > { > struct mptcp_sock *msk = mptcp_sk(sk); > > - /* clears msk->subflow, allowing the following to close > - * even the initial subflow > - */ > mptcp_dispose_initial_subflow(msk); > + > + /* allow the following to close even the initial subflow */ > + msk->free_first = 1; > mptcp_destroy_common(msk, 0); > sk_sockets_allocated_dec(sk); > } > diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h > index 4ec8e0a81b5a..e5d553dfc13f 100644 > --- a/net/mptcp/protocol.h > +++ b/net/mptcp/protocol.h > @@ -287,7 +287,8 @@ struct mptcp_sock { > cork:1, > nodelay:1, > fastopening:1, > - in_accept_queue:1; > + in_accept_queue:1, > + free_first:1; > struct work_struct work; > struct sk_buff *ooo_last_skb; > struct rb_root out_of_order_queue; > -- > 2.43.0 > >
On Wed, 24 Jan 2024, Christoph Paasch wrote: > Hello Paolo, > >> On Jan 24, 2024, at 3:35 AM, Paolo Abeni <pabeni@redhat.com> wrote: >> >> This is a partial backport of the upstram commit 39880bd808ad ("mptcp: >> get rid of msk->subflow"). It's partial to avoid a long a complex >> dependency chain not suitable for stable. >> >> The only bit remaning from the original commit is the introduction of a >> new field avoid a race at close time causing an UaF: >> >> BUG: KASAN: use-after-free in mptcp_subflow_queue_clean+0x2c9/0x390 include/net/mptcp.h:104 >> Read of size 1 at addr ffff88803bf72884 by task syz-executor.6/23092 >> >> CPU: 0 PID: 23092 Comm: syz-executor.6 Not tainted 6.1.65-gc6114c845984 #50 >> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014 >> Call Trace: >> <TASK> >> __dump_stack lib/dump_stack.c:88 [inline] >> dump_stack_lvl+0x125/0x18f lib/dump_stack.c:106 >> print_report+0x163/0x4f0 mm/kasan/report.c:284 >> kasan_report+0xc4/0x100 mm/kasan/report.c:495 >> mptcp_subflow_queue_clean+0x2c9/0x390 include/net/mptcp.h:104 >> mptcp_check_listen_stop+0x190/0x2a0 net/mptcp/protocol.c:3009 >> __mptcp_close+0x9a/0x970 net/mptcp/protocol.c:3024 >> mptcp_close+0x2a/0x130 net/mptcp/protocol.c:3089 >> inet_release+0x13d/0x190 net/ipv4/af_inet.c:429 >> sock_close+0xcf/0x230 net/socket.c:652 >> __fput+0x3a2/0x870 fs/file_table.c:320 >> task_work_run+0x24e/0x300 kernel/task_work.c:179 >> resume_user_mode_work include/linux/resume_user_mode.h:49 [inline] >> exit_to_user_mode_loop+0xa4/0xc0 kernel/entry/common.c:171 >> exit_to_user_mode_prepare+0x51/0x90 kernel/entry/common.c:204 >> syscall_exit_to_user_mode+0x26/0x140 kernel/entry/common.c:286 >> do_syscall_64+0x53/0xa0 arch/x86/entry/common.c:86 >> entry_SYSCALL_64_after_hwframe+0x64/0xce >> RIP: 0033:0x41d791 >> Code: 75 14 b8 03 00 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 74 2a 00 00 c3 48 83 ec 08 e8 9a fc ff ff 48 89 04 24 b8 03 00 00 00 0f 05 <48> 8b 3c 24 48 89 c2 e8 e3 fc ff ff 48 89 d0 48 83 c4 08 48 3d 01 >> RSP: 002b:00000000008bfb90 EFLAGS: 00000293 ORIG_RAX: 0000000000000003 >> RAX: 0000000000000000 RBX: 0000000000000004 RCX: 000000000041d791 >> RDX: 0000001b33920000 RSI: ffffffff8139adff RDI: 0000000000000003 >> RBP: 000000000079d980 R08: 0000001b33d20000 R09: 0000000000000951 >> R10: 000000008139a955 R11: 0000000000000293 R12: 00000000000c739b >> R13: 000000000079bf8c R14: 00007fa301053000 R15: 00000000000c705a >> </TASK> >> >> Allocated by task 22528: >> kasan_save_stack mm/kasan/common.c:45 [inline] >> kasan_set_track+0x40/0x70 mm/kasan/common.c:52 >> ____kasan_kmalloc mm/kasan/common.c:374 [inline] >> __kasan_kmalloc+0xa0/0xb0 mm/kasan/common.c:383 >> kasan_kmalloc include/linux/kasan.h:211 [inline] >> __do_kmalloc_node mm/slab_common.c:955 [inline] >> __kmalloc+0xaa/0x1c0 mm/slab_common.c:968 >> kmalloc include/linux/slab.h:558 [inline] >> sk_prot_alloc+0xac/0x200 net/core/sock.c:2038 >> sk_clone_lock+0x56/0x1090 net/core/sock.c:2236 >> inet_csk_clone_lock+0x26/0x420 net/ipv4/inet_connection_sock.c:1141 >> tcp_create_openreq_child+0x30/0x1910 net/ipv4/tcp_minisocks.c:474 >> tcp_v6_syn_recv_sock+0x413/0x1a90 net/ipv6/tcp_ipv6.c:1283 >> subflow_syn_recv_sock+0x621/0x1300 net/mptcp/subflow.c:730 >> tcp_get_cookie_sock+0xf0/0x5f0 net/ipv4/syncookies.c:201 >> cookie_v6_check+0x130f/0x1c50 net/ipv6/syncookies.c:261 >> tcp_v6_do_rcv+0x7e0/0x12b0 net/ipv6/tcp_ipv6.c:1147 >> tcp_v6_rcv+0x2494/0x2f50 net/ipv6/tcp_ipv6.c:1743 >> ip6_protocol_deliver_rcu+0xba3/0x1620 net/ipv6/ip6_input.c:438 >> ip6_input+0x1bc/0x470 net/ipv6/ip6_input.c:483 >> ipv6_rcv+0xef/0x2c0 include/linux/netfilter.h:302 >> __netif_receive_skb+0x1ea/0x6a0 net/core/dev.c:5525 >> process_backlog+0x353/0x660 net/core/dev.c:5967 >> __napi_poll+0xc6/0x5a0 net/core/dev.c:6534 >> net_rx_action+0x652/0xea0 net/core/dev.c:6601 >> __do_softirq+0x176/0x525 kernel/softirq.c:571 >> >> Freed by task 23093: >> kasan_save_stack mm/kasan/common.c:45 [inline] >> kasan_set_track+0x40/0x70 mm/kasan/common.c:52 >> kasan_save_free_info+0x2b/0x50 mm/kasan/generic.c:516 >> ____kasan_slab_free+0x13a/0x1b0 mm/kasan/common.c:236 >> kasan_slab_free include/linux/kasan.h:177 [inline] >> slab_free_hook mm/slub.c:1724 [inline] >> slab_free_freelist_hook mm/slub.c:1750 [inline] >> slab_free mm/slub.c:3661 [inline] >> __kmem_cache_free+0x1eb/0x340 mm/slub.c:3674 >> sk_prot_free net/core/sock.c:2074 [inline] >> __sk_destruct+0x4ad/0x620 net/core/sock.c:2160 >> tcp_v6_rcv+0x269c/0x2f50 net/ipv6/tcp_ipv6.c:1761 >> ip6_protocol_deliver_rcu+0xba3/0x1620 net/ipv6/ip6_input.c:438 >> ip6_input+0x1bc/0x470 net/ipv6/ip6_input.c:483 >> ipv6_rcv+0xef/0x2c0 include/linux/netfilter.h:302 >> __netif_receive_skb+0x1ea/0x6a0 net/core/dev.c:5525 >> process_backlog+0x353/0x660 net/core/dev.c:5967 >> __napi_poll+0xc6/0x5a0 net/core/dev.c:6534 >> net_rx_action+0x652/0xea0 net/core/dev.c:6601 >> __do_softirq+0x176/0x525 kernel/softirq.c:571 >> >> The buggy address belongs to the object at ffff88803bf72000 >> which belongs to the cache kmalloc-4k of size 4096 >> The buggy address is located 2180 bytes inside of >> 4096-byte region [ffff88803bf72000, ffff88803bf73000) >> >> The buggy address belongs to the physical page: >> page:00000000a72e4e51 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3bf70 >> head:00000000a72e4e51 order:3 compound_mapcount:0 compound_pincount:0 >> flags: 0x100000000010200(slab|head|node=0|zone=1) >> raw: 0100000000010200 ffffea0000a0ea00 dead000000000002 ffff888100042140 >> raw: 0000000000000000 0000000000040004 00000001ffffffff 0000000000000000 >> page dumped because: kasan: bad access detected >> >> Memory state around the buggy address: >> ffff88803bf72780: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >> ffff88803bf72800: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >>> ffff88803bf72880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >> ^ >> ffff88803bf72900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >> ffff88803bf72980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >> >> Prevent the MPTCP worker from freeing the first subflow for unaccepted >> socket when such sockets transition to TCP_CLOSE state, and let that >> happen at accept() or listener close() time. >> >> Fixes: b6985b9b8295 ("mptcp: use the workqueue to destroy unaccepted sockets") >> Signed-off-by: Paolo Abeni <pabeni@redhat.com> >> --- >> This is targeting _stable_ and specifically 6.1.65. >> I tested vs the repro in: >> >> https://github.com/multipath-tcp/mptcp_net-next/issues/466 Thanks Paolo, patch LGTM for 6.1-stable: Reviewed-by: Mat Martineau <martineau@kernel.org> >> >> and WFM. @Christoph could you please validate this in your testbed, too? > > Yes, this fixes both #466 and #465. > > I’m updating syzkaller and if it’s happy I can push it to upstream. > And thanks Christoph for bisecting, testing, and pushing upstream! - Mat
On Wed, 2024-01-24 at 09:51 -0800, Christoph Paasch wrote: > On Jan 24, 2024, at 3:35 AM, Paolo Abeni <pabeni@redhat.com> wrote: > > This is targeting _stable_ and specifically 6.1.65. > > I tested vs the repro in: > > > > https://github.com/multipath-tcp/mptcp_net-next/issues/466 > > > > and WFM. @Christoph could you please validate this in your testbed, too? > > Yes, this fixes both #466 and #465. > > I’m updating syzkaller and if it’s happy I can push it to upstream. Thanks for testing and doing the process! I'm wondering if there are other pending issues that impact your deployment someway? Cheers, Paolo
> On Jan 30, 2024, at 10:56 AM, Paolo Abeni <pabeni@redhat.com> wrote: > > On Wed, 2024-01-24 at 09:51 -0800, Christoph Paasch wrote: >> On Jan 24, 2024, at 3:35 AM, Paolo Abeni <pabeni@redhat.com> wrote: >>> This is targeting _stable_ and specifically 6.1.65. >>> I tested vs the repro in: >>> >>> https://github.com/multipath-tcp/mptcp_net-next/issues/466 >>> >>> and WFM. @Christoph could you please validate this in your testbed, too? >> >> Yes, this fixes both #466 and #465. >> >> I’m updating syzkaller and if it’s happy I can push it to upstream. > > Thanks for testing and doing the process! > > I'm wondering if there are other pending issues that impact your > deployment someway? Right now, nothing. RHEL 9.3 is running well ;-) Christoph > > Cheers, > > Paolo >
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 76539d1004eb..db5369b6442d 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2422,7 +2422,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, goto out_release; } - dispose_it = !msk->subflow || ssk != msk->subflow->sk; + dispose_it = msk->free_first || ssk != msk->first; if (dispose_it) list_del(&subflow->node); @@ -2440,7 +2440,6 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, need_push = (flags & MPTCP_CF_PUSH) && __mptcp_retransmit_pending_data(sk); if (!dispose_it) { __mptcp_subflow_disconnect(ssk, subflow, flags); - msk->subflow->state = SS_UNCONNECTED; release_sock(ssk); goto out; @@ -3341,10 +3340,10 @@ static void mptcp_destroy(struct sock *sk) { struct mptcp_sock *msk = mptcp_sk(sk); - /* clears msk->subflow, allowing the following to close - * even the initial subflow - */ mptcp_dispose_initial_subflow(msk); + + /* allow the following to close even the initial subflow */ + msk->free_first = 1; mptcp_destroy_common(msk, 0); sk_sockets_allocated_dec(sk); } diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 4ec8e0a81b5a..e5d553dfc13f 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -287,7 +287,8 @@ struct mptcp_sock { cork:1, nodelay:1, fastopening:1, - in_accept_queue:1; + in_accept_queue:1, + free_first:1; struct work_struct work; struct sk_buff *ooo_last_skb; struct rb_root out_of_order_queue;