[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAG_fn=X8mc9-_-S-+b9HuF4_-PhN3=1umu5twY8oYn1OgRhuLg@mail.gmail.com>
Date: Mon, 9 May 2022 18:51:59 +0200
From: Alexander Potapenko <glider@...gle.com>
To: Thomas Gleixner <tglx@...utronix.de>
Cc: Alexander Viro <viro@...iv.linux.org.uk>,
Andrew Morton <akpm@...ux-foundation.org>,
Andrey Konovalov <andreyknvl@...gle.com>,
Andy Lutomirski <luto@...nel.org>,
Arnd Bergmann <arnd@...db.de>, Borislav Petkov <bp@...en8.de>,
Christoph Hellwig <hch@....de>,
Christoph Lameter <cl@...ux.com>,
David Rientjes <rientjes@...gle.com>,
Dmitry Vyukov <dvyukov@...gle.com>,
Eric Dumazet <edumazet@...gle.com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Herbert Xu <herbert@...dor.apana.org.au>,
Ilya Leoshkevich <iii@...ux.ibm.com>,
Ingo Molnar <mingo@...hat.com>, Jens Axboe <axboe@...nel.dk>,
Joonsoo Kim <iamjoonsoo.kim@....com>,
Kees Cook <keescook@...omium.org>,
Marco Elver <elver@...gle.com>,
Mark Rutland <mark.rutland@....com>,
Matthew Wilcox <willy@...radead.org>,
"Michael S. Tsirkin" <mst@...hat.com>,
Pekka Enberg <penberg@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Petr Mladek <pmladek@...e.com>,
Steven Rostedt <rostedt@...dmis.org>,
Vasily Gorbik <gor@...ux.ibm.com>,
Vegard Nossum <vegard.nossum@...cle.com>,
Vlastimil Babka <vbabka@...e.cz>,
kasan-dev <kasan-dev@...glegroups.com>,
Linux Memory Management List <linux-mm@...ck.org>,
Linux-Arch <linux-arch@...r.kernel.org>,
LKML <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v3 28/46] kmsan: entry: handle register passing from
uninstrumented code
On Mon, May 9, 2022 at 6:50 PM Alexander Potapenko <glider@...gle.com> wrote:
>
> > The callchain is:
> >
> > asm_sysvec_apic_timer_interrupt <- ASM entry in gate
> > sysvec_apic_timer_interrupt(regs) <- noinstr C entry point
> > irqentry_enter(regs) <- unpoisons @reg
> > __sysvec_apic_timer_interrupt(regs) <- the actual handler
> > set_irq_regs(regs) <- stores regs
> > local_apic_timer_interrupt()
> > ...
> > tick_handler() <- One of the 4 variants
> > regs = get_irq_regs(); <- retrieves regs
> > update_process_times(user_tick = user_mode(regs))
> > account_process_tick(user_tick)
> > irqtime_account_process_tick(user_tick)
> > line 382: } else if { user_tick } <- KMSAN complains
> >
> > I'm even more confused now.
>
> Ok, I think I know what's going on.
>
> Indeed, calling kmsan_unpoison_memory() in irqentry_enter() was
> supposed to be enough, but we have code in kmsan_unpoison_memory() (as
> well as other runtime functions) that checks for kmsan_in_runtime()
> and bails out to prevent potential recursion if KMSAN code starts
> calling itself.
>
> kmsan_in_runtime() is implemented as follows:
>
> ==============================================
> static __always_inline bool kmsan_in_runtime(void)
> {
> if ((hardirq_count() >> HARDIRQ_SHIFT) > 1)
> return true;
> return kmsan_get_context()->kmsan_in_runtime;
> }
> ==============================================
> (see the code here:
> https://lore.kernel.org/lkml/20220426164315.625149-13-glider@google.com/#Z31mm:kmsan:kmsan.h)
>
> If we are running in the task context (in_task()==true),
> kmsan_get_context() returns a per-task `struct *kmsan_ctx`.
> If `in_task()==false` and `hardirq_count()>>HARDIRQ_SHIFT==1`, it
> returns a per-CPU one.
> Otherwise kmsan_in_runtime() is considered true to avoid dealing with
> nested interrupts.
>
> So in the case when `hardirq_count()>>HARDIRQ_SHIFT` is greater than
> 1, kmsan_in_runtime() becomes a no-op, which leads to false positives.
Should be "kmsan_unpoison_memory() becomes a no-op..."
Powered by blists - more mailing lists