[PATCH OLK-6.6] tcp: clear sock_ops cb flags before force-closing a child socket
From: Sechang Lim <rhkrqnwk98@gmail.com> mainline inclusion from mainline-v7.2-rc1 commit 990348e5bb457697c2f1f7f7b65154a3334d9d2b category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17954 CVE: CVE-2026-74268 Reference:https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- A child socket inherits the listener's bpf_sock_ops_cb_flags via sk_clone_lock(). If its setup fails in tcp_v4_syn_recv_sock() / tcp_v6_syn_recv_sock(), the child is freed through put_and_exit, where inet_csk_prepare_forced_close() drops the socket lock and tcp_done() runs without it. If BPF_SOCK_OPS_STATE_CB_FLAG was inherited, tcp_done() -> tcp_set_state() calls tcp_call_bpf(), which expects the lock and trips sock_owned_by_me(): WARNING: include/net/sock.h:1799 at tcp_set_state+0x433/0x550 RIP: 0010:tcp_set_state+0x433/0x550 include/net/sock.h:1799 Call Trace: <IRQ> tcp_done+0xba/0x250 net/ipv4/tcp.c:5095 tcp_v4_syn_recv_sock+0x850/0xa50 net/ipv4/tcp_ipv4.c:1787 tcp_check_req+0xf30/0x1360 net/ipv4/tcp_minisocks.c:926 tcp_v4_rcv+0x1047/0x1b50 net/ipv4/tcp_ipv4.c:2164 </IRQ> The child is freed before it is ever established, so it should run no sock_ops callback. Clear its cb flags in inet_csk_prepare_for_destroy_sock(), the common point for the IPv4, IPv6 and chtls forced-close paths and for the MPTCP ->syn_recv_sock() failure path (dispose_child), which reaches tcp_done() on a child that was never established too. Suggested-by: Jiayuan Chen <jiayuan.chen@linux.dev> Fixes: d44874910a26 ("bpf: Add BPF_SOCK_OPS_STATE_CB") Signed-off-by: Sechang Lim <rhkrqnwk98@gmail.com> Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260611092923.1895982-1-rhkrqnwk98@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Conflicts: net/ipv4/inet_connection_sock.c [In OLK-6.6, inet_csk_prepare_for_destroy_sock() remains a static inline function in include/net/inet_connection_sock.h, while upstream already moved it into inet_connection_sock.c via commit 7051b54fb5aa (due to header dependency). This backport cherry-picks the inline-to-non-inline conversion (changing the definition in inet_connection_sock.h to a declaration), retains OLK-6.6's this_cpu_inc(*sk->sk_prot->orphan_count) implementation without pulling in the orphan_count refactoring, and adds a sk->sk_protocol == IPPROTO_TCP guard to isolate the DCCP path. Signed-off-by: JiangJieHua <jiangjiehua1@huawei.com> --- include/net/inet_connection_sock.h | 8 +------- include/net/tcp.h | 9 +++++++++ net/ipv4/inet_connection_sock.c | 9 +++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 327ae14ca82b..c16f600e5c5c 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -303,14 +303,8 @@ reqsk_timeout(struct request_sock *req, unsigned long max_timeout) return (unsigned long)min_t(u64, timeout, max_timeout); } -static inline void inet_csk_prepare_for_destroy_sock(struct sock *sk) -{ - /* The below has to be done to allow calling inet_csk_destroy_sock */ - sock_set_flag(sk, SOCK_DEAD); - this_cpu_inc(*sk->sk_prot->orphan_count); -} - void inet_csk_destroy_sock(struct sock *sk); +void inet_csk_prepare_for_destroy_sock(struct sock *sk); void inet_csk_prepare_forced_close(struct sock *sk); /* diff --git a/include/net/tcp.h b/include/net/tcp.h index 8674996bd39c..e1a345d5a40b 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -2515,6 +2515,11 @@ static inline int tcp_call_bpf_3arg(struct sock *sk, int op, u32 arg1, u32 arg2, return tcp_call_bpf(sk, op, 3, args); } +static inline void tcp_clear_sock_ops_cb_flags(struct sock *sk) +{ + tcp_sk(sk)->bpf_sock_ops_cb_flags = 0; +} + #else static inline int tcp_call_bpf(struct sock *sk, int op, u32 nargs, u32 *args) { @@ -2532,6 +2537,10 @@ static inline int tcp_call_bpf_3arg(struct sock *sk, int op, u32 arg1, u32 arg2, return -EPERM; } +static inline void tcp_clear_sock_ops_cb_flags(struct sock *sk) +{ +} + #endif static inline u32 tcp_timeout_init(struct sock *sk) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 9f1d17cd5eeb..b0844b7fa7fc 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -1240,6 +1240,15 @@ void inet_csk_destroy_sock(struct sock *sk) } EXPORT_SYMBOL(inet_csk_destroy_sock); +void inet_csk_prepare_for_destroy_sock(struct sock *sk) +{ + /* The below has to be done to allow calling inet_csk_destroy_sock */ + if (sk->sk_protocol == IPPROTO_TCP) + tcp_clear_sock_ops_cb_flags(sk); + sock_set_flag(sk, SOCK_DEAD); + tcp_orphan_count_inc(); +} + /* This function allows to force a closure of a socket after the call to * tcp/dccp_create_openreq_child(). */ -- 2.33.8
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/26795 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/7TE... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/26795 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/7TE...
participants (2)
-
JiangJieHua -
patchwork bot