From f16d9e87f41fbc93fab640405e81f44f121683a2 Mon Sep 17 00:00:00 2001 From: Brett Mastbergen Date: Tue, 1 Jul 2025 15:45:25 -0400 Subject: [PATCH 1/2] net/ulp: prevent ULP without clone op from entering the LISTEN status jira VULN-8789 cve CVE-2023-0461 commit-author Paolo Abeni commit 2c02d41d71f90a5168391b6a5f2954112ba2307c upstream-diff In inet_csk_listen_start ret is reinitialized to -EADDRINUSE after the new inet_ulp_can_listen check. The upstream change did not do this because err would inevitably be set later in the function in that version. In this kernel there is no future inevitable set of err so we need to set it back to -EADDRINUSE to ensure this function will return -EADDERINUSE if ->get_port() fails. See LT 5.10 commit fdaf88531cfd17b2a710cceb3141ef6f9085ff40 for the inspiration for this upstream-diff When an ULP-enabled socket enters the LISTEN status, the listener ULP data pointer is copied inside the child/accepted sockets by sk_clone_lock(). The relevant ULP can take care of de-duplicating the context pointer via the clone() operation, but only MPTCP and SMC implement such op. Other ULPs may end-up with a double-free at socket disposal time. We can't simply clear the ULP data at clone time, as TLS replaces the socket ops with custom ones assuming a valid TLS ULP context is available. Instead completely prevent clone-less ULP sockets from entering the LISTEN status. Fixes: 734942cc4ea6 ("tcp: ULP infrastructure") Reported-by: slipper Signed-off-by: Paolo Abeni Link: https://lore.kernel.org/r/4b80c3d1dbe3d0ab072f80450c202d9bc88b4b03.1672740602.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski (cherry picked from commit 2c02d41d71f90a5168391b6a5f2954112ba2307c) Signed-off-by: Brett Mastbergen --- net/ipv4/inet_connection_sock.c | 15 +++++++++++++++ net/ipv4/tcp_ulp.c | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index f4cb1c50e999c..9ab1ffd976134 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -900,12 +900,27 @@ void inet_csk_prepare_forced_close(struct sock *sk) } EXPORT_SYMBOL(inet_csk_prepare_forced_close); +static int inet_ulp_can_listen(const struct sock *sk) +{ + const struct inet_connection_sock *icsk = inet_csk(sk); + + if (icsk->icsk_ulp_ops && !icsk->icsk_ulp_ops->clone) + return -EINVAL; + + return 0; +} + int inet_csk_listen_start(struct sock *sk, int backlog) { struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet = inet_sk(sk); int err = -EADDRINUSE; + err = inet_ulp_can_listen(sk); + if (unlikely(err)) + return err; + + err = -EADDRINUSE; reqsk_queue_alloc(&icsk->icsk_accept_queue); sk->sk_ack_backlog = 0; diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c index 6cae9e21420ba..d3454b6e38fe0 100644 --- a/net/ipv4/tcp_ulp.c +++ b/net/ipv4/tcp_ulp.c @@ -131,6 +131,10 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops) if (icsk->icsk_ulp_ops) goto out_err; + err = -EINVAL; + if (!ulp_ops->clone && sk->sk_state == TCP_LISTEN) + goto out_err; + err = ulp_ops->init(sk); if (err) goto out_err; From 25bb22c30da5b730c1c4c003160b712ba50dc18e Mon Sep 17 00:00:00 2001 From: Brett Mastbergen Date: Tue, 1 Jul 2025 16:59:31 -0400 Subject: [PATCH 2/2] net/ulp: use consistent error code when blocking ULP jira VULN-8789 cve-bf CVE-2023-0461 commit-author Paolo Abeni commit 8ccc99362b60c6f27bb46f36fdaaccf4ef0303de The referenced commit changed the error code returned by the kernel when preventing a non-established socket from attaching the ktls ULP. Before to such a commit, the user-space got ENOTCONN instead of EINVAL. The existing self-tests depend on such error code, and the change caused a failure: RUN global.non_established ... tls.c:1673:non_established:Expected errno (22) == ENOTCONN (107) non_established: Test failed at step #3 FAIL global.non_established In the unlikely event existing applications do the same, address the issue by restoring the prior error code in the above scenario. Note that the only other ULP performing similar checks at init time - smc_ulp_ops - also fails with ENOTCONN when trying to attach the ULP to a non-established socket. Reported-by: Sabrina Dubroca Fixes: 2c02d41d71f9 ("net/ulp: prevent ULP without clone op from entering the LISTEN status") Signed-off-by: Paolo Abeni Reviewed-by: Sabrina Dubroca Link: https://lore.kernel.org/r/7bb199e7a93317fb6f8bf8b9b2dc71c18f337cde.1674042685.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski (cherry picked from commit 8ccc99362b60c6f27bb46f36fdaaccf4ef0303de) Signed-off-by: Brett Mastbergen # Conflicts: # net/ipv4/tcp_ulp.c --- net/ipv4/tcp_ulp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c index d3454b6e38fe0..ab92c3fea0504 100644 --- a/net/ipv4/tcp_ulp.c +++ b/net/ipv4/tcp_ulp.c @@ -131,7 +131,7 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops) if (icsk->icsk_ulp_ops) goto out_err; - err = -EINVAL; + err = -ENOTCONN; if (!ulp_ops->clone && sk->sk_state == TCP_LISTEN) goto out_err;