kasan: bring up KASAN for 32bit os [2/2]

PD#SWPL-7085

Problem:
Currently kasan can't be used on 32bit kernel, it's difficult to debug
memory problems;

Solution:
Bring up KASAN on 32bit kernel

Verify:
p212

Change-Id: I4d80568f023315994e969c79b786eba856177c9c
Signed-off-by: Tao Zeng <tao.zeng@amlogic.com>
This commit is contained in:
Tao Zeng
2019-04-16 09:42:24 +08:00
parent bdd35d7859
commit 3bed10b47f
28 changed files with 543 additions and 4 deletions

View File

@@ -13541,6 +13541,11 @@ AMLOGIC boot config for M8B
M: Tao Zeng <tao.zeng@amlogic.com>
F: arch/arm/mach-meson/Makefile.boot
AMLOGIC implementation for 32bit kasan
M: Tao Zeng <tao.zeng@amlogic.com>
F: arch/arm/include/asm/kasan.h
F: arch/arm/mm/kasan_init.c
HDMITX OUTPUT DRIVER
M: Yi Zhou <yi.zhou@amlogic.com>
M: Zongdong Jiao <zongdong.jiao@amlogic.com>

View File

@@ -90,6 +90,7 @@ config ARM
select PERF_USE_VMALLOC
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
select HAVE_ARCH_KASAN
# Above selects are sorted alphabetically; please add new ones
# according to that. Thanks.
help
@@ -1444,6 +1445,7 @@ config PAGE_OFFSET
default 0x40000000 if VMSPLIT_1G
default 0x80000000 if VMSPLIT_2G
default 0xB0000000 if VMSPLIT_3G_OPT
default 0xD0000000 if AMLOGIC_KASAN32
default 0xC0000000
config NR_CPUS

View File

@@ -52,6 +52,10 @@ AS += -EL
LD += -EL
endif
ifeq ($(CONFIG_KASAN),y)
KASAN_SHADOW_OFFSET := 0xA0000000
endif
#
# The Scalar Replacement of Aggregates (SRA) optimization pass in GCC 4.9 and
# later may result in code being generated that handles signed short and signed

View File

@@ -4,6 +4,8 @@
# create a compressed vmlinuz image from the original vmlinux
#
KASAN_SANITIZE := n
OBJS =
AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)

View File

@@ -120,7 +120,9 @@ char *strchr(const char *s, int c)
return (char *)s;
}
#ifndef CONFIG_AMLOGIC_KASAN32 /* for compile problems */
#undef memset
#endif
void *memset(void *s, int c, size_t count)
{

View File

@@ -3,7 +3,12 @@
#include <asm/kmap_types.h>
#ifdef CONFIG_AMLOGIC_KASAN32
#include <asm/memory.h>
#define PKMAP_BASE VMALLOC_END
#else
#define PKMAP_BASE (PAGE_OFFSET - PMD_SIZE)
#endif
#define LAST_PKMAP PTRS_PER_PTE
#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
#define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT)

View File

@@ -0,0 +1,66 @@
#ifndef __ASM_KASAN_H
#define __ASM_KASAN_H
#ifndef __ASSEMBLY__
#ifdef CONFIG_KASAN
#include <linux/linkage.h>
#include <asm/memory.h>
#define sym_to_pfn(x) __phys_to_pfn(__pa_symbol(x))
#define PAGE_KERNEL_RO _MOD_PROT(pgprot_kernel, L_PTE_RDONLY)
/*
* KASAN_SHADOW_START: beginning of the kernel virtual addresses.
* KASAN_SHADOW_END: KASAN_SHADOW_START + 1/8 of kernel virtual addresses.
*
* For 32bit KASAN, we using a fixed Memory map here
*
* 0x00000000 +--------+
* | |
* | |
* | | User space memory, 2944MB
* | |
* | |
* 0xb8000000 +--------+
* | | Kasan shaddow memory, 128MB
* 0xc0000000 +--------+
* | | Vmalloc address, 240MB
* | |
* 0xCF400000 +--------+
* 0xCF600000 +--------+ PKmap, for kmap 2MB
* 0xD0000000 +--------+ Module and pkmap, 10MB
* | |
* | | Kernel linear mapped space, 762MB
* 0xFFa00000 +--------+
* 0xFFFc0000 +--------+ static map, 2MB
* 0xFFF00000 +--------+ Fixed map, for kmap_atomic, 3MB
* 0xFFFF0000 +--------+ High vector, 4KB
*
*/
#define KADDR_SIZE (SZ_1G)
#define KASAN_SHADOW_SIZE (KADDR_SIZE >> 3)
#define KASAN_SHADOW_START (TASK_SIZE)
#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
/*
* This value is used to map an address to the corresponding shadow
* address by the following formula:
* shadow_addr = (address >> 3) + KASAN_SHADOW_OFFSET;
*
*/
#define KASAN_SHADOW_OFFSET (KASAN_SHADOW_START - (VMALLOC_START >> 3))
struct map_desc;
void kasan_init(void);
void kasan_copy_shadow(pgd_t *pgdir);
asmlinkage void kasan_early_init(void);
void cpu_v7_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
void create_mapping(struct map_desc *md);
#else
static inline void kasan_init(void) { }
static inline void kasan_copy_shadow(pgd_t *pgdir) { }
#endif
#endif
#endif

View File

@@ -39,15 +39,22 @@
* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
*/
#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_64M))
#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M)
#else /* CONFIG_AMLOGIC_VMAP */
#elif defined(CONFIG_AMLOGIC_KASAN32)
/*
* reserve 128MB address space for kasan
* for this memory layout implementation, PAGE_OFFSET should be 0xD0000000
*/
#define VMALLOC_START (UL(CONFIG_PAGE_OFFSET) - UL(SZ_256M))
#define TASK_SIZE (VMALLOC_START - UL(SZ_128M))
#define KMEM_END (0xffa00000UL)
#else
/*
* TASK_SIZE - the maximum size of a user space task.
* TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
*/
#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M))
#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M)
#endif /* CONFIG_AMLOGIC_VMAP */
#define TASK_UNMAPPED_BASE ALIGN(TASK_SIZE / 3, SZ_16M)
/*
* The maximum size of a 26-bit user space task.
@@ -66,13 +73,24 @@
* and PAGE_OFFSET - it must be within 32MB of the kernel text.
*/
#ifndef CONFIG_THUMB2_KERNEL
#ifdef CONFIG_AMLOGIC_KASAN32
/*
* to fix module link problem
*/
#define MODULES_VADDR (PAGE_OFFSET - SZ_16M + SZ_4M + SZ_2M)
#else
#define MODULES_VADDR (PAGE_OFFSET - SZ_16M)
#endif
#else
/* smaller range for Thumb-2 symbols relocation (2^24)*/
#define MODULES_VADDR (PAGE_OFFSET - SZ_8M)
#endif
#endif /* CONFIG_AMLOGIC_VMAP */
#ifdef CONFIG_AMLOGIC_KASAN32
#define VMALLOC_END (MODULES_VADDR - SZ_2M)
#endif
#if TASK_SIZE > MODULES_VADDR
#error Top of user space clashes with start of module space
#endif
@@ -80,11 +98,15 @@
/*
* The highmem pkmap virtual space shares the end of the module area.
*/
#ifdef CONFIG_AMLOGIC_KASAN32
#define MODULES_END (PAGE_OFFSET)
#else
#ifdef CONFIG_HIGHMEM
#define MODULES_END (PAGE_OFFSET - PMD_SIZE)
#else
#define MODULES_END (PAGE_OFFSET)
#endif
#endif
/*
* The XIP kernel gets mapped at the bottom of the module vm area.

View File

@@ -41,9 +41,11 @@
* The vmalloc() routines leaves a hole of 4kB between each vmalloced
* area for the same reason. ;)
*/
#ifndef CONFIG_AMLOGIC_KASAN32
#define VMALLOC_OFFSET (8*1024*1024)
#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#define VMALLOC_END 0xff800000UL
#endif /* !CONFIG_AMLOGIC_KASAN32 */
#define LIBRARY_TEXT_START 0x0c000000

View File

@@ -26,6 +26,24 @@ extern void * memset(void *, int, __kernel_size_t);
extern void __memzero(void *ptr, __kernel_size_t n);
#ifdef CONFIG_AMLOGIC_KASAN32
/* replace default function to check kasan */
extern void *__memcpy(void *dst, const void *src, __kernel_size_t size);
extern void *__memmove(void *dst, const void *src, __kernel_size_t size);
extern void *__memset(void *dst, int v, __kernel_size_t size);
#if defined(CONFIG_KASAN) && !defined(__SANITIZE_ADDRESS__)
/*
* For files that are not instrumented (e.g. mm/slub.c) we
* should use not instrumented version of mem* functions.
*/
#define memcpy(dst, src, len) __memcpy(dst, src, len)
#define memmove(dst, src, len) __memmove(dst, src, len)
#define memset(s, c, n) __memset(s, c, n)
#endif
#else
#define memset(p,v,n) \
({ \
void *__p = (p); size_t __n = n; \
@@ -39,3 +57,4 @@ extern void __memzero(void *ptr, __kernel_size_t n);
})
#endif
#endif

View File

@@ -16,8 +16,14 @@
#include <asm/fpstate.h>
#include <asm/page.h>
#ifdef CONFIG_AMLOGIC_KASAN32
#define THREAD_SIZE_ORDER 2
#else
#define THREAD_SIZE_ORDER 1
#endif /* CONFIG_AMLOGIC_KASAN32 */
#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
#ifdef CONFIG_AMLOGIC_VMAP
#define THREAD_INFO_SIZE (sizeof(struct thread_info))
#define THREAD_INFO_OFFSET (THREAD_SIZE - THREAD_INFO_SIZE)

View File

@@ -18,6 +18,9 @@
#include <asm/domain.h>
#include <asm/unified.h>
#include <asm/compiler.h>
#ifdef CONFIG_AMLOGIC_KASAN32
#include <linux/kasan-checks.h>
#endif
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
#include <asm-generic/uaccess-unaligned.h>
@@ -532,6 +535,9 @@ __clear_user(void __user *addr, unsigned long n)
static inline unsigned long __must_check
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
#ifdef CONFIG_AMLOGIC_KASAN32
kasan_check_write(to, n);
#endif
check_object_size(to, n, false);
return __arch_copy_from_user(to, from, n);
}
@@ -540,6 +546,9 @@ static inline unsigned long __must_check
copy_from_user(void *to, const void __user *from, unsigned long n)
{
unsigned long res = n;
#ifdef CONFIG_AMLOGIC_KASAN32
kasan_check_write(to, n);
#endif
check_object_size(to, n, false);
@@ -553,6 +562,9 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
static inline unsigned long __must_check
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
#ifdef CONFIG_AMLOGIC_KASAN32
kasan_check_read(from, n);
#endif
check_object_size(from, n, true);
return __arch_copy_to_user(to, from, n);
@@ -561,6 +573,9 @@ __copy_to_user(void __user *to, const void *from, unsigned long n)
static inline unsigned long __must_check
copy_to_user(void __user *to, const void *from, unsigned long n)
{
#ifdef CONFIG_AMLOGIC_KASAN32
kasan_check_read(from, n);
#endif
check_object_size(from, n, true);
if (access_ok(VERIFY_WRITE, to, n))

View File

@@ -181,3 +181,9 @@ EXPORT_SYMBOL(__pv_offset);
EXPORT_SYMBOL(__arm_smccc_smc);
EXPORT_SYMBOL(__arm_smccc_hvc);
#endif
#ifdef CONFIG_AMLOGIC_KASAN32
EXPORT_SYMBOL(__memset);
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(__memmove);
#endif

View File

@@ -101,6 +101,9 @@ __mmap_switched:
str r2, [r6] @ Save atags pointer
cmp r7, #0
strne r0, [r7] @ Save control register values
#ifdef CONFIG_AMLOGIC_KASAN32
bl kasan_early_init
#endif
b start_kernel
ENDPROC(__mmap_switched)

View File

@@ -25,6 +25,9 @@
#include <asm/smp_plat.h>
#include <asm/unwind.h>
#include <asm/opcodes.h>
#ifdef CONFIG_AMLOGIC_KASAN32
#include <linux/kasan.h>
#endif
#ifdef CONFIG_XIP_KERNEL
/*
@@ -40,6 +43,20 @@
#ifdef CONFIG_MMU
void *module_alloc(unsigned long size)
{
#ifdef CONFIG_AMLOGIC_KASAN32
void *p = __vmalloc_node_range(size, MODULE_ALIGN, MODULES_VADDR,
MODULES_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
NUMA_NO_NODE, __builtin_return_address(0));
if (!p)
p = __vmalloc_node_range(size, MODULE_ALIGN, VMALLOC_START,
VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
NUMA_NO_NODE, __builtin_return_address(0));
if (p && (kasan_module_alloc(p, size) < 0)) {
vfree(p);
return NULL;
}
return p;
#else
void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
__builtin_return_address(0));
@@ -48,6 +65,7 @@ void *module_alloc(unsigned long size)
return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
__builtin_return_address(0));
#endif
}
#endif

View File

@@ -68,6 +68,9 @@
#ifdef CONFIG_AMLOGIC_CPU_INFO
#include <linux/amlogic/cpu_version.h>
#endif
#ifdef CONFIG_AMLOGIC_KASAN32
#include <asm/kasan.h>
#endif
#include "atags.h"
@@ -1127,6 +1130,9 @@ void __init setup_arch(char **cmdline_p)
early_ioremap_reset();
paging_init(mdesc);
#ifdef CONFIG_AMLOGIC_KASAN32
kasan_init();
#endif
request_standard_resources(mdesc);
if (mdesc->restart)

View File

@@ -246,8 +246,21 @@ static unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl)
}
/* Before poping a register check whether it is feasible or not */
#ifdef CONFIG_AMLOGIC_KASAN32
/*
* If enabled KASAN and unwind_frame is called under IRQ routine,
* an value-less kasan report will trigger. Because IRQ is using
* thread context and don't initialized shadow memory when irq_svc
* saving irq context. Since it's hard to guess reserved memory for
* shadow in stack by compiler, so we just tell compiler do not
* sanitize for this function
*/
int __no_sanitize_address unwind_pop_register(struct unwind_ctrl_block *ctrl,
unsigned long **vsp, unsigned int reg)
#else
static int unwind_pop_register(struct unwind_ctrl_block *ctrl,
unsigned long **vsp, unsigned int reg)
#endif
{
if (unlikely(ctrl->check_each_pop))
if (*vsp >= (unsigned long *)ctrl->sp_high)
@@ -407,7 +420,13 @@ int unwind_frame(struct stackframe *frame)
idx = unwind_find_idx(frame->pc);
if (!idx) {
#ifdef CONFIG_AMLOGIC_KASAN32
/* avoid FUCKING close source ko print too many here */
if (frame->pc > PAGE_OFFSET)
pr_warn("unwind: Index not found %08lx\n", frame->pc);
#else
pr_warn("unwind: Index not found %08lx\n", frame->pc);
#endif
return -URC_FAILURE;
}

View File

@@ -62,9 +62,17 @@
/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
ENTRY(mmiocpy)
#ifdef CONFIG_AMLOGIC_KASAN32
ENTRY(__memcpy)
#else
ENTRY(memcpy)
#endif
#include "copy_template.S"
#ifdef CONFIG_AMLOGIC_KASAN32
ENDPROC(__memcpy)
#else
ENDPROC(memcpy)
#endif
ENDPROC(mmiocpy)

View File

@@ -27,7 +27,11 @@
* occurring in the opposite direction.
*/
#ifdef CONFIG_AMLOGIC_KASAN32
ENTRY(__memmove)
#else
ENTRY(memmove)
#endif
UNWIND( .fnstart )
subs ip, r0, r1
@@ -224,4 +228,8 @@ ENTRY(memmove)
18: backward_copy_shift push=24 pull=8
#ifdef CONFIG_AMLOGIC_KASAN32
ENDPROC(__memmove)
#else
ENDPROC(memmove)
#endif

View File

@@ -17,7 +17,11 @@
.align 5
ENTRY(mmioset)
#ifdef CONFIG_AMLOGIC_KASAN32
ENTRY(__memset)
#else
ENTRY(memset)
#endif
UNWIND( .fnstart )
ands r3, r0, #3 @ 1 unaligned?
mov ip, r0 @ preserve r0 as return value
@@ -133,5 +137,9 @@ UNWIND( .fnstart )
add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
b 1b
UNWIND( .fnend )
#ifdef CONFIG_AMLOGIC_KASAN32
ENDPROC(__memset)
#else
ENDPROC(memset)
#endif
ENDPROC(mmioset)

View File

@@ -107,3 +107,6 @@ obj-$(CONFIG_CACHE_L2X0_PMU) += cache-l2x0-pmu.o
obj-$(CONFIG_CACHE_XSC3L2) += cache-xsc3l2.o
obj-$(CONFIG_CACHE_TAUROS2) += cache-tauros2.o
obj-$(CONFIG_CACHE_UNIPHIER) += cache-uniphier.o
obj-$(CONFIG_AMLOGIC_KASAN32) += kasan_init.o
KASAN_SANITIZE_kasan_init.o := n

View File

@@ -36,6 +36,9 @@
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#ifdef CONFIG_AMLOGIC_KASAN32
#include <asm/kasan.h>
#endif
#include "mm.h"
@@ -502,6 +505,9 @@ void __init mem_init(void)
#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
pr_notice("Virtual kernel memory layout:\n"
#ifdef CONFIG_AMLOGIC_KASAN32
" kasan : 0x%08lx - 0x%08lx (%4ld MB)\n"
#endif
" vector : 0x%08lx - 0x%08lx (%4ld kB)\n"
#ifdef CONFIG_HAVE_TCM
" DTCM : 0x%08lx - 0x%08lx (%4ld kB)\n"
@@ -520,6 +526,9 @@ void __init mem_init(void)
" .init : 0x%p" " - 0x%p" " (%4td kB)\n"
" .data : 0x%p" " - 0x%p" " (%4td kB)\n"
" .bss : 0x%p" " - 0x%p" " (%4td kB)\n",
#ifdef CONFIG_AMLOGIC_KASAN32
MLM(KASAN_SHADOW_START, KASAN_SHADOW_END),
#endif
MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
(PAGE_SIZE)),

218
arch/arm/mm/kasan_init.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* This file contains kasan initialization code for ARM64.
*
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
* Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#define pr_fmt(fmt) "kasan: " fmt
#include <linux/kasan.h>
#include <linux/kernel.h>
#include <linux/memblock.h>
#include <linux/start_kernel.h>
#include <linux/mm.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/sections.h>
#include <asm/tlbflush.h>
#include <asm/mach/map.h>
#include <asm/fixmap.h>
#define PGD_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
static pgd_t tmp_pg_dir[PTRS_PER_PGD] __initdata __aligned(PGD_SIZE);
/*
* The p*d_populate functions call virt_to_phys implicitly so they can't be used
* directly on kernel symbols (bm_p*d). All the early functions are called too
* early to use lm_alias so __p*d_populate functions must be used to populate
* with the physical address from __pa_symbol.
*/
static void __init kasan_early_pte_populate(pmd_t *pmd, unsigned long addr,
unsigned long end)
{
pte_t *pte;
unsigned long next;
pgprot_t kernel_pte = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
L_PTE_SHARED | L_PTE_DIRTY |
L_PTE_MT_WRITEALLOC);
if (pmd_none(*pmd))
__pmd_populate(pmd, __pa_symbol(kasan_zero_pte),
_PAGE_KERNEL_TABLE);
pte = pte_offset_kernel(pmd, addr);
do {
next = addr + PAGE_SIZE;
cpu_v7_set_pte_ext(pte, pfn_pte(sym_to_pfn(kasan_zero_page),
kernel_pte),
0);
} while (pte++, addr = next, addr != end && pte_none(*pte));
}
static void __init kasan_early_pmd_populate(pud_t *pud,
unsigned long addr,
unsigned long end)
{
pmd_t *pmd;
unsigned long next;
if (pud_none(*pud))
pud_populate(pud, __pa_symbol(kasan_zero_pmd), PMD_TYPE_TABLE);
pmd = pmd_offset(pud, addr);
do {
next = pmd_addr_end(addr, end);
kasan_early_pte_populate(pmd, addr, next);
} while (pmd++, addr = next, addr != end && pmd_none(*pmd));
}
static void __init kasan_early_pud_populate(pgd_t *pgd,
unsigned long addr,
unsigned long end)
{
pud_t *pud;
unsigned long next;
if (pgd_none(*pgd))
pgd_populate(pgd, __pa_symbol(kasan_zero_pud), PUD_TYPE_TABLE);
pud = pud_offset(pgd, addr);
do {
next = pud_addr_end(addr, end);
kasan_early_pmd_populate(pud, addr, next);
} while (pud++, addr = next, addr != end && pud_none(*pud));
}
static void __init kasan_map_early_shadow(unsigned long start,
unsigned long end)
{
unsigned long addr = start;
unsigned long next;
pgd_t *pgd;
pgd = pgd_offset_k(addr);
do {
next = pgd_addr_end(addr, end);
kasan_early_pud_populate(pgd, addr, next);
} while (pgd++, addr = next, addr != end);
}
asmlinkage void __init kasan_early_init(void)
{
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_START, PGDIR_SIZE));
BUILD_BUG_ON(!IS_ALIGNED(KASAN_SHADOW_END, PGDIR_SIZE));
kasan_map_early_shadow(KASAN_SHADOW_START, KASAN_SHADOW_END);
}
static inline pmd_t *pmd_off_k(unsigned long virt)
{
return pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt);
}
static void __init clear_pmds(unsigned long start,
unsigned long end)
{
/*
* Remove references to kasan page tables from
* swapper_pg_dir. pmd_clear() can't be used
* here because it's nop on 2,3-level pagetable setups
*/
for (; start < end; start += PGDIR_SIZE)
pmd_clear(pmd_off_k(start));
}
static void kasan_alloc_and_map_shadow(unsigned long start, unsigned long end)
{
struct map_desc desc;
unsigned long size;
phys_addr_t l_shadow;
size = (end - start) >> KASAN_SHADOW_SCALE_SHIFT;
l_shadow = memblock_alloc(size, SECTION_SIZE);
WARN(!l_shadow, "%s, reserve %ld shadow memory failed",
__func__, size);
desc.virtual = (unsigned long)kasan_mem_to_shadow((void *)start);
desc.pfn = __phys_to_pfn(l_shadow);
desc.length = size;
desc.type = MT_MEMORY_RW;
create_mapping(&desc);
pr_info("KASAN shadow, virt:[%lx-%lx], phys:%x, size:%lx\n",
start, end, l_shadow, size);
}
void __init kasan_init(void)
{
unsigned long start, end;
int i;
/*
* We are going to perform proper setup of shadow memory.
* At first we should unmap early shadow (clear_pmds() call bellow).
* However, instrumented code couldn't execute without shadow memory.
* tmp_pg_dir used to keep early shadow mapped until full shadow
* setup will be finished.
*/
memcpy(tmp_pg_dir, swapper_pg_dir, sizeof(tmp_pg_dir));
dsb(ishst);
cpu_switch_mm(tmp_pg_dir, &init_mm);
clear_pmds(KASAN_SHADOW_START, KASAN_SHADOW_END);
kasan_alloc_and_map_shadow(PAGE_OFFSET, KMEM_END);
kasan_alloc_and_map_shadow(FIXADDR_START, FIXADDR_END);
#ifdef CONFIG_HIGHMEM
kasan_alloc_and_map_shadow(PKMAP_BASE,
PKMAP_BASE + LAST_PKMAP * PAGE_SIZE);
#endif
/*
* populate zero page for vmalloc area and other gap area
* TODO:
* Need check kasan for vmalloc?
*/
start = (ulong)kasan_mem_to_shadow((void *)MODULES_VADDR);
kasan_map_early_shadow(KASAN_SHADOW_START, start);
start = (ulong)kasan_mem_to_shadow((void *)KMEM_END);
end = (ulong)kasan_mem_to_shadow((void *)FIXADDR_START);
kasan_map_early_shadow(start, end);
/*
* KAsan may reuse the contents of kasan_zero_pte directly, so we
* should make sure that it maps the zero page read-only.
*/
for (i = 0; i < PTRS_PER_PTE; i++)
set_pte_ext(&kasan_zero_pte[i],
pfn_pte(sym_to_pfn(kasan_zero_page),
PAGE_KERNEL_RO), 0);
memset(kasan_zero_page, 0, PAGE_SIZE);
cpu_switch_mm(swapper_pg_dir, &init_mm);
local_flush_tlb_all();
flush_cache_all();
/* clear all shawdow memory before kasan running */
memset(kasan_mem_to_shadow((void *)PAGE_OFFSET), 0,
(KMEM_END - PAGE_OFFSET) >> KASAN_SHADOW_SCALE_SHIFT);
memset(kasan_mem_to_shadow((void *)FIXADDR_START), 0,
(FIXADDR_END - FIXADDR_START) >> KASAN_SHADOW_SCALE_SHIFT);
#ifdef CONFIG_HIGHMEM
memset(kasan_mem_to_shadow((void *)PKMAP_BASE), 0,
(LAST_PKMAP * PAGE_SIZE) >> KASAN_SHADOW_SCALE_SHIFT);
#endif
/* At this point kasan is fully initialized. Enable error messages */
init_task.kasan_depth = 0;
pr_info("KernelAddressSanitizer initialized\n");
}

View File

@@ -37,6 +37,9 @@
#include <asm/mach/map.h>
#include <asm/mach/pci.h>
#include <asm/fixmap.h>
#ifdef CONFIG_AMLOGIC_KASAN32
#include <asm/kasan.h>
#endif
#include "fault.h"
#include "mm.h"
@@ -951,7 +954,11 @@ static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md,
* offsets, and we take full advantage of sections and
* supersections.
*/
#ifdef CONFIG_AMLOGIC_KASAN32
void __init create_mapping(struct map_desc *md)
#else
static void __init create_mapping(struct map_desc *md)
#endif
{
if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
@@ -1121,6 +1128,7 @@ void __init debug_ll_io_init(void)
}
#endif
#ifndef CONFIG_AMLOGIC_KASAN32
static void * __initdata vmalloc_min =
(void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
@@ -1149,6 +1157,7 @@ static int __init early_vmalloc(char *arg)
return 0;
}
early_param("vmalloc", early_vmalloc);
#endif
phys_addr_t arm_lowmem_limit __initdata = 0;
@@ -1166,7 +1175,11 @@ void __init adjust_lowmem_bounds(void)
* and may itself be outside the valid range for which phys_addr_t
* and therefore __pa() is defined.
*/
#ifdef CONFIG_AMLOGIC_KASAN32
vmalloc_limit = (u64)(KMEM_END - PAGE_OFFSET + PHYS_OFFSET);
#else
vmalloc_limit = (u64)(uintptr_t)vmalloc_min - PAGE_OFFSET + PHYS_OFFSET;
#endif
for_each_memblock(memory, reg) {
phys_addr_t block_start = reg->base;
@@ -1244,8 +1257,19 @@ static inline void prepare_page_table(void)
/*
* Clear out all the mappings below the kernel image.
*/
#ifdef CONFIG_AMLOGIC_KASAN32
for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE) {
/*
* keep pre-initialized kasan shadow memory MMU before
* kasan really eanbled
*/
if (addr < KASAN_SHADOW_START || addr >= KASAN_SHADOW_END)
pmd_clear(pmd_off_k(addr));
}
#else
for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
#endif
#ifdef CONFIG_XIP_KERNEL
/* The XIP kernel is mapped in the module area -- skip over it */
@@ -1321,8 +1345,16 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
/*
* Clear page table except top pmd used by early fixmaps
*/
#ifdef CONFIG_AMLOGIC_KASAN32
/* we have adjusted memory map layout */
for (addr = VMALLOC_START;
addr < (PAGE_OFFSET & PMD_MASK);
addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
#else
for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
#endif
/*
* Map the kernel if it is XIP.
@@ -1645,10 +1677,11 @@ void __init paging_init(const struct machine_desc *mdesc)
unsigned long notrace phys_check(phys_addr_t x)
{
unsigned long addr;
struct page *page;
addr = x - PHYS_OFFSET + PAGE_OFFSET;
#ifndef CONFIG_AMLOGIC_KASAN32
if (scheduler_running) {
struct page *page;
page = phys_to_page(x);
/*
@@ -1662,16 +1695,19 @@ unsigned long notrace phys_check(phys_addr_t x)
dump_stack();
}
}
#endif
return addr;
}
EXPORT_SYMBOL(phys_check);
unsigned long notrace virt_check(unsigned long x)
{
#ifndef CONFIG_AMLOGIC_KASAN32
if (scheduler_running && (x >= VMALLOC_START || x < PAGE_OFFSET)) {
pr_err("bad input of virt:%lx\n", x);
dump_stack();
}
#endif
return (phys_addr_t)x - PAGE_OFFSET + PHYS_OFFSET;
}
EXPORT_SYMBOL(virt_check);

View File

@@ -20,6 +20,8 @@ obj-$(CONFIG_VDSO) += vdso.o
extra-$(CONFIG_VDSO) += vdso.lds
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
KASAN_SANITIZE_vgettimeofday.o := n
CFLAGS_REMOVE_vdso.o = -pg
# Force -O2 to avoid libgcc dependencies

View File

@@ -40,10 +40,23 @@ config AMLOGIC_CMA
Amlogic CMA optimization for cma alloc/free problems
Including policy change of CMA usage
config AMLOGIC_KASAN32
bool "Amlogic KASAN support for 32bit kernel"
depends on AMLOGIC_MEMORY_EXTEND
depends on KASAN
depends on !64BIT
default y
help
Amlogic implementation for KASAN on 32bit ARM kernel.
Which can help to debug memory of use-after-free,
out-of-bounds and other problems. This config will
change memory layout.
config AMLOGIC_VMAP
bool "Amlogic kernel stack"
depends on AMLOGIC_MEMORY_EXTEND
depends on !KASAN
depends on !AMLOGIC_KASAN32
default y
help
This config is used to enable amlogic kernel stack

View File

@@ -161,6 +161,18 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
&prop);
#ifdef CONFIG_AMLOGIC_MODIFY
#ifdef CONFIG_AMLOGIC_KASAN32
{
unsigned long lowmem_size;
/* fix for cma overlap 2 zone */
lowmem_size = KMEM_END - PAGE_OFFSET;
lowmem_size += CONFIG_PHYS_OFFSET;
if (start < lowmem_size && end > lowmem_size) {
end = lowmem_size - SZ_4M;
}
}
#endif
#ifdef CONFIG_PHYS_ADDR_T_64BIT
pr_info("%s, start:%pa, end:%pa, len:%ld MiB\n",
__func__, &start, &end,

View File

@@ -416,8 +416,18 @@ void kasan_cache_create(struct kmem_cache *cache, size_t *size,
if (redzone_adjust > 0)
*size += redzone_adjust;
#ifdef CONFIG_AMLOGIC_KASAN32 /* compile problem */
{
size_t s1;
s1 = max(*size, cache->object_size +
optimal_redzone(cache->object_size));
*size = s1 >= KMALLOC_MAX_SIZE ? KMALLOC_MAX_SIZE : s1;
}
#else
*size = min(KMALLOC_MAX_SIZE, max(*size, cache->object_size +
optimal_redzone(cache->object_size)));
#endif
/*
* If the metadata doesn't fit, don't enable KASAN at all.
@@ -569,8 +579,13 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object)
shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object));
if (shadow_byte < 0 || shadow_byte >= KASAN_SHADOW_SCALE_SIZE) {
#ifdef CONFIG_AMLOGIC_KASAN32 /* for compile problems */
kasan_report_double_free(cache, object,
__builtin_return_address(0));
#else
kasan_report_double_free(cache, object,
__builtin_return_address(1));
#endif
return true;
}
@@ -731,6 +746,11 @@ static void register_global(struct kasan_global *global)
{
size_t aligned_size = round_up(global->size, KASAN_SHADOW_SCALE_SIZE);
#ifdef CONFIG_AMLOGIC_KASAN32
/* avoid FUCKING close source ko panic here */
if ((unsigned long)global->beg < MODULES_VADDR)
return;
#endif
kasan_unpoison_shadow(global->beg, global->size);
kasan_poison_shadow(global->beg + aligned_size,