From a8b8b96e53a43b0ca150f941bd0deefbc656d0d4 Mon Sep 17 00:00:00 2001 From: Tao Zeng Date: Fri, 25 Oct 2019 15:01:24 +0800 Subject: [PATCH] kasan: fix pc crash if open kasan with vmap stack [1/1] PD#SWPL-10141 Problem: If open KASAN, connect wifi, and auto-start apk dianshijia, it will soon crash as: [ 56.655524@2] Unable to handle kernel NULL pointer dereference at virtual address 00000050 [ 56.658155@2] pgd = d0104000 [ 56.661008@2] [00000050] *pgd=00000000 [ 56.664744@2] Internal error: Oops: 80000005 1 PREEMPT SMP ARM common(O) firmware(O) media_clock(O) tb_detect(O) dnlp_alg ldim_alg mxl661_fe_32(O) [ 56.709028@2] CPU: 2 PID: 4930 Comm: kworker/u9:3 Tainted: O 4.9.113 #1 [ 56.716908@2] Hardware name: Generic DT based system [ 56.721858@2] task: f2632bc0 task.stack: c2010000 [ 56.726530@2] PC is at 0x50 [ 56.729301@2] LR is at 0x0 Solution: Fix wrong pmd check address Verify: TL1 X301 Change-Id: I85e01418789801e0ef7691a9d8963c233e115b28 Signed-off-by: Tao Zeng --- arch/arm/kernel/entry-armv.S | 22 +++++++++++++++++++++- drivers/amlogic/memory_ext/vmap_stack.c | 16 ++++++++-------- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 51c5758..4bd8391 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -38,12 +38,16 @@ /* * Interrupt handling. */ - .macro irq_handler #ifdef CONFIG_AMLOGIC_VMAP + .macro irq_handler, vmap=0 + .if \vmap mov r8, sp /* back up sp */ mov r0, sp bl irq_stack_entry /* switch IRQ stack */ mov sp, r0 + .endif +#else + .macro irq_handler #endif #ifdef CONFIG_MULTI_IRQ_HANDLER ldr r1, =handle_arch_irq @@ -59,7 +63,9 @@ #endif 9997: #ifdef CONFIG_AMLOGIC_VMAP + .if \vmap mov sp, r8 /* switch stack back to task stack */ + .endif #endif .endm @@ -226,8 +232,14 @@ ENDPROC(__und_invalid) * get fault task thread info */ ldr r0, [sp, #(SVC_REGS_SIZE + TI_VMAP_BACK_SP)] +#ifdef CONFIG_AMLOGIC_KASAN32 + /* FAR may be kasan shadow then nobody will handle it */ mrc p15, 0, r1, c6, c0, 0 @ get FAR bl pmd_check +#endif + /* sp may not access able when swith task */ + mov r1, r0 + bl pmd_check mov tsk, r0 mov tsk, tsk, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT mov tsk, tsk, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT @@ -294,7 +306,11 @@ __dabt_svc: sub r0, #SVC_REGS_SIZE mov r1, sp mov r2, #SVC_REGS_SIZE +#ifdef CONFIG_AMLOGIC_KASAN32 + bl __memcpy /* copy back sp */ +#else bl memcpy /* copy back sp */ +#endif mov sp, r0 #else svc_entry uaccess=0 @@ -309,7 +325,11 @@ ENDPROC(__dabt_svc) .align 5 __irq_svc: svc_entry +#ifdef CONFIG_AMLOGIC_VMAP + irq_handler vmap=1 +#else irq_handler +#endif #ifdef CONFIG_PREEMPT ldr r8, [tsk, #TI_PREEMPT] @ get preempt count diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index 2d25772..cbceeeb 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -181,12 +181,12 @@ unsigned long notrace pmd_check(unsigned long addr, unsigned long far) pud_t *pud, *pud_k; pmd_t *pmd, *pmd_k; - if (addr < TASK_SIZE) + if (far < TASK_SIZE) return addr; - index = pgd_index(addr); + index = pgd_index(far); - pgd = cpu_get_pgd() + index; + pgd = cpu_get_pgd() + index; pgd_k = init_mm.pgd + index; if (pgd_none(*pgd_k)) @@ -194,16 +194,16 @@ unsigned long notrace pmd_check(unsigned long addr, unsigned long far) if (!pgd_present(*pgd)) set_pgd(pgd, *pgd_k); - pud = pud_offset(pgd, addr); - pud_k = pud_offset(pgd_k, addr); + pud = pud_offset(pgd, far); + pud_k = pud_offset(pgd_k, far); if (pud_none(*pud_k)) goto bad_area; if (!pud_present(*pud)) set_pud(pud, *pud_k); - pmd = pmd_offset(pud, addr); - pmd_k = pmd_offset(pud_k, addr); + pmd = pmd_offset(pud, far); + pmd_k = pmd_offset(pud_k, far); #ifdef CONFIG_ARM_LPAE /* @@ -219,7 +219,7 @@ unsigned long notrace pmd_check(unsigned long addr, unsigned long far) * pmd_none() check for the entry really corresponded to address, not * for the first of pair. */ - index = (addr >> SECTION_SHIFT) & 1; + index = (far >> SECTION_SHIFT) & 1; #endif if (pmd_none(pmd_k[index])) goto bad_area; -- 2.7.4