Skip to content

Commit 443041d

Browse files
Gang Yankuba-moo
authored andcommitted
mptcp: fix NULL pointer in can_accept_new_subflow
When testing valkey benchmark tool with MPTCP, the kernel panics in 'mptcp_can_accept_new_subflow' because subflow_req->msk is NULL. Call trace: mptcp_can_accept_new_subflow (./net/mptcp/subflow.c:63 (discriminator 4)) (P) subflow_syn_recv_sock (./net/mptcp/subflow.c:854) tcp_check_req (./net/ipv4/tcp_minisocks.c:863) tcp_v4_rcv (./net/ipv4/tcp_ipv4.c:2268) ip_protocol_deliver_rcu (./net/ipv4/ip_input.c:207) ip_local_deliver_finish (./net/ipv4/ip_input.c:234) ip_local_deliver (./net/ipv4/ip_input.c:254) ip_rcv_finish (./net/ipv4/ip_input.c:449) ... According to the debug log, the same req received two SYN-ACK in a very short time, very likely because the client retransmits the syn ack due to multiple reasons. Even if the packets are transmitted with a relevant time interval, they can be processed by the server on different CPUs concurrently). The 'subflow_req->msk' ownership is transferred to the subflow the first, and there will be a risk of a null pointer dereference here. This patch fixes this issue by moving the 'subflow_req->msk' under the `own_req == true` conditional. Note that the !msk check in subflow_hmac_valid() can be dropped, because the same check already exists under the own_req mpj branch where the code has been moved to. Fixes: 9466a1c ("mptcp: enable JOIN requests even if cookies are in use") Cc: [email protected] Suggested-by: Paolo Abeni <[email protected]> Signed-off-by: Gang Yan <[email protected]> Reviewed-by: Matthieu Baerts (NGI0) <[email protected]> Signed-off-by: Matthieu Baerts (NGI0) <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 323d6db commit 443041d

File tree

1 file changed

+8
-7
lines changed

1 file changed

+8
-7
lines changed

net/mptcp/subflow.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -754,8 +754,6 @@ static bool subflow_hmac_valid(const struct request_sock *req,
754754

755755
subflow_req = mptcp_subflow_rsk(req);
756756
msk = subflow_req->msk;
757-
if (!msk)
758-
return false;
759757

760758
subflow_generate_hmac(READ_ONCE(msk->remote_key),
761759
READ_ONCE(msk->local_key),
@@ -850,12 +848,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
850848

851849
} else if (subflow_req->mp_join) {
852850
mptcp_get_options(skb, &mp_opt);
853-
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) ||
854-
!subflow_hmac_valid(req, &mp_opt) ||
855-
!mptcp_can_accept_new_subflow(subflow_req->msk)) {
856-
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
851+
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK))
857852
fallback = true;
858-
}
859853
}
860854

861855
create_child:
@@ -905,6 +899,13 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
905899
goto dispose_child;
906900
}
907901

902+
if (!subflow_hmac_valid(req, &mp_opt) ||
903+
!mptcp_can_accept_new_subflow(subflow_req->msk)) {
904+
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
905+
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
906+
goto dispose_child;
907+
}
908+
908909
/* move the msk reference ownership to the subflow */
909910
subflow_req->msk = NULL;
910911
ctx->conn = (struct sock *)owner;

0 commit comments

Comments
 (0)