aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/kprobes-decode.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index 4ab83f4c47cf..6d09db9c84ab 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -68,6 +68,8 @@
68 68
69#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25) 69#define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
70 70
71#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
72
71#define PSR_fs (PSR_f|PSR_s) 73#define PSR_fs (PSR_f|PSR_s)
72 74
73#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */ 75#define KPROBE_RETURN_INSTRUCTION 0xe1a0f00e /* mov pc, lr */
@@ -897,6 +899,9 @@ prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
897static enum kprobe_insn __kprobes 899static enum kprobe_insn __kprobes
898prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi) 900prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
899{ 901{
902 if (is_r15(insn, 12))
903 return INSN_REJECTED; /* Rd is PC */
904
900 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */ 905 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
901 asi->insn[0] = insn; 906 asi->insn[0] = insn;
902 asi->insn_handler = emulate_rd12rm0; 907 asi->insn_handler = emulate_rd12rm0;
@@ -907,6 +912,9 @@ static enum kprobe_insn __kprobes
907prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn, 912prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
908 struct arch_specific_insn *asi) 913 struct arch_specific_insn *asi)
909{ 914{
915 if (is_r15(insn, 12))
916 return INSN_REJECTED; /* Rd is PC */
917
910 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */ 918 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
911 insn |= 0x00000001; /* Rm = r1 */ 919 insn |= 0x00000001; /* Rm = r1 */
912 asi->insn[0] = insn; 920 asi->insn[0] = insn;
@@ -918,6 +926,9 @@ static enum kprobe_insn __kprobes
918prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn, 926prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
919 struct arch_specific_insn *asi) 927 struct arch_specific_insn *asi)
920{ 928{
929 if (is_r15(insn, 16))
930 return INSN_REJECTED; /* Rd is PC */
931
921 insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */ 932 insn &= 0xfff0f0f0; /* Rd = r0, Rs = r0 */
922 insn |= 0x00000001; /* Rm = r1 */ 933 insn |= 0x00000001; /* Rm = r1 */
923 asi->insn[0] = insn; 934 asi->insn[0] = insn;
@@ -929,6 +940,9 @@ static enum kprobe_insn __kprobes
929prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn, 940prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
930 struct arch_specific_insn *asi) 941 struct arch_specific_insn *asi)
931{ 942{
943 if (is_r15(insn, 16))
944 return INSN_REJECTED; /* Rd is PC */
945
932 insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */ 946 insn &= 0xfff000f0; /* Rd = r0, Rn = r0 */
933 insn |= 0x00000102; /* Rs = r1, Rm = r2 */ 947 insn |= 0x00000102; /* Rs = r1, Rm = r2 */
934 asi->insn[0] = insn; 948 asi->insn[0] = insn;
@@ -940,6 +954,9 @@ static enum kprobe_insn __kprobes
940prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn, 954prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
941 struct arch_specific_insn *asi) 955 struct arch_specific_insn *asi)
942{ 956{
957 if (is_r15(insn, 16) || is_r15(insn, 12))
958 return INSN_REJECTED; /* RdHi or RdLo is PC */
959
943 insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */ 960 insn &= 0xfff000f0; /* RdHi = r0, RdLo = r1 */
944 insn |= 0x00001203; /* Rs = r2, Rm = r3 */ 961 insn |= 0x00001203; /* Rs = r2, Rm = r3 */
945 asi->insn[0] = insn; 962 asi->insn[0] = insn;
@@ -1035,6 +1052,8 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1035 1052
1036 /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */ 1053 /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
1037 if ((insn & 0x0ff000f0) == 0x01000000) { 1054 if ((insn & 0x0ff000f0) == 0x01000000) {
1055 if (is_r15(insn, 12))
1056 return INSN_REJECTED; /* Rd is PC */
1038 asi->insn_handler = simulate_mrs; 1057 asi->insn_handler = simulate_mrs;
1039 return INSN_GOOD_NO_SLOT; 1058 return INSN_GOOD_NO_SLOT;
1040 } 1059 }
@@ -1065,6 +1084,8 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1065 /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */ 1084 /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
1066 /* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */ 1085 /* BX : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
1067 if ((insn & 0x0ff000d0) == 0x01200010) { 1086 if ((insn & 0x0ff000d0) == 0x01200010) {
1087 if ((insn & 0x0ff000ff) == 0x0120003f)
1088 return INSN_REJECTED; /* BLX pc */
1068 asi->insn_handler = simulate_blx2bx; 1089 asi->insn_handler = simulate_blx2bx;
1069 return INSN_GOOD_NO_SLOT; 1090 return INSN_GOOD_NO_SLOT;
1070 } 1091 }
@@ -1234,6 +1255,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1234{ 1255{
1235 /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */ 1256 /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
1236 if ((insn & 0x0ff000f0) == 0x068000b0) { 1257 if ((insn & 0x0ff000f0) == 0x068000b0) {
1258 if (is_r15(insn, 12))
1259 return INSN_REJECTED; /* Rd is PC */
1237 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */ 1260 insn &= 0xfff00ff0; /* Rd = r0, Rn = r0 */
1238 insn |= 0x00000001; /* Rm = r1 */ 1261 insn |= 0x00000001; /* Rm = r1 */
1239 asi->insn[0] = insn; 1262 asi->insn[0] = insn;
@@ -1247,6 +1270,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1247 /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */ 1270 /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
1248 if ((insn & 0x0fa00030) == 0x06a00010 || 1271 if ((insn & 0x0fa00030) == 0x06a00010 ||
1249 (insn & 0x0fb000f0) == 0x06a00030) { 1272 (insn & 0x0fb000f0) == 0x06a00030) {
1273 if (is_r15(insn, 12))
1274 return INSN_REJECTED; /* Rd is PC */
1250 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */ 1275 insn &= 0xffff0ff0; /* Rd = r0, Rm = r0 */
1251 asi->insn[0] = insn; 1276 asi->insn[0] = insn;
1252 asi->insn_handler = emulate_sat; 1277 asi->insn_handler = emulate_sat;
@@ -1384,6 +1409,9 @@ space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1384{ 1409{
1385 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ 1410 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1386 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ 1411 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1412 if (is_r15(insn, 16) || is_r15(insn, 12))
1413 return INSN_REJECTED; /* Rn or Rd is PC */
1414
1387 insn &= 0xfff00fff; 1415 insn &= 0xfff00fff;
1388 insn |= 0x00001000; /* Rn = r0, Rd = r1 */ 1416 insn |= 0x00001000; /* Rn = r0, Rd = r1 */
1389 asi->insn[0] = insn; 1417 asi->insn[0] = insn;