]> git.hungrycats.org Git - linux/commitdiff
mptcp: cope racing subflow creation in mptcp_rcv_space_adjust
authorPaolo Abeni <pabeni@redhat.com>
Tue, 19 Nov 2024 08:35:49 +0000 (09:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 22 Nov 2024 14:37:33 +0000 (15:37 +0100)
commit ce7356ae35943cc6494cc692e62d51a734062b7d upstream.

Additional active subflows - i.e. created by the in kernel path
manager - are included into the subflow list before starting the
3whs.

A racing recvmsg() spooling data received on an already established
subflow would unconditionally call tcp_cleanup_rbuf() on all the
current subflows, potentially hitting a divide by zero error on
the newly created ones.

Explicitly check that the subflow is in a suitable state before
invoking tcp_cleanup_rbuf().

Fixes: c76c6956566f ("mptcp: call tcp_cleanup_rbuf on subflows")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/02374660836e1b52afc91966b7535c8c5f7bafb0.1731060874.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Conflicts in protocol.c, because commit f410cbea9f3d ("tcp: annotate
  data-races around tp->window_clamp") has not been backported to this
  version. The conflict is easy to resolve, because only the context is
  different, but not the line to modify. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/mptcp/protocol.c

index 78ac5c538e139fa7bae602017e8c1ac38a772f28..1acd4e37a0ea6c111f73d00d593b5f1c6c91a9e6 100644 (file)
@@ -2057,7 +2057,8 @@ static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied)
                                slow = lock_sock_fast(ssk);
                                WRITE_ONCE(ssk->sk_rcvbuf, rcvbuf);
                                tcp_sk(ssk)->window_clamp = window_clamp;
-                               tcp_cleanup_rbuf(ssk, 1);
+                               if (tcp_can_send_ack(ssk))
+                                       tcp_cleanup_rbuf(ssk, 1);
                                unlock_sock_fast(ssk, slow);
                        }
                }