summaryrefslogtreecommitdiff
authorJiamin 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)
commitd6691a7e2defd91778b8ad3dabbf6b41471b78d7 (patch)
treebc20a25701db9efd759d81bc9115ceaeff54f5e9
parent97d6a2393ceb900732a152aa6453be137e56a65a (diff)
downloadcommon-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>
Diffstat
-rw-r--r--arch/arm64/kernel/traps.c24
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