[PATCH 0/6 v14] KASan for Arm

Ard Biesheuvel ardb at kernel.org
Sun Oct 4 05:09:27 EDT 2020


On Sun, 4 Oct 2020 at 10:41, Ard Biesheuvel <ardb at kernel.org> wrote:
>
> On Sun, 4 Oct 2020 at 10:06, Ard Biesheuvel <ardb at kernel.org> wrote:
> >
> > On Sat, 3 Oct 2020 at 17:50, Ard Biesheuvel <ardb at kernel.org> wrote:
> > >
> > > On Thu, 1 Oct 2020 at 21:19, Florian Fainelli <f.fainelli at gmail.com> wrote:
> > > >
> > > >
> > > >
> > > > On 10/1/2020 8:22 AM, Linus Walleij wrote:
> > > > > This is the 14th iteration of KASan for ARM/Aarch32.
> > > > >
> > > > > I have added one patch in the beginning of the series to
> > > > > fix the issue when the DTB (often attached DTB) ends up
> > > > > in lowmem. It also amends ARM to copy the device tree
> > > > > instead of just unflattening it and using it from where
> > > > > it is.
> > > > >
> > > > > This fixes my particular issue on the Qualcomm APQ8060
> > > > > and I hope it may also solve Florian's issue and what
> > > > > Ard has been seeing. If you inspect patch 1/6 you can
> > > > > see what has been going on for me. My hypothesis about
> > > > > what was going on was mostly right.
> > > > >
> > > > > You are encouraged to test this patch set to find memory out
> > > > > of bounds bugs with ARM32 platforms and drivers.
> > > > >
> > > > > There is a git branch you can pull in:
> > > > > https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=kasan
> > > >
> > > > It does appear to be slight better, although all platforms that I have
> > > > where memory starts at physical address 0 cannot boot, attached logs
> > > > which are all more or less the same.
> > > >
> > > > The physical memory map looks like this:
> > > >
> > > > 0..3GB -> DRAM
> > > > 3GB..4GB -> Registers, Boot ROM, Boot SRAM
> > > > 4GB..12GB -> DRAM extension
> > > >
> > > > Do any of the platforms you use for testing have a similar memory map?
> > > > Could you try to contrive a QEMU machine to have something similar in
> > > > case that helps reproducing these failures?
> > > >
> > >
> > > I am getting very similar failures on a Raspberry Pi4 booting in
> > > 32-bit mode from U-boot+EFI
> > >
> > > Full log attached.
> > >
> > > I will try to dig a bit deeper.
> >
> > OK, one obvious issue with the code as-is is that the following routine
> >
> > static __init void *kasan_alloc_block(size_t size)
> > {
> >   return memblock_alloc_try_nid(size, size, __pa(MAX_DMA_ADDRESS),
> >                                 MEMBLOCK_ALLOC_KASAN, NUMA_NO_NODE);
> > }
> >
> > is called after the early shadow is unmapped, but before the permanent
> > shadow is in place. memblock_alloc_try_nid() clears the newly
> > allocated memory using memset(), which checks the associated shadow,
> > which is unmapped -> BOOM.
> >
> > With the following implementation, I can avoid the crash similar to
> > the one Florian is reporting:
> >
> > static __init void *kasan_alloc_block(size_t size)
> > {
> >   void *p = memblock_alloc_try_nid_raw(size, size,
> >     __pa(MAX_DMA_ADDRESS), MEMBLOCK_ALLOC_KASAN,
> >     NUMA_NO_NODE);
> >
> >   if (p)
> >     __memset(p, 0, size);
> >   return p;
> > }
> >
> > However, I still get a hang a bit later, and I haven't tracked that down yet.
>
> The above issue appears to be related to TLB maintenance. So keeping
> kasan_alloc_block() as is, and doing
>
> --- a/arch/arm/mm/kasan_init.c
> +++ b/arch/arm/mm/kasan_init.c
> @@ -223,6 +223,8 @@ void __init kasan_init(void)
>                 __pgd(__pa(tmp_pmd_table) | PMD_TYPE_TABLE | L_PGD_SWAPPER));
>  #endif
>         cpu_switch_mm(tmp_pgd_table, &init_mm);
> +       local_flush_tlb_all();
> +
>         clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);
>
>         kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START),
>
> instead fixes the crash as well.
>
> Still have the hang right after though ..

OK, booting now - turns out the switch back to swapper_pg_dir needs a
proper TLB flush as well.

Full patch below - with that applied, I can boot the RPi4 to the point
where it wants to mount the rootfs (but I don't have a 32-bit rootfs
at hand)


The first change avoids reallocating KASAN blocks when a range gets
mapped twice - this occurs when mapping the DTB space explicitly
(although I am not sure that that is still needed now that you move
the DTB)

diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c
index 6fd9bc70970f..6877212a370d 100644
--- a/arch/arm/mm/kasan_init.c
+++ b/arch/arm/mm/kasan_init.c
@@ -45,11 +45,15 @@

        do {
                pte_t entry;
+               void *p;

                next = addr + PAGE_SIZE;

                if (!early) {
-                       void *p = kasan_alloc_block(PAGE_SIZE);
+                       if (!pte_none(READ_ONCE(*ptep)))
+                               continue;
+
+                       p = kasan_alloc_block(PAGE_SIZE);
                        if (!p) {
                                panic("%s failed to alloc pte for
address 0x%lx\n",
                                      __func__, addr);
@@ -223,11 +227,15 @@
                __pgd(__pa(tmp_pmd_table) | PMD_TYPE_TABLE | L_PGD_SWAPPER));
 #endif
        cpu_switch_mm(tmp_pgd_table, &init_mm);
+       local_flush_tlb_all();
+
        clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END);

        kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START),
                                    kasan_mem_to_shadow((void *)-1UL) + 1);

+       __memblock_dump_all();
+
        for_each_memblock(memory, reg) {
                void *start = __va(reg->base);
                void *end = __va(reg->base + reg->size);
@@ -277,10 +285,11 @@
                           pfn_pte(virt_to_pfn(kasan_early_shadow_page),
                                __pgprot(pgprot_val(PAGE_KERNEL)
                                         | L_PTE_RDONLY)));
+
+       cpu_switch_mm(swapper_pg_dir, &init_mm);
        local_flush_tlb_all();

        memset(kasan_early_shadow_page, 0, PAGE_SIZE);
-       cpu_switch_mm(swapper_pg_dir, &init_mm);
        pr_info("Kernel address sanitizer initialized\n");
        init_task.kasan_depth = 0;
 }

Full boot log attached.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: screen-exchange
Type: application/octet-stream
Size: 23457 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20201004/adbf4bd5/attachment-0001.obj>


More information about the linux-arm-kernel mailing list