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 <tao.zeng@amlogic.com>
This commit is contained in:
Tao Zeng
2019-10-25 15:01:24 +08:00
committed by Chris KIM
parent 0f0317ba0c
commit 256d948c1d
2 changed files with 29 additions and 9 deletions

View File

@@ -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

View File

@@ -179,12 +179,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))
@@ -192,16 +192,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
/*
@@ -217,7 +217,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;