author | Jiamin Ma <jiamin.ma@amlogic.com> | 2019-10-11 09:34:01 (GMT) |
---|---|---|
committer | Tao Zeng <tao.zeng@amlogic.com> | 2019-10-15 02:07:38 (GMT) |
commit | d6691a7e2defd91778b8ad3dabbf6b41471b78d7 (patch) | |
tree | bc20a25701db9efd759d81bc9115ceaeff54f5e9 | |
parent | 97d6a2393ceb900732a152aa6453be137e56a65a (diff) | |
download | common-d6691a7e2defd91778b8ad3dabbf6b41471b78d7.zip common-d6691a7e2defd91778b8ad3dabbf6b41471b78d7.tar.gz common-d6691a7e2defd91778b8ad3dabbf6b41471b78d7.tar.bz2 |
backtrace: add validation checking for fp [1/1]
PD#SWPL-15010
Problem:
Crash if keep executing echo w > /proc/sysrq-trigger
on android platform
Solution:
Add necessary checking for the fp to be dereferenced in
dump_backtrace_entry with VMAP stack enabled
Verify:
U212
Change-Id: I69d8d7353cf99a71dc3e7640efa1d460ef2f5f9a
Signed-off-by: Jiamin Ma <jiamin.ma@amlogic.com>
-rw-r--r-- | arch/arm64/kernel/traps.c | 24 |
1 files changed, 18 insertions, 6 deletions
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 0f274f3..fd8b48f 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -98,18 +98,28 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, } #ifdef CONFIG_AMLOGIC_VMAP -static void dump_backtrace_entry(unsigned long ip, unsigned long fp) +static void dump_backtrace_entry(unsigned long ip, unsigned long fp, + unsigned long low) { unsigned long fp_size = 0; + unsigned long high; - if (fp >= VMALLOC_START) { + high = low + THREAD_SIZE; + + /* + * Since the target process may be rescheduled again, + * we have to add necessary validation checking for fp. + * The checking condition is borrowed from unwind_frame + */ + if (on_irq_stack(fp, raw_smp_processor_id()) || + (fp >= low && fp <= high)) { fp_size = *((unsigned long *)fp) - fp; /* fp cross IRQ or vmap stack */ if (fp_size >= THREAD_SIZE) fp_size = 0; } - printk("[%016lx+%4ld][<%p>] %pS\n", - fp, fp_size, (void *) ip, (void *) ip); + pr_info("[%016lx+%4ld][<%016lx>] %pS\n", + fp, fp_size, (unsigned long)ip, (void *)ip); } #else static void dump_backtrace_entry(unsigned long where) @@ -203,7 +213,8 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) /* skip until specified stack frame */ if (!skip) { #ifdef CONFIG_AMLOGIC_VMAP - dump_backtrace_entry(where, frame.fp); + dump_backtrace_entry(where, frame.fp, + (unsigned long)tsk->stack); #else dump_backtrace_entry(where); #endif @@ -217,7 +228,8 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) * instead. */ #ifdef CONFIG_AMLOGIC_VMAP - dump_backtrace_entry(regs->pc, frame.fp); + dump_backtrace_entry(regs->pc, frame.fp, + (unsigned long)tsk->stack); #else dump_backtrace_entry(regs->pc); #endif |