• Linus Walleij's avatar
    ARM: 9015/2: Define the virtual space of KASan's shadow region · c12366ba
    Linus Walleij authored
    Define KASAN_SHADOW_OFFSET,KASAN_SHADOW_START and KASAN_SHADOW_END for
    the Arm kernel address sanitizer. We are "stealing" lowmem (the 4GB
    addressable by a 32bit architecture) out of the virtual address
    space to use as shadow memory for KASan as follows:
    
     +----+ 0xffffffff
     |    |
     |    | |-> Static kernel image (vmlinux) BSS and page table
     |    |/
     +----+ PAGE_OFFSET
     |    |
     |    | |->  Loadable kernel modules virtual address space area
     |    |/
     +----+ MODULES_VADDR = KASAN_SHADOW_END
     |    |
     |    | |-> The shadow area of kernel virtual address.
     |    |/
     +----+->  TASK_SIZE (start of kernel space) = KASAN_SHADOW_START the
     |    |   shadow address of MODULES_VADDR
     |    | |
     |    | |
     |    | |-> The user space area in lowmem. The kernel address
     |    | |   sanitizer do not use this space, nor does it map it.
     |    | |
     |    | |
     |    | |
     |    | |
     |    |/
     ------ 0
    
    0 .. TASK_SIZE is the memory that can be used by shared
    userspace/kernelspace. It us used for userspace processes and for
    passing parameters and memory buffers in system calls etc. We do not
    need to shadow this area.
    
    KASAN_SHADOW_START:
     This value begins with the MODULE_VADDR's shadow address. It is the
     start of kernel virtual space. Since we have modules to load, we need
     to cover also that area with shadow memory so we can find memory
     bugs in modules.
    
    KASAN_SHADOW_END
     This value is the 0x100000000's shadow address: the mapping that would
     be after the end of the kernel memory at 0xffffffff. It is the end of
     kernel address sanitizer shadow area. It is also the start of the
     module area.
    
    KASAN_SHADOW_OFFSET:
     This value is used to map an address to the corresponding shadow
     address by the following formula:
    
       shadow_addr = (address >> 3) + KASAN_SHADOW_OFFSET;
    
     As you would expect, >> 3 is equal to dividing by 8, meaning each
     byte in the shadow memory covers 8 bytes of kernel memory, so one
     bit shadow memory per byte of kernel memory is used.
    
     The KASAN_SHADOW_OFFSET is provided in a Kconfig option depending
     on the VMSPLIT layout of the system: the kernel and userspace can
     split up lowmem in different ways according to needs, so we calculate
     the shadow offset depending on this.
    
    When kasan is enabled, the definition of TASK_SIZE is not an 8-bit
    rotated constant, so we need to modify the TASK_SIZE access code in the
    *.s file.
    
    The kernel and modules may use different amounts of memory,
    according to the VMSPLIT configuration, which in turn
    determines the PAGE_OFFSET.
    
    We use the following KASAN_SHADOW_OFFSETs depending on how the
    virtual memory is split up:
    
    - 0x1f000000 if we have 1G userspace / 3G kernelspace split:
      - The kernel address space is 3G (0xc0000000)
      - PAGE_OFFSET is then set to 0x40000000 so the kernel static
        image (vmlinux) uses addresses 0x40000000 .. 0xffffffff
      - On top of that we have the MODULES_VADDR which under
        the worst case (using ARM instructions) is
        PAGE_OFFSET - 16M (0x01000000) = 0x3f000000
        so the modules use addresses 0x3f000000 .. 0x3fffffff
      - So the addresses 0x3f000000 .. 0xffffffff need to be
        covered with shadow memory. That is 0xc1000000 bytes
        of memory.
      - 1/8 of that is needed for its shadow memory, so
        0x18200000 bytes of shadow memory is needed. We
        "steal" that from the remaining lowmem.
      - The KASAN_SHADOW_START becomes 0x26e00000, to
        KASAN_SHADOW_END at 0x3effffff.
      - Now we can calculate the KASAN_SHADOW_OFFSET for any
        kernel address as 0x3f000000 needs to map to the first
        byte of shadow memory and 0xffffffff needs to map to
        the last byte of shadow memory. Since:
        SHADOW_ADDR = (address >> 3) + KASAN_SHADOW_OFFSET
        0x26e00000 = (0x3f000000 >> 3) + KASAN_SHADOW_OFFSET
        KASAN_SHADOW_OFFSET = 0x26e00000 - (0x3f000000 >> 3)
        KASAN_SHADOW_OFFSET = 0x26e00000 - 0x07e00000
        KASAN_SHADOW_OFFSET = 0x1f000000
    
    - 0x5f000000 if we have 2G userspace / 2G kernelspace split:
      - The kernel space is 2G (0x80000000)
      - PAGE_OFFSET is set to 0x80000000 so the kernel static
        image uses 0x80000000 .. 0xffffffff.
      - On top of that we have the MODULES_VADDR which under
        the worst case (using ARM instructions) is
        PAGE_OFFSET - 16M (0x01000000) = 0x7f000000
        so the modules use addresses 0x7f000000 .. 0x7fffffff
      - So the addresses 0x7f000000 .. 0xffffffff need to be
        covered with shadow memory. That is 0x81000000 bytes
        of memory.
      - 1/8 of that is needed for its shadow memory, so
        0x10200000 bytes of shadow memory is needed. We
        "steal" that from the remaining lowmem.
      - The KASAN_SHADOW_START becomes 0x6ee00000, to
        KASAN_SHADOW_END at 0x7effffff.
      - Now we can calculate the KASAN_SHADOW_OFFSET for any
        kernel address as 0x7f000000 needs to map to the first
        byte of shadow memory and 0xffffffff needs to map to
        the last byte of shadow memory. Since:
        SHADOW_ADDR = (address >> 3) + KASAN_SHADOW_OFFSET
        0x6ee00000 = (0x7f000000 >> 3) + KASAN_SHADOW_OFFSET
        KASAN_SHADOW_OFFSET = 0x6ee00000 - (0x7f000000 >> 3)
        KASAN_SHADOW_OFFSET = 0x6ee00000 - 0x0fe00000
        KASAN_SHADOW_OFFSET = 0x5f000000
    
    - 0x9f000000 if we have 3G userspace / 1G kernelspace split,
      and this is the default split for ARM:
      - The kernel address space is 1GB (0x40000000)
      - PAGE_OFFSET is set to 0xc0000000 so the kernel static
        image uses 0xc0000000 .. 0xffffffff.
      - On top of that we have the MODULES_VADDR which under
        the worst case (using ARM instructions) is
        PAGE_OFFSET - 16M (0x01000000) = 0xbf000000
        so the modules use addresses 0xbf000000 .. 0xbfffffff
      - So the addresses 0xbf000000 .. 0xffffffff need to be
        covered with shadow memory. That is 0x41000000 bytes
        of memory.
      - 1/8 of that is needed for its shadow memory, so
        0x08200000 bytes of shadow memory is needed. We
        "steal" that from the remaining lowmem.
      - The KASAN_SHADOW_START becomes 0xb6e00000, to
        KASAN_SHADOW_END at 0xbfffffff.
      - Now we can calculate the KASAN_SHADOW_OFFSET for any
        kernel address as 0xbf000000 needs to map to the first
        byte of shadow memory and 0xffffffff needs to map to
        the last byte of shadow memory. Since:
        SHADOW_ADDR = (address >> 3) + KASAN_SHADOW_OFFSET
        0xb6e00000 = (0xbf000000 >> 3) + KASAN_SHADOW_OFFSET
        KASAN_SHADOW_OFFSET = 0xb6e00000 - (0xbf000000 >> 3)
        KASAN_SHADOW_OFFSET = 0xb6e00000 - 0x17e00000
        KASAN_SHADOW_OFFSET = 0x9f000000
    
    - 0x8f000000 if we have 3G userspace / 1G kernelspace with
      full 1 GB low memory (VMSPLIT_3G_OPT):
      - The kernel address space is 1GB (0x40000000)
      - PAGE_OFFSET is set to 0xb0000000 so the kernel static
        image uses 0xb0000000 .. 0xffffffff.
      - On top of that we have the MODULES_VADDR which under
        the worst case (using ARM instructions) is
        PAGE_OFFSET - 16M (0x01000000) = 0xaf000000
        so the modules use addresses 0xaf000000 .. 0xaffffff
      - So the addresses 0xaf000000 .. 0xffffffff need to be
        covered with shadow memory. That is 0x51000000 bytes
        of memory.
      - 1/8 of that is needed for its shadow memory, so
        0x0a200000 bytes of shadow memory is needed. We
        "steal" that from the remaining lowmem.
      - The KASAN_SHADOW_START becomes 0xa4e00000, to
        KASAN_SHADOW_END at 0xaeffffff.
      - Now we can calculate the KASAN_SHADOW_OFFSET for any
        kernel address as 0xaf000000 needs to map to the first
        byte of shadow memory and 0xffffffff needs to map to
        the last byte of shadow memory. Since:
        SHADOW_ADDR = (address >> 3) + KASAN_SHADOW_OFFSET
        0xa4e00000 = (0xaf000000 >> 3) + KASAN_SHADOW_OFFSET
        KASAN_SHADOW_OFFSET = 0xa4e00000 - (0xaf000000 >> 3)
        KASAN_SHADOW_OFFSET = 0xa4e00000 - 0x15e00000
        KASAN_SHADOW_OFFSET = 0x8f000000
    
    - The default value of 0xffffffff for KASAN_SHADOW_OFFSET
      is an error value. We should always match one of the
      above shadow offsets.
    
    When we do this, TASK_SIZE will sometimes get a bit odd values
    that will not fit into immediate mov assembly instructions.
    To account for this, we need to rewrite some assembly using
    TASK_SIZE like this:
    
    -       mov     r1, #TASK_SIZE
    +       ldr     r1, =TASK_SIZE
    
    or
    
    -       cmp     r4, #TASK_SIZE
    +       ldr     r0, =TASK_SIZE
    +       cmp     r4, r0
    
    this is done to avoid the immediate #TASK_SIZE that need to
    fit into a limited number of bits.
    
    Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
    Cc: Alexander Potapenko <glider@google.com>
    Cc: Dmitry Vyukov <dvyukov@google.com>
    Cc: kasan-dev@googlegroups.com
    Cc: Mike Rapoport <rppt@linux.ibm.com>
    Reviewed-by: default avatarArd Biesheuvel <ardb@kernel.org>
    Tested-by: Ard Biesheuvel <ardb@kernel.org> # QEMU/KVM/mach-virt/LPAE/8G
    Tested-by: Florian Fainelli <f.fainelli@gmail.com> # Brahma SoCs
    Tested-by: Ahmad Fatoum <a.fatoum@pengutronix.de> # i.MX6Q
    Reported-by: default avatarArd Biesheuvel <ardb@kernel.org>
    Signed-off-by: default avatarAbbott Liu <liuwenliang@huawei.com>
    Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
    Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
    c12366ba
uaccess-asm.h 2.83 KB