Re: [syzbot] [mptcp?] KMSAN: uninit-value in mptcp_established_options

From: Matthieu Baerts

Date: Tue May 12 2026 - 05:02:32 EST


Hi Alexander,

On 08/05/2026 12:46, Matthieu Baerts wrote:
> Hi Alexander,
>
> Thank you for your reply!
>
> On 08/05/2026 12:11, Alexander Potapenko wrote:
>> On Fri, May 8, 2026 at 11:27 AM 'Paolo Abeni' via syzkaller-bugs
>> <syzkaller-bugs@xxxxxxxxxxxxxxxx> wrote:
>>>
>>> On 5/7/26 9:44 AM, Matthieu Baerts wrote:
>>>> Hi Paolo, Kuniyuki,
>>>>
>>>> On 04/05/2026 20:20, syzbot wrote:
>>>>> Hello,
>>>>>
>>>>> syzbot has tested the proposed patch but the reproducer is still triggering an issue:
>>>>> KMSAN: uninit-value in irqentry_exit_to_kernel_mode_preempt
>>>>
>>>> It looks like the issue is different now:
>>>>
>>>>> =====================================================
>>>>> BUG: KMSAN: uninit-value in irqentry_exit_to_kernel_mode_preempt+0xb0/0xc0 include/linux/irq-entry-common.h:472
>>>>> irqentry_exit_to_kernel_mode_preempt+0xb0/0xc0 include/linux/irq-entry-common.h:472
>>>>> irqentry_exit_to_kernel_mode include/linux/irq-entry-common.h:547 [inline]
>>>>> irqentry_exit+0x7b/0x760 kernel/entry/common.c:164
>>>>> sysvec_apic_timer_interrupt+0x52/0x90 arch/x86/kernel/apic/apic.c:1061
>>>>> asm_sysvec_apic_timer_interrupt+0x1f/0x30 arch/x86/include/asm/idtentry.h:697
>>>>> kmsan_get_metadata+0x17/0x160 mm/kmsan/shadow.c:125
>>>>> kmsan_get_shadow_origin_ptr+0x4a/0xb0 mm/kmsan/shadow.c:102
>>>>> get_shadow_origin_ptr mm/kmsan/instrumentation.c:38 [inline]
>>>>> __msan_metadata_ptr_for_load_4+0x24/0x40 mm/kmsan/instrumentation.c:93
>>>>> tcp_data_queue+0xdc/0x7c90 net/ipv4/tcp_input.c:5589
>>>>> tcp_rcv_established+0x19bb/0x3200 net/ipv4/tcp_input.c:6656
>>>>> tcp_v4_do_rcv+0xc4b/0x1b10 net/ipv4/tcp_ipv4.c:1852
>>>>> sk_backlog_rcv include/net/sock.h:1190 [inline]
>>>>
>>>> That's the input side.
>>>>
>>>>> __release_sock+0x360/0x7d0 net/core/sock.c:3216
>>>>> release_sock+0x22d/0x300 net/core/sock.c:3815
>>>>> mptcp_subflow_shutdown+0x358/0x690 net/mptcp/protocol.c:3144
>>>>> 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_syscall_64+0x236/0xf80 arch/x86/entry/syscall_64.c:100
>>>>> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>>>>>
>>>>> Local variable mp_opt created at:
>>>>> mptcp_incoming_options+0x11d/0x43b0 net/mptcp/options.c:1171
>>>>
>>>> Confirmed here. With "struct mptcp_options_received" while the original
>>>> issue was with "struct mptcp_out_options".
>>>>
>>>> Plus I'm not exactly sure to understand the issue here: mp_opt is
>>>> defined and used only in mptcp_incoming_options(), and I don't see
>>>> anything using it after the end of this function. Or did I miss something?
>>>
>>> I also had hard time understanding the backtrace, I think some frames
>>> are omitted/missing (it happens sometime, IDK why), specifically the one
>>> related to mptcp_options_received() - which would be useful to
>>> understand the issue.
>>
>> This is probably related to
>> https://lore.kernel.org/all/69e7ee1f.a00a0220.17a17.001d.GAE@xxxxxxxxxx/T/
>
> Ah yes, it looks similar.
>
>> Let me send the patch, perhaps this issue will also go away.
>
> That would be great, thank you!

Thank you for having sent your patch.

Here is one combining your modifications, and the ones from Paolo, for
syzbot. If this one is OK, we can continue with Paolo's patch.

#syz test

Cheers,
Mattdiff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
index 167fba7dbf04..be47d430d521 100644
--- a/include/linux/irq-entry-common.h
+++ b/include/linux/irq-entry-common.h
@@ -427,6 +427,7 @@ static __always_inline irqentry_state_t irqentry_enter_from_kernel_mode(struct p
ct_irq_enter();
instrumentation_begin();
kmsan_unpoison_entry_regs(regs);
+ kmsan_unpoison_memory(&ret, sizeof(ret));
trace_hardirqs_off_finish();
instrumentation_end();

@@ -443,6 +444,7 @@ static __always_inline irqentry_state_t irqentry_enter_from_kernel_mode(struct p
lockdep_hardirqs_off(CALLER_ADDR0);
instrumentation_begin();
kmsan_unpoison_entry_regs(regs);
+ kmsan_unpoison_memory(&ret, sizeof(ret));
rcu_irq_enter_check_tick();
trace_hardirqs_off_finish();
instrumentation_end();
diff --git a/include/net/mptcp.h b/include/net/mptcp.h
index f7263fe2a2e4..0763fd6f7758 100644
--- a/include/net/mptcp.h
+++ b/include/net/mptcp.h
@@ -27,6 +27,9 @@ struct mptcp_ext {
u32 subflow_seq;
u16 data_len;
__sum16 csum;
+
+ struct_group(flags,
+
u8 use_map:1,
dsn64:1,
data_fin:1,
@@ -38,6 +41,8 @@ struct mptcp_ext {
u8 reset_reason:4,
csum_reqd:1,
infinite_map:1;
+
+ ); /* end of flags group */
};

#define MPTCPOPT_HMAC_LEN 20
diff --git a/kernel/entry/common.c b/kernel/entry/common.c
index 19d2244a9fef..390364943f92 100644
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
@@ -177,6 +177,7 @@ irqentry_state_t noinstr irqentry_nmi_enter(struct pt_regs *regs)

instrumentation_begin();
kmsan_unpoison_entry_regs(regs);
+ kmsan_unpoison_memory(&irq_state, sizeof(irq_state));
trace_hardirqs_off_finish();
ftrace_nmi_enter();
instrumentation_end();
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 8a1c5698983c..3fd40dbff82b 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -572,6 +572,11 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
bool ret = false;
u64 ack_seq;

+ /* Zero `can_ack` and `use_map` flags with one shot. */
+ BUILD_BUG_ON(sizeof_field(struct mptcp_ext, flags) != sizeof(u16));
+ BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct mptcp_ext, flags),
+ sizeof(u16)));
+ *(u16 *)&opts->ext_copy.flags = 0;
opts->csum_reqd = READ_ONCE(msk->csum_enabled);
mpext = skb ? mptcp_get_ext(skb) : NULL;

@@ -595,7 +600,6 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb,
/* passive sockets msk will set the 'can_ack' after accept(), even
* if the first subflow may have the already the remote key handy
*/
- opts->ext_copy.use_ack = 0;
if (!READ_ONCE(msk->can_ack)) {
*size = ALIGN(dss_size, 4);
return ret;