Skip to content

Commit 0069103

Browse files
JosephChen2017rkhuangtao
authored andcommitted
fiq debugger: rockchip: fix crash because of invalid sp_el0
(1) use cpu id from bl31 delivers; (2) sp_el0 should point to kernel address in EL1 mode. On ARM64, kernel uses sp_el0 to store current_thread_info(), we see a problem: when fiq occurs, cpu is EL1 mode but sp_el0 point to userspace address. At this moment, if we read 'current_thread_info()->cpu' or other, it leads an error. We find above situation happens when save/restore cpu context between system mode and user mode under heavy load. Like 'ret_fast_syscall()', kernel restore context of user mode, but fiq occurs before the instruction 'eret', so this causes the above situation. Assembly code: ffffff80080826c8 <ret_fast_syscall>: ...skipping... ffffff80080826fc: d503201f nop ffffff8008082700: d5384100 mrs x0, sp_el0 ffffff8008082704: f9400c00 ldr x0, [x0,torvalds#24] ffffff8008082708: d5182000 msr ttbr0_el1, x0 ffffff800808270c: d5033fdf isb ffffff8008082710: f9407ff7 ldr x23, [sp,torvalds#248] ffffff8008082714: d5184117 msr sp_el0, x23 ffffff8008082718: d503201f nop ffffff800808271c: d503201f nop ffffff8008082720: d5184035 msr elr_el1, x21 ffffff8008082724: d5184016 msr spsr_el1, x22 ffffff8008082728: a94007e0 ldp x0, x1, [sp] ffffff800808272c: a9410fe2 ldp x2, x3, [sp,torvalds#16] ffffff8008082730: a94217e4 ldp x4, x5, [sp,torvalds#32] ffffff8008082734: a9431fe6 ldp x6, x7, [sp,torvalds#48] ffffff8008082738: a94427e8 ldp x8, x9, [sp,torvalds#64] ffffff800808273c: a9452fea ldp x10, x11, [sp,torvalds#80] ffffff8008082740: a94637ec ldp x12, x13, [sp,torvalds#96] ffffff8008082744: a9473fee ldp x14, x15, [sp,torvalds#112] ffffff8008082748: a94847f0 ldp x16, x17, [sp,torvalds#128] ffffff800808274c: a9494ff2 ldp x18, x19, [sp,torvalds#144] ffffff8008082750: a94a57f4 ldp x20, x21, [sp,torvalds#160] ffffff8008082754: a94b5ff6 ldp x22, x23, [sp,torvalds#176] ffffff8008082758: a94c67f8 ldp x24, x25, [sp,torvalds#192] ffffff800808275c: a94d6ffa ldp x26, x27, [sp,torvalds#208] ffffff8008082760: a94e77fc ldp x28, x29, [sp,torvalds#224] ffffff8008082764: f9407bfe ldr x30, [sp,torvalds#240] ffffff8008082768: 9104c3ff add sp, sp, #0x130 ffffff800808276c: d69f03e0 eret Change-Id: I071e899f8a407764e166ca0403199c9d87d6ce78 Signed-off-by: chenjh <[email protected]>
1 parent 8616b35 commit 0069103

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

drivers/staging/android/fiq_debugger/fiq_debugger.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,13 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state,
583583
void *svc_sp)
584584
{
585585
bool signal_helper = false;
586+
unsigned long va_start;
586587

588+
#ifdef CONFIG_ARM64
589+
va_start = VA_START;
590+
#else
591+
va_start = PAGE_OFFSET;
592+
#endif
587593
if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) {
588594
fiq_debugger_help(state);
589595
} else if (!strcmp(cmd, "pc")) {
@@ -593,11 +599,14 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state,
593599
} else if (!strcmp(cmd, "allregs")) {
594600
fiq_debugger_dump_allregs(&state->output, regs);
595601
} else if (!strcmp(cmd, "bt")) {
596-
if (!user_mode((struct pt_regs *)regs))
602+
if (user_mode((struct pt_regs *)regs) ||
603+
((unsigned long)svc_sp < va_start) ||
604+
((unsigned long)svc_sp > -256UL))
605+
fiq_debugger_printf(&state->output, "User mode\n");
606+
else
597607
fiq_debugger_dump_stacktrace(&state->output, regs,
598608
100, svc_sp);
599-
else
600-
fiq_debugger_printf(&state->output, "User mode\n");
609+
601610
} else if (!strncmp(cmd, "reset", 5)) {
602611
cmd += 5;
603612
while (*cmd == ' ')
@@ -1022,13 +1031,8 @@ void fiq_debugger_fiq(void *regs, u32 cpu)
10221031
if (!state)
10231032
return;
10241033

1025-
if (!user_mode((struct pt_regs *)regs))
1026-
need_irq = fiq_debugger_handle_uart_interrupt(state,
1027-
smp_processor_id(),
1028-
regs, current_thread_info());
1029-
else
1030-
need_irq = fiq_debugger_handle_uart_interrupt(state, cpu,
1031-
regs, current_thread_info());
1034+
need_irq = fiq_debugger_handle_uart_interrupt(state, cpu, regs,
1035+
current_thread_info());
10321036
if (need_irq)
10331037
fiq_debugger_force_irq(state);
10341038
}

0 commit comments

Comments
 (0)