[PATCH mptcp-net v2] mptcp: fix divide-by-zero in __mptcp_push_pending close path

Shardul Bankar posted 1 patch 16 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/multipath-tcp/mptcp_net-next tags/patchew/20260525003233.857172-1-shardul.b@mpiricsoftware.com
net/mptcp/protocol.c | 6 ++++++
1 file changed, 6 insertions(+)
[PATCH mptcp-net v2] mptcp: fix divide-by-zero in __mptcp_push_pending close path
Posted by Shardul Bankar 16 hours ago
A divide-by-zero in tcp_tso_segs() is reachable via __mptcp_close_ssk ->
__mptcp_push_pending -> mptcp_push_release(ssk, &info) with info.mss_now
== 0, triggered by MPTCP_PM_CMD_FLUSH_ADDRS.  __mptcp_close_ssk() leaves
the ssk in a state where __tcp_can_send() is false (FIN_WAIT1/2, CLOSING,
LAST_ACK) and then unconditionally calls __mptcp_push_pending(sk, 0).
For such an ssk, mptcp_sendmsg_frag() returns -EAGAIN before reaching
its tcp_send_mss(), so info.mss_now stays 0 when the trailing
mptcp_push_release() feeds it into tcp_push() -> tcp_tso_autosize().

Commit 1094c6fe7280 ("mptcp: fix possible divide by zero") covered the
alloc-failure branch by moving tcp_send_mss() before allocation; it does
not cover this -EAGAIN-before-tcp_send_mss() case.

When __subflow_push_pending() returns <= 0 in __mptcp_push_pending(),
release ssk and clear the pointer in the existing failure branch, so
the trailing mptcp_push_release(ssk, &info) short-circuits on a failed
last iteration: info.mss_now == 0 cannot reach tcp_tso_segs().

Found by an MPTCP protocol-flow harness extending BRF
(arXiv:2305.08782) via the MPTCP_PM_CMD_FLUSH_ADDRS kernel-PM admin
path; the oops is reached on the first qualifying run.

Fixes: 724cfd2ee8aa ("mptcp: allocate TX skbs in msk context")
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Shardul Bankar <shardul.b@mpiricsoftware.com>
---
v2:
- Replace the __subflow_push_pending() entry-init with the slow-path
  release_sock(ssk) + ssk=NULL inside the existing ret<=0 branch of
  __mptcp_push_pending() (Paolo).  Keeps the fix at the actual exit
  point where the invariant fails and removes the per-iteration cost
  in the hot send path.
- Reproducer status: syz-manager's auto-reducer returned 0 on the
  original hit; a syz-crush replay of the harness workdir log against
  the unpatched build is ongoing.

Link to v1: https://lore.kernel.org/all/20260523211800.2952905-1-shardul.b@mpiricsoftware.com/

 net/mptcp/protocol.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index a72a6ad6ee8b1..44c8d048679e9 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1711,6 +1711,12 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
 					    (1 << ssk->sk_state) &
 					     (TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSE))
 						push_count--;
+
+					/* Prevent the trailing mptcp_push_release()
+					 * from pushing data with mss_now == 0.
+					 */
+					release_sock(ssk);
+					ssk = NULL;
 					continue;
 				}
 				copied = true;

base-commit: 6c7a815d6a7192e42bb1875202df1d48c3a83e64
-- 
2.34.1
Re: [PATCH mptcp-net v2] mptcp: fix divide-by-zero in __mptcp_push_pending close path
Posted by MPTCP CI 15 hours ago
Hi Shardul,

Thank you for your modifications, that's great!

Our CI did some validations and here is its report:

- KVM Validation: normal (except selftest_mptcp_join): Unstable: 7 failed test(s): packetdrill_dss packetdrill_sockopts selftest_mptcp_connect selftest_mptcp_connect_checksum selftest_mptcp_connect_mmap selftest_mptcp_connect_sendfile selftest_mptcp_connect_splice ⚠️ 
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Unstable: 7 failed test(s): packetdrill_dss packetdrill_sockopts selftest_mptcp_connect selftest_mptcp_connect_checksum selftest_mptcp_connect_mmap selftest_mptcp_connect_sendfile selftest_mptcp_connect_splice ⚠️ 
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Unstable: 1 failed test(s): bpftest_test_progs-no_alu32_mptcp ⚠️ 
- KVM Validation: btf-debug (only bpftest_all): Unstable: 1 failed test(s): bpftest_test_progs-no_alu32_mptcp ⚠️ 
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/26377768525

Initiator: Patchew Applier
Commits: https://github.com/multipath-tcp/mptcp_net-next/commits/6fcb9bbec4aa
Patchwork: https://patchwork.kernel.org/project/mptcp/list/?series=1100122


If there are some issues, you can reproduce them using the same environment as
the one used by the CI thanks to a docker image, e.g.:

    $ cd [kernel source code]
    $ docker run -v "${PWD}:${PWD}:rw" -w "${PWD}" --privileged --rm -it \
        --pull always mptcp/mptcp-upstream-virtme-docker:latest \
        auto-normal

For more details:

    https://github.com/multipath-tcp/mptcp-upstream-virtme-docker


Please note that despite all the efforts that have been already done to have a
stable tests suite when executed on a public CI like here, it is possible some
reported issues are not due to your modifications. Still, do not hesitate to
help us improve that ;-)

Cheers,
MPTCP GH Action bot
Bot operated by Matthieu Baerts (NGI0 Core)
Re: [PATCH mptcp-net v2] mptcp: fix divide-by-zero in __mptcp_push_pending close path
Posted by Paolo Abeni 8 hours ago
On 5/25/26 3:44 AM, MPTCP CI wrote:
> Thank you for your modifications, that's great!
> 
> Our CI did some validations and here is its report:
> 
> - KVM Validation: normal (except selftest_mptcp_join): Unstable: 7 failed test(s): packetdrill_dss packetdrill_sockopts selftest_mptcp_connect selftest_mptcp_connect_checksum selftest_mptcp_connect_mmap selftest_mptcp_connect_sendfile selftest_mptcp_connect_splice ⚠️ 
> - KVM Validation: normal (only selftest_mptcp_join): Success! ✅
> - KVM Validation: debug (except selftest_mptcp_join): Unstable: 7 failed test(s): packetdrill_dss packetdrill_sockopts selftest_mptcp_connect selftest_mptcp_connect_checksum selftest_mptcp_connect_mmap selftest_mptcp_connect_sendfile selftest_mptcp_connect_splice ⚠️ 

The above failures look real. I guess the check I suggested is a bit too
rough. Could you please double check the failures are due to this change
and ev. try to refine it?

Thanks,

Paolo