aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-04-18 03:53:54 -0400
committerNicolas Pitre <nicolas.pitre@linaro.org>2011-04-28 23:40:58 -0400
commitfa1a03b429b3fd5f28e7fdd20ce99ca572bfd236 (patch)
tree3b69ca654478557d3b6432e2e0a44095628e70f8 /arch/arm
parentc6e4ae32911c2a0ad02d47ee59ccba352a74c38e (diff)
ARM: kprobes: Reject probing of all coprocessor instructions
The kernel doesn't currently support VFP or Neon code, and probing of code with CP15 operations is fraught with bad consequences. Therefore we don't need the ability to probe coprocessor instructions and the code to support this can be removed. The removed code also had at least two bugs: - MRC into R15 should set CPSR not trash PC - LDC and STC which use PC as base register needed the address offset by 8 Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/kprobes-decode.c113
1 files changed, 11 insertions, 102 deletions
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index 8391dac41855..ff3970741653 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -520,17 +520,6 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
520 regs->uregs[12] = regs->uregs[13]; 520 regs->uregs[12] = regs->uregs[13];
521} 521}
522 522
523static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
524{
525 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
526 kprobe_opcode_t insn = p->opcode;
527 int rn = (insn >> 16) & 0xf;
528 long rnv = regs->uregs[rn];
529
530 /* Save Rn in case of writeback. */
531 regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
532}
533
534static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs) 523static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
535{ 524{
536 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0]; 525 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
@@ -635,31 +624,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
635 regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */ 624 regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */
636} 625}
637 626
638static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
639{
640 insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
641 kprobe_opcode_t insn = p->opcode;
642 union reg_pair fnr;
643 int rd = (insn >> 12) & 0xf;
644 int rn = (insn >> 16) & 0xf;
645
646 fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
647 regs->uregs[rn] = fnr.r0;
648 regs->uregs[rd] = fnr.r1;
649}
650
651static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
652{
653 insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
654 kprobe_opcode_t insn = p->opcode;
655 int rd = (insn >> 12) & 0xf;
656 int rn = (insn >> 16) & 0xf;
657 long rnv = regs->uregs[rn];
658 long rdv = regs->uregs[rd];
659
660 insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
661}
662
663static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs) 627static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
664{ 628{
665 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; 629 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
@@ -693,24 +657,6 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
693 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn); 657 insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
694} 658}
695 659
696static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
697{
698 insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
699 kprobe_opcode_t insn = p->opcode;
700 int rd = (insn >> 12) & 0xf;
701
702 regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
703}
704
705static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
706{
707 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
708 kprobe_opcode_t insn = p->opcode;
709 int ird = (insn >> 12) & 0xf;
710
711 insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
712}
713
714static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs) 660static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
715{ 661{
716 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0]; 662 insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
@@ -1010,40 +956,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1010 } 956 }
1011 957
1012 /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */ 958 /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
1013 /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ 959 if ((insn & 0xffff00f0) == 0xf1010000) {
1014 if ((insn & 0xffff00f0) == 0xf1010000 ||
1015 (insn & 0xff000010) == 0xfe000000) {
1016 asi->insn[0] = insn; 960 asi->insn[0] = insn;
1017 asi->insn_handler = emulate_none; 961 asi->insn_handler = emulate_none;
1018 return INSN_GOOD; 962 return INSN_GOOD;
1019 } 963 }
1020 964
965 /* Coprocessor instructions... */
1021 /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */ 966 /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
1022 /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */ 967 /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
1023 if ((insn & 0xffe00000) == 0xfc400000) { 968 /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1024 insn &= 0xfff00fff; /* Rn = r0 */ 969 /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1025 insn |= 0x00001000; /* Rd = r1 */ 970 /* CDP2 : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1026 asi->insn[0] = insn; 971 /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1027 asi->insn_handler = 972 /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1028 (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1029 return INSN_GOOD;
1030 }
1031 973
1032 /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ 974 return INSN_REJECTED;
1033 /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1034 if ((insn & 0xfe000000) == 0xfc000000) {
1035 insn &= 0xfff0ffff; /* Rn = r0 */
1036 asi->insn[0] = insn;
1037 asi->insn_handler = emulate_ldcstc;
1038 return INSN_GOOD;
1039 }
1040
1041 /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1042 /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1043 insn &= 0xffff0fff; /* Rd = r0 */
1044 asi->insn[0] = insn;
1045 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1046 return INSN_GOOD;
1047} 975}
1048 976
1049static enum kprobe_insn __kprobes 977static enum kprobe_insn __kprobes
@@ -1504,14 +1432,7 @@ space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1504{ 1432{
1505 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ 1433 /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1506 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */ 1434 /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
1507 if (is_r15(insn, 16) || is_r15(insn, 12)) 1435 return INSN_REJECTED;
1508 return INSN_REJECTED; /* Rn or Rd is PC */
1509
1510 insn &= 0xfff00fff;
1511 insn |= 0x00001000; /* Rn = r0, Rd = r1 */
1512 asi->insn[0] = insn;
1513 asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
1514 return INSN_GOOD;
1515} 1436}
1516 1437
1517static enum kprobe_insn __kprobes 1438static enum kprobe_insn __kprobes
@@ -1519,10 +1440,7 @@ space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1519{ 1440{
1520 /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */ 1441 /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
1521 /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */ 1442 /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
1522 insn &= 0xfff0ffff; /* Rn = r0 */ 1443 return INSN_REJECTED;
1523 asi->insn[0] = insn;
1524 asi->insn_handler = emulate_ldcstc;
1525 return INSN_GOOD;
1526} 1444}
1527 1445
1528static enum kprobe_insn __kprobes 1446static enum kprobe_insn __kprobes
@@ -1535,18 +1453,9 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
1535 return INSN_REJECTED; 1453 return INSN_REJECTED;
1536 1454
1537 /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */ 1455 /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
1538 if ((insn & 0x0f000010) == 0x0e000000) {
1539 asi->insn[0] = insn;
1540 asi->insn_handler = emulate_none;
1541 return INSN_GOOD;
1542 }
1543
1544 /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */ 1456 /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
1545 /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */ 1457 /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
1546 insn &= 0xffff0fff; /* Rd = r0 */ 1458 return INSN_REJECTED;
1547 asi->insn[0] = insn;
1548 asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
1549 return INSN_GOOD;
1550} 1459}
1551 1460
1552static unsigned long __kprobes __check_eq(unsigned long cpsr) 1461static unsigned long __kprobes __check_eq(unsigned long cpsr)