6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arthur Mongodin amongodin@randorisec.fr
commit 2c1f97a52cb827a5f2768e67a9dddffae1ed47ab upstream.
Because of the size restriction in the TCP options space, the MPTCP ADD_ADDR option is exclusive and cannot be sent with other MPTCP ones. For this reason, in the linked mptcp_out_options structure, group of fields linked to different options are part of the same union.
There is a case where the mptcp_pm_add_addr_signal() function can modify opts->addr, but not ended up sending an ADD_ADDR. Later on, back in mptcp_established_options, other options will be sent, but with unexpected data written in other fields due to the union, e.g. in opts->ext_copy. This could lead to a data stream corruption in the next packet.
Using an intermediate variable, prevents from corrupting previously established DSS option. The assignment of the ADD_ADDR option parameters is now done once we are sure this ADD_ADDR option can be set in the packet, e.g. after having dropped other suboptions.
Fixes: 1bff1e43a30e ("mptcp: optimize out option generation") Cc: stable@vger.kernel.org Suggested-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Arthur Mongodin amongodin@randorisec.fr Reviewed-by: Matthieu Baerts (NGI0) matttbe@kernel.org [ Matt: the commit message has been updated: long lines splits and some clarifications. ] Signed-off-by: Matthieu Baerts (NGI0) matttbe@kernel.org Reviewed-by: Simon Horman horms@kernel.org Link: https://patch.msgid.link/20250314-net-mptcp-fix-data-stream-corr-sockopt-v1-... Signed-off-by: Paolo Abeni pabeni@redhat.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/mptcp/options.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
--- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -649,6 +649,7 @@ static bool mptcp_established_options_ad struct mptcp_sock *msk = mptcp_sk(subflow->conn); bool drop_other_suboptions = false; unsigned int opt_size = *size; + struct mptcp_addr_info addr; bool echo; int len;
@@ -657,7 +658,7 @@ static bool mptcp_established_options_ad */ if (!mptcp_pm_should_add_signal(msk) || (opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) || - !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, &opts->addr, + !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, &addr, &echo, &drop_other_suboptions)) return false;
@@ -670,7 +671,7 @@ static bool mptcp_established_options_ad else if (opts->suboptions & OPTION_MPTCP_DSS) return false;
- len = mptcp_add_addr_len(opts->addr.family, echo, !!opts->addr.port); + len = mptcp_add_addr_len(addr.family, echo, !!addr.port); if (remaining < len) return false;
@@ -687,6 +688,7 @@ static bool mptcp_established_options_ad opts->ahmac = 0; *size -= opt_size; } + opts->addr = addr; opts->suboptions |= OPTION_MPTCP_ADD_ADDR; if (!echo) { opts->ahmac = add_addr_generate_hmac(msk->local_key,