backtrace: add validation checking for fp [1/1]
authorJiamin Ma <jiamin.ma@amlogic.com>
Fri, 11 Oct 2019 09:34:01 +0000 (17:34 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Tue, 15 Oct 2019 02:07:38 +0000 (19:07 -0700)
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>
arch/arm64/kernel/traps.c

index 0f274f3d6ed3de0f25020af7982e81bb6c631985..fd8b48fbebf9f016c34c57a42a07dcb7c211e570 100644 (file)
@@ -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