syzbot reported a KMSAN uninit-value warning in irqentry_exit_to_kernel_mode_preempt(). This is a false positive caused by the initialization of `ret` in irqentry_enter_from_kernel_mode() occurring in uninstrumented (noinstr) code. Because the initialization is untracked, KMSAN considers the state variable uninitialized when it is later passed into the instrumented code of irqentry_exit_to_kernel_mode_preempt(). The same issue exists in irqentry_nmi_enter(), where `irq_state` is initialized in noinstr code and later passed to the instrumented irqentry_nmi_exit(). Fix this by explicitly calling kmsan_unpoison_memory() on the `ret` and `irq_state` objects inside the instrumentation_begin() blocks of irqentry_enter_from_kernel_mode() and irqentry_nmi_enter(), respectively, immediately alongside the kmsan_unpoison_entry_regs() calls. Fixes: c5538d0141b3 ("entry: Split kernel mode logic from irqentry_{enter,exit}()") Fixes: 6cae637fa26d ("entry: kmsan: introduce kmsan_unpoison_entry_regs()") Cc: Dmitry Vyukov Cc: Jinjie Ruan Cc: Kuniyuki Iwashima Cc: Matthieu Baerts (NGI0) Cc: Mark Rutland Cc: Paolo Abeni Reported-by: syzbot+cdcfd55737fe43eeb3a3@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/69e7ee1f.a00a0220.17a17.001d.GAE@google.com/T/ Signed-off-by: Alexander Potapenko --- include/linux/irq-entry-common.h | 2 ++ kernel/entry/common.c | 1 + 2 files changed, 3 insertions(+) diff --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/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(); -- 2.54.0.563.g4f69b47b94-goog