https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85230

            Bug ID: 85230
           Summary: asan: false positives in kernel on allocas
           Product: gcc
           Version: 8.0.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dvyukov at google dot com
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at 
gcc dot gnu.org
  Target Milestone: ---

We are seeing what looks like false positives related to KASAN alloca
instrumentation and interrupt handlers. I don't have full picture yet, but want
to document what I know now in case one can spot something obvious in asan.c

This is on gcc version 8.0.1 20180301 (experimental) (GCC).

Here are 2 examples of presumably false KASAN reports:

https://gist.githubusercontent.com/dvyukov/eb7d0edadae48e4a0a2fa751bacb11d7/raw/1b719820c9965168fb8ab281b2fb8b6af63d50b5/gistfile1.txt
https://gist.githubusercontent.com/dvyukov/607155ff7a5696cac565975a338f091b/raw/073662fb5f5bfb4893e00a86acbbac9bdf6e1d9b/gistfile1.txt

This is on upstream kernel commit 17dec0a949153d9ac00760ba2f5b78cb583e995f.

All reports has some similarities, namely:
 - all happen in interrupt code
 - when interrupt code accesses pt_regs object which contains saved registers
and which is stored on the _task_ stack before switching to interrupt stack
 - interrupt arrives into __asan_allocas_unpoison function
 - usually happens inside of crypto_shash_update which contains an alloca, but
I suspect it's red herring (we just need a function that uses alloca and there
are few of them)

This all strongly points in the direction of violated -mno-red-zone (which
kernel uses e.g. for interrupts). It seems that saved registers in interrupt
entry somehow land onto alloca-ed region which is not yet unpoisoned.

Here is disasm of the crypto_shash_update function (you can see 3
alloca-related calls there):
https://gist.githubusercontent.com/dvyukov/a55eefef7bb5c305ff4eb91e127524fc/raw/81f2c4d13ae4d46d90a3a6f6c7119a4066ac3a66/gistfile1.txt

I thought that maybe code first deallocates the alloca memory on stack, and
only then unpoisons it. But no, it first unpoisons and then restores rsp.

It's also strange that it always happens inside of __asan_allocas_unpoison and
not in crypto_shash_update itself. If anything allocating more frames should
divert interrupt handler further from poisoned memory. However, maybe it's a
coincidence, or maybe when interrupt arrived right into crypto_shash_update,
pt_regs accidentally land in between poisoned regions.

Just in case, I've also tried to unpoison more in __asan_allocas_unpoison:

void __asan_allocas_unpoison(const void *stack_top, const void *stack_bottom)
{
        if (unlikely(!stack_top))
                return;
+       stack_bottom += 64;
+       stack_top -= 64;
        if (unlikely(stack_top > stack_bottom))
                return;
        kasan_unpoison_shadow(stack_top, stack_bottom - stack_top);
}

trying to cross out any off-by-ones. But this does not help.

Reply via email to