[PATCH v1 mptcp] mptcp: Clear mptcp_out_options.ext_copy in mptcp_established_options_dss().

Kuniyuki Iwashima posted 1 patch 4 days, 3 hours ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/multipath-tcp/mptcp_net-next tags/patchew/20260501061939.1808489-1-kuniyu@google.com
net/mptcp/options.c | 1 +
1 file changed, 1 insertion(+)
[PATCH v1 mptcp] mptcp: Clear mptcp_out_options.ext_copy in mptcp_established_options_dss().
Posted by Kuniyuki Iwashima 4 days, 3 hours ago
syzbot reported read of uninit-value in mptcp_write_data_fin().

Since the cited commit, struct mptcp_out_options is not cleared
in __tcp_transmit_skb().

Let's clear it in mptcp_established_options_dss().

Another option is to move struct mptcp_out_options to struct
tcp_out_options.cleared, but this memset() is not needed for TCP.

[0]:
BUG: KMSAN: uninit-value in mptcp_write_data_fin net/mptcp/options.c:542 [inline]
BUG: KMSAN: uninit-value in mptcp_established_options_dss net/mptcp/options.c:590 [inline]
BUG: KMSAN: uninit-value in mptcp_established_options+0x112f/0x3530 net/mptcp/options.c:874
 mptcp_write_data_fin net/mptcp/options.c:542 [inline]
 mptcp_established_options_dss net/mptcp/options.c:590 [inline]
 mptcp_established_options+0x112f/0x3530 net/mptcp/options.c:874
 tcp_established_options+0x312/0xcc0 net/ipv4/tcp_output.c:1192
 __tcp_transmit_skb+0x5dc/0x5fe0 net/ipv4/tcp_output.c:1575
 __tcp_send_ack+0x967/0xad0 net/ipv4/tcp_output.c:4499
 tcp_send_ack+0x3d/0x60 net/ipv4/tcp_output.c:4505
 mptcp_subflow_shutdown+0x164/0x690 net/mptcp/protocol.c:3137
 mptcp_check_send_data_fin+0x31b/0x3d0 net/mptcp/protocol.c:3218
 __mptcp_wr_shutdown net/mptcp/protocol.c:3234 [inline]
 __mptcp_close+0x860/0x1360 net/mptcp/protocol.c:3313
 mptcp_close+0x42/0x260 net/mptcp/protocol.c:3367
 inet_release+0x1ee/0x2a0 net/ipv4/af_inet.c:442
 __sock_release net/socket.c:722 [inline]
 sock_close+0xd6/0x2f0 net/socket.c:1514
 __fput+0x60e/0x1010 fs/file_table.c:510
 ____fput+0x25/0x30 fs/file_table.c:538
 task_work_run+0x208/0x2b0 kernel/task_work.c:233
 resume_user_mode_work include/linux/resume_user_mode.h:50 [inline]
 __exit_to_user_mode_loop kernel/entry/common.c:67 [inline]
 exit_to_user_mode_loop+0x306/0x1b60 kernel/entry/common.c:98
 __exit_to_user_mode_prepare include/linux/irq-entry-common.h:207 [inline]
 syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:238 [inline]
 syscall_exit_to_user_mode include/linux/entry-common.h:318 [inline]
 __do_fast_syscall_32+0x2c7/0x460 arch/x86/entry/syscall_32.c:310
 do_fast_syscall_32+0x37/0x80 arch/x86/entry/syscall_32.c:332
 do_SYSENTER_32+0x1f/0x30 arch/x86/entry/syscall_32.c:370
 entry_SYSENTER_compat_after_hwframe+0x84/0x8e

Local variable opts created at:
 __tcp_transmit_skb+0x4d/0x5fe0 net/ipv4/tcp_output.c:1536
 __tcp_send_ack+0x967/0xad0 net/ipv4/tcp_output.c:4499

CPU: 1 UID: 0 PID: 5855 Comm: syz.3.4 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/18/2026

Fixes: cfcceb7a39fc ("tcp: shrink per-packet memset in __tcp_transmit_skb()")
Reported-by: syzbot+ff020673c5e3d94d9478@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/mptcp/69f44505.050a0220.3cbe47.0008.GAE@google.com/
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
 net/mptcp/options.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 8a1c5698983c..3fb914196987 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -572,6 +572,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
 	bool ret = false;
 	u64 ack_seq;
 
+	memset(&opts->ext_copy, 0, sizeof(opts->ext_copy));
 	opts->csum_reqd = READ_ONCE(msk->csum_enabled);
 	mpext = skb ? mptcp_get_ext(skb) : NULL;
 
-- 
2.54.0.545.g6539524ca2-goog
Re: [PATCH v1 mptcp] mptcp: Clear mptcp_out_options.ext_copy in mptcp_established_options_dss().
Posted by Matthieu Baerts 3 days, 19 hours ago
On Fri, 01 May 2026 06:19:35 +0000, Kuniyuki Iwashima <kuniyu@google.com> wrote:
> syzbot reported read of uninit-value in mptcp_write_data_fin().
> 
> Since the cited commit, struct mptcp_out_options is not cleared
> in __tcp_transmit_skb().
> 
> Let's clear it in mptcp_established_options_dss().

Thank you for looking at that! I forgot to look at the bitfields that
can be half initialised when reviewing the cited commit...

> 
> Another option is to move struct mptcp_out_options to struct

Indeed.

>
>
> diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> index 4cc583fdc7a9..ae1cb955035b 100644
> --- a/net/mptcp/options.c
> +++ b/net/mptcp/options.c
> @@ -572,6 +572,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
>  	bool ret = false;
>  	u64 ack_seq;
>  
> +	memset(&opts->ext_copy, 0, sizeof(opts->ext_copy));
>  	opts->csum_reqd = READ_ONCE(msk->csum_enabled);

Sashiko is saying:

  Will the bitfield assignment to opts->csum_reqd still trigger a KMSAN warning?

  Looking at struct mptcp_out_options in include/net/mptcp.h, there are several
  bitfields that reside outside the ext_copy union:

  	u8 reset_reason:4,
  	   reset_transient:1,
  	   csum_reqd:1,
  	   allow_join_id0:1;

  Because __tcp_transmit_skb() allocates the mptcp_out_options structure on the
  stack without zeroing it, the byte containing these bitfields remains
  uninitialized.

  The compiler translates the bitfield assignment into a read-modify-write
  operation on that uninitialized byte, which will cause KMSAN to still report a
  read of uninitialized memory.

  -> via: https://sashiko.dev/#/message/20260501061939.1808489-1-kuniyu@google.com

That's the only other bitfield in this structure, but it is not next to
the other one, and with all the unions and inner structures, it might be
harder to introduce a new struct_group().

Maybe safer and easier for the moment to memset mptcp_out_options struct
before calling mptcp_{syn,synack,established}_options() from
tcp_output.c? Or from these functions. This will then only be done when
the TCP sk is being used by MPTCP, so that doesn't impact "plain" TCP
connections. WDYT?

(Or using two new unions to clear these bitfields with
'opts->cleared = 0' from mptcp_{syn,synack,established}_options() and
'opts->ext_copy.cleared = 0' from mptcp_established_options_dss()?)

-- 
Matthieu Baerts (NGI0) <matttbe@kernel.org>
Re: [PATCH v1 mptcp] mptcp: Clear mptcp_out_options.ext_copy in mptcp_established_options_dss().
Posted by Kuniyuki Iwashima 3 days, 16 hours ago
On Fri, May 1, 2026 at 7:30 AM Matthieu Baerts <matttbe@kernel.org> wrote:
>
> On Fri, 01 May 2026 06:19:35 +0000, Kuniyuki Iwashima <kuniyu@google.com> wrote:
> > syzbot reported read of uninit-value in mptcp_write_data_fin().
> >
> > Since the cited commit, struct mptcp_out_options is not cleared
> > in __tcp_transmit_skb().
> >
> > Let's clear it in mptcp_established_options_dss().
>
> Thank you for looking at that! I forgot to look at the bitfields that
> can be half initialised when reviewing the cited commit...
>
> >
> > Another option is to move struct mptcp_out_options to struct
>
> Indeed.
>
> >
> >
> > diff --git a/net/mptcp/options.c b/net/mptcp/options.c
> > index 4cc583fdc7a9..ae1cb955035b 100644
> > --- a/net/mptcp/options.c
> > +++ b/net/mptcp/options.c
> > @@ -572,6 +572,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
> >       bool ret = false;
> >       u64 ack_seq;
> >
> > +     memset(&opts->ext_copy, 0, sizeof(opts->ext_copy));
> >       opts->csum_reqd = READ_ONCE(msk->csum_enabled);
>
> Sashiko is saying:
>
>   Will the bitfield assignment to opts->csum_reqd still trigger a KMSAN warning?
>
>   Looking at struct mptcp_out_options in include/net/mptcp.h, there are several
>   bitfields that reside outside the ext_copy union:
>
>         u8 reset_reason:4,
>            reset_transient:1,
>            csum_reqd:1,
>            allow_join_id0:1;
>
>   Because __tcp_transmit_skb() allocates the mptcp_out_options structure on the
>   stack without zeroing it, the byte containing these bitfields remains
>   uninitialized.

Oh this is right.

>
>   The compiler translates the bitfield assignment into a read-modify-write
>   operation on that uninitialized byte, which will cause KMSAN to still report a
>   read of uninitialized memory.
>
>   -> via: https://sashiko.dev/#/message/20260501061939.1808489-1-kuniyu@google.com
>
> That's the only other bitfield in this structure, but it is not next to
> the other one, and with all the unions and inner structures, it might be
> harder to introduce a new struct_group().
>
> Maybe safer and easier for the moment to memset mptcp_out_options struct
> before calling mptcp_{syn,synack,established}_options() from
> tcp_output.c? Or from these functions. This will then only be done when
> the TCP sk is being used by MPTCP, so that doesn't impact "plain" TCP
> connections. WDYT?

Sounds good, I'll simply clear the struct in the mptcp functions.

Thanks !
Re: [PATCH v1 mptcp] mptcp: Clear mptcp_out_options.ext_copy in mptcp_established_options_dss().
Posted by MPTCP CI 4 days, 2 hours ago
Hi Kuniyuki,

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): Success! ✅
- KVM Validation: normal (only selftest_mptcp_join): Success! ✅
- KVM Validation: debug (except selftest_mptcp_join): Unstable: 1 failed test(s): packetdrill_mp_capable ⚠️ 
- KVM Validation: debug (only selftest_mptcp_join): Success! ✅
- KVM Validation: btf-normal (only bpftest_all): Success! ✅
- KVM Validation: btf-debug (only bpftest_all): Success! ✅
- Task: https://github.com/multipath-tcp/mptcp_net-next/actions/runs/25205245139

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


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)