ARM: kprobes: disallow probing stack consuming instructions
authorWang Nan <wangnan0@huawei.com>
Mon, 5 Jan 2015 11:29:25 +0000 (19:29 +0800)
committerJon Medhurst <tixy@linaro.org>
Tue, 13 Jan 2015 16:10:15 +0000 (16:10 +0000)
This patch prohibits probing instructions for which the stack
requirements are unable to be determined statically. Some test cases
are found not work again after the modification, this patch also
removes them.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Reviewed-by: Jon Medhurst <tixy@linaro.org>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
arch/arm/include/asm/kprobes.h
arch/arm/include/asm/probes.h
arch/arm/kernel/entry-armv.S
arch/arm/probes/kprobes/core.c
arch/arm/probes/kprobes/test-arm.c

index 49fa0dfaad336539b52d35e224b2301f283f9dbd..56f9ac68fbd180e2b889fcfc904cc9a27d76fd96 100644 (file)
@@ -22,7 +22,6 @@
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE                  2
-#define MAX_STACK_SIZE                 64      /* 32 would probably be OK */
 
 #define flush_insn_slot(p)             do { } while (0)
 #define kretprobe_blacklist_size       0
index 6026deb28794bfbf745c712167e46163f00be382..cd9e81588d830bff9d96bad0e7143c4708f46198 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef _ASM_PROBES_H
 #define _ASM_PROBES_H
 
+#ifndef __ASSEMBLY__
+
 typedef u32 probes_opcode_t;
 
 struct arch_probes_insn;
@@ -41,4 +43,14 @@ struct arch_probes_insn {
        int                             stack_space;
 };
 
+#endif /* __ASSEMBLY__ */
+
+/*
+ * We assume one instruction can consume at most 64 bytes stack, which is
+ * 'push {r0-r15}'. Instructions consume more or unknown stack space like
+ * 'str r0, [sp, #-80]' and 'str r0, [sp, r1]' should be prohibit to probe.
+ * Both kprobe and jprobe use this macro.
+ */
+#define MAX_STACK_SIZE                 64
+
 #endif
index 2f5555d307b345b7e0191adb7d7f02fe49ab887b..672b21942fff77581d13959039b518a36a1e1eef 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
+#include <asm/probes.h>
 
 /*
  * Interrupt handling.
@@ -249,7 +250,7 @@ __und_svc:
        @ If a kprobe is about to simulate a "stmdb sp..." instruction,
        @ it obviously needs free stack space which then will belong to
        @ the saved context.
-       svc_entry 64
+       svc_entry MAX_STACK_SIZE
 #else
        svc_entry
 #endif
index 74f3dc3ac212b85ebd40039a80750247c006531b..3a58db4cc1c6b2a545fe296030168914a3050303 100644 (file)
@@ -115,6 +115,15 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
                break;
        }
 
+       /*
+        * Never instrument insn like 'str r0, [sp, +/-r1]'. Also, insn likes
+        * 'str r0, [sp, #-68]' should also be prohibited.
+        * See __und_svc.
+        */
+       if ((p->ainsn.stack_space < 0) ||
+                       (p->ainsn.stack_space > MAX_STACK_SIZE))
+               return -EINVAL;
+
        return 0;
 }
 
index d9a1255f3043ae05b47f3e52b83707e877f1fc52..fdeb300b0fc80ce72d3882260dcc473f567fc278 100644 (file)
@@ -476,7 +476,8 @@ void kprobe_arm_test_cases(void)
        TEST_GROUP("Extra load/store instructions")
 
        TEST_RPR(  "strh        r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")
-       TEST_RPR(  "streqh      r",14,VAL2,", [r",13,0, ", r",12, 48,"]")
+       TEST_RPR(  "streqh      r",14,VAL2,", [r",11,0, ", r",12, 48,"]")
+       TEST_UNSUPPORTED(  "streqh      r14, [r13, r12]")
        TEST_RPR(  "strh        r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")
        TEST_RPR(  "strneh      r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
        TEST_RPR(  "strh        r",2, VAL1,", [r",3, 24,"], r",4, 48,"")
@@ -565,7 +566,8 @@ void kprobe_arm_test_cases(void)
 
 #if __LINUX_ARM_ARCH__ >= 5
        TEST_RPR(  "strd        r",0, VAL1,", [r",1, 48,", -r",2,24,"]")
-       TEST_RPR(  "strccd      r",8, VAL2,", [r",13,0, ", r",12,48,"]")
+       TEST_RPR(  "strccd      r",8, VAL2,", [r",11,0, ", r",12,48,"]")
+       TEST_UNSUPPORTED(  "strccd r8, [r13, r12]")
        TEST_RPR(  "strd        r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
        TEST_RPR(  "strcsd      r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
        TEST_RPR(  "strd        r",2, VAL1,", [r",5, 24,"], r",4,48,"")
@@ -638,13 +640,15 @@ void kprobe_arm_test_cases(void)
        TEST_RP( "str"byte"     r",2, VAL1,", [r",3, 24,"], #48")               \
        TEST_RP( "str"byte"     r",10,VAL2,", [r",9, 64,"], #-48")              \
        TEST_RPR("str"byte"     r",0, VAL1,", [r",1, 48,", -r",2, 24,"]")       \
-       TEST_RPR("str"byte"     r",14,VAL2,", [r",13,0, ", r",12, 48,"]")       \
+       TEST_RPR("str"byte"     r",14,VAL2,", [r",11,0, ", r",12, 48,"]")       \
+       TEST_UNSUPPORTED("str"byte" r14, [r13, r12]")   \
        TEST_RPR("str"byte"     r",1, VAL1,", [r",2, 24,", r",3,  48,"]!")      \
        TEST_RPR("str"byte"     r",12,VAL2,", [r",11,48,", -r",10,24,"]!")      \
        TEST_RPR("str"byte"     r",2, VAL1,", [r",3, 24,"], r",4, 48,"")        \
        TEST_RPR("str"byte"     r",10,VAL2,", [r",9, 48,"], -r",11,24,"")       \
        TEST_RPR("str"byte"     r",0, VAL1,", [r",1, 24,", r",2,  32,", asl #1]")\
-       TEST_RPR("str"byte"     r",14,VAL2,", [r",13,0, ", r",12, 32,", lsr #2]")\
+       TEST_RPR("str"byte"     r",14,VAL2,", [r",11,0, ", r",12, 32,", lsr #2]")\
+       TEST_UNSUPPORTED("str"byte"     r14, [r13, r12, lsr #2]")\
        TEST_RPR("str"byte"     r",1, VAL1,", [r",2, 24,", r",3,  32,", asr #3]!")\
        TEST_RPR("str"byte"     r",12,VAL2,", [r",11,24,", r",10, 4,", ror #31]!")\
        TEST_P(  "ldr"byte"     r0, [r",0,  24,", #-2]")                        \
@@ -668,12 +672,12 @@ void kprobe_arm_test_cases(void)
 
        LOAD_STORE("")
        TEST_P(   "str  pc, [r",0,0,", #15*4]")
-       TEST_R(   "str  pc, [sp, r",2,15*4,"]")
+       TEST_UNSUPPORTED(   "str        pc, [sp, r2]")
        TEST_BF(  "ldr  pc, [sp, #15*4]")
        TEST_BF_R("ldr  pc, [sp, r",2,15*4,"]")
 
        TEST_P(   "str  sp, [r",0,0,", #13*4]")
-       TEST_R(   "str  sp, [sp, r",2,13*4,"]")
+       TEST_UNSUPPORTED(   "str        sp, [sp, r2]")
        TEST_BF(  "ldr  sp, [sp, #13*4]")
        TEST_BF_R("ldr  sp, [sp, r",2,13*4,"]")