Re: [PATCH v3 28/46] kmsan: entry: handle register passing from uninstrumented code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, May 9, 2022 at 6:50 PM Alexander Potapenko <glider@xxxxxxxxxx> 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@xxxxxxxxxx/#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..."




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux