aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-07-03 10:04:26 -0400
committerTixy <tixy@medhuaa1.miniserver.com>2011-07-13 13:32:47 -0400
commitd691023b62bdf33ed84023330f4d2c77d2325b01 (patch)
treefbe9813708414f82dc62d271140d41fd08e6788a
parent46009cc5c59e0acdf165ed8a9d1ccc43baf44800 (diff)
ARM: kprobes: Decode 32-bit Thumb load/store single data item instructions
We will reject probing of unprivileged load and store instructions. These rarely occur and writing test cases for them is difficult. Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
-rw-r--r--arch/arm/kernel/kprobes-thumb.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/arch/arm/kernel/kprobes-thumb.c b/arch/arm/kernel/kprobes-thumb.c
index bf1113c89b15..9be8bea2990c 100644
--- a/arch/arm/kernel/kprobes-thumb.c
+++ b/arch/arm/kernel/kprobes-thumb.c
@@ -118,6 +118,44 @@ t32_simulate_branch(struct kprobe *p, struct pt_regs *regs)
118 regs->ARM_pc = pc + (offset * 2); 118 regs->ARM_pc = pc + (offset * 2);
119} 119}
120 120
121static void __kprobes
122t32_simulate_ldr_literal(struct kprobe *p, struct pt_regs *regs)
123{
124 kprobe_opcode_t insn = p->opcode;
125 unsigned long addr = thumb_probe_pc(p) & ~3;
126 int rt = (insn >> 12) & 0xf;
127 unsigned long rtv;
128
129 long offset = insn & 0xfff;
130 if (insn & 0x00800000)
131 addr += offset;
132 else
133 addr -= offset;
134
135 if (insn & 0x00400000) {
136 /* LDR */
137 rtv = *(unsigned long *)addr;
138 if (rt == 15) {
139 bx_write_pc(rtv, regs);
140 return;
141 }
142 } else if (insn & 0x00200000) {
143 /* LDRH */
144 if (insn & 0x01000000)
145 rtv = *(s16 *)addr;
146 else
147 rtv = *(u16 *)addr;
148 } else {
149 /* LDRB */
150 if (insn & 0x01000000)
151 rtv = *(s8 *)addr;
152 else
153 rtv = *(u8 *)addr;
154 }
155
156 regs->uregs[rt] = rtv;
157}
158
121static enum kprobe_insn __kprobes 159static enum kprobe_insn __kprobes
122t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi) 160t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
123{ 161{
@@ -159,6 +197,32 @@ t32_emulate_ldrdstrd(struct kprobe *p, struct pt_regs *regs)
159} 197}
160 198
161static void __kprobes 199static void __kprobes
200t32_emulate_ldrstr(struct kprobe *p, struct pt_regs *regs)
201{
202 kprobe_opcode_t insn = p->opcode;
203 int rt = (insn >> 12) & 0xf;
204 int rn = (insn >> 16) & 0xf;
205 int rm = insn & 0xf;
206
207 register unsigned long rtv asm("r0") = regs->uregs[rt];
208 register unsigned long rnv asm("r2") = regs->uregs[rn];
209 register unsigned long rmv asm("r3") = regs->uregs[rm];
210
211 __asm__ __volatile__ (
212 "blx %[fn]"
213 : "=r" (rtv), "=r" (rnv)
214 : "0" (rtv), "1" (rnv), "r" (rmv), [fn] "r" (p->ainsn.insn_fn)
215 : "lr", "memory", "cc"
216 );
217
218 regs->uregs[rn] = rnv; /* Writeback base register */
219 if (rt == 15) /* Can't be true for a STR as they aren't allowed */
220 bx_write_pc(rtv, regs);
221 else
222 regs->uregs[rt] = rtv;
223}
224
225static void __kprobes
162t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs) 226t32_emulate_rd8rn16rm0_rwflags(struct kprobe *p, struct pt_regs *regs)
163{ 227{
164 kprobe_opcode_t insn = p->opcode; 228 kprobe_opcode_t insn = p->opcode;
@@ -516,6 +580,87 @@ static const union decode_item t32_table_1111_100x_x0x1__1111[] = {
516 DECODE_END 580 DECODE_END
517}; 581};
518 582
583static const union decode_item t32_table_1111_100x[] = {
584 /* Store/Load single data item */
585
586 /* ??? 1111 100x x11x xxxx xxxx xxxx xxxx xxxx */
587 DECODE_REJECT (0xfe600000, 0xf8600000),
588
589 /* ??? 1111 1001 0101 xxxx xxxx xxxx xxxx xxxx */
590 DECODE_REJECT (0xfff00000, 0xf9500000),
591
592 /* ??? 1111 100x 0xxx xxxx xxxx 10x0 xxxx xxxx */
593 DECODE_REJECT (0xfe800d00, 0xf8000800),
594
595 /* STRBT 1111 1000 0000 xxxx xxxx 1110 xxxx xxxx */
596 /* STRHT 1111 1000 0010 xxxx xxxx 1110 xxxx xxxx */
597 /* STRT 1111 1000 0100 xxxx xxxx 1110 xxxx xxxx */
598 /* LDRBT 1111 1000 0001 xxxx xxxx 1110 xxxx xxxx */
599 /* LDRSBT 1111 1001 0001 xxxx xxxx 1110 xxxx xxxx */
600 /* LDRHT 1111 1000 0011 xxxx xxxx 1110 xxxx xxxx */
601 /* LDRSHT 1111 1001 0011 xxxx xxxx 1110 xxxx xxxx */
602 /* LDRT 1111 1000 0101 xxxx xxxx 1110 xxxx xxxx */
603 DECODE_REJECT (0xfe800f00, 0xf8000e00),
604
605 /* STR{,B,H} Rn,[PC...] 1111 1000 xxx0 1111 xxxx xxxx xxxx xxxx */
606 DECODE_REJECT (0xff1f0000, 0xf80f0000),
607
608 /* STR{,B,H} PC,[Rn...] 1111 1000 xxx0 xxxx 1111 xxxx xxxx xxxx */
609 DECODE_REJECT (0xff10f000, 0xf800f000),
610
611 /* LDR (literal) 1111 1000 x101 1111 xxxx xxxx xxxx xxxx */
612 DECODE_SIMULATEX(0xff7f0000, 0xf85f0000, t32_simulate_ldr_literal,
613 REGS(PC, ANY, 0, 0, 0)),
614
615 /* STR (immediate) 1111 1000 0100 xxxx xxxx 1xxx xxxx xxxx */
616 /* LDR (immediate) 1111 1000 0101 xxxx xxxx 1xxx xxxx xxxx */
617 DECODE_OR (0xffe00800, 0xf8400800),
618 /* STR (immediate) 1111 1000 1100 xxxx xxxx xxxx xxxx xxxx */
619 /* LDR (immediate) 1111 1000 1101 xxxx xxxx xxxx xxxx xxxx */
620 DECODE_EMULATEX (0xffe00000, 0xf8c00000, t32_emulate_ldrstr,
621 REGS(NOPCX, ANY, 0, 0, 0)),
622
623 /* STR (register) 1111 1000 0100 xxxx xxxx 0000 00xx xxxx */
624 /* LDR (register) 1111 1000 0101 xxxx xxxx 0000 00xx xxxx */
625 DECODE_EMULATEX (0xffe00fc0, 0xf8400000, t32_emulate_ldrstr,
626 REGS(NOPCX, ANY, 0, 0, NOSPPC)),
627
628 /* LDRB (literal) 1111 1000 x001 1111 xxxx xxxx xxxx xxxx */
629 /* LDRSB (literal) 1111 1001 x001 1111 xxxx xxxx xxxx xxxx */
630 /* LDRH (literal) 1111 1000 x011 1111 xxxx xxxx xxxx xxxx */
631 /* LDRSH (literal) 1111 1001 x011 1111 xxxx xxxx xxxx xxxx */
632 DECODE_EMULATEX (0xfe5f0000, 0xf81f0000, t32_simulate_ldr_literal,
633 REGS(PC, NOSPPCX, 0, 0, 0)),
634
635 /* STRB (immediate) 1111 1000 0000 xxxx xxxx 1xxx xxxx xxxx */
636 /* STRH (immediate) 1111 1000 0010 xxxx xxxx 1xxx xxxx xxxx */
637 /* LDRB (immediate) 1111 1000 0001 xxxx xxxx 1xxx xxxx xxxx */
638 /* LDRSB (immediate) 1111 1001 0001 xxxx xxxx 1xxx xxxx xxxx */
639 /* LDRH (immediate) 1111 1000 0011 xxxx xxxx 1xxx xxxx xxxx */
640 /* LDRSH (immediate) 1111 1001 0011 xxxx xxxx 1xxx xxxx xxxx */
641 DECODE_OR (0xfec00800, 0xf8000800),
642 /* STRB (immediate) 1111 1000 1000 xxxx xxxx xxxx xxxx xxxx */
643 /* STRH (immediate) 1111 1000 1010 xxxx xxxx xxxx xxxx xxxx */
644 /* LDRB (immediate) 1111 1000 1001 xxxx xxxx xxxx xxxx xxxx */
645 /* LDRSB (immediate) 1111 1001 1001 xxxx xxxx xxxx xxxx xxxx */
646 /* LDRH (immediate) 1111 1000 1011 xxxx xxxx xxxx xxxx xxxx */
647 /* LDRSH (immediate) 1111 1001 1011 xxxx xxxx xxxx xxxx xxxx */
648 DECODE_EMULATEX (0xfec00000, 0xf8800000, t32_emulate_ldrstr,
649 REGS(NOPCX, NOSPPCX, 0, 0, 0)),
650
651 /* STRB (register) 1111 1000 0000 xxxx xxxx 0000 00xx xxxx */
652 /* STRH (register) 1111 1000 0010 xxxx xxxx 0000 00xx xxxx */
653 /* LDRB (register) 1111 1000 0001 xxxx xxxx 0000 00xx xxxx */
654 /* LDRSB (register) 1111 1001 0001 xxxx xxxx 0000 00xx xxxx */
655 /* LDRH (register) 1111 1000 0011 xxxx xxxx 0000 00xx xxxx */
656 /* LDRSH (register) 1111 1001 0011 xxxx xxxx 0000 00xx xxxx */
657 DECODE_EMULATEX (0xfe800fc0, 0xf8000000, t32_emulate_ldrstr,
658 REGS(NOPCX, NOSPPCX, 0, 0, NOSPPC)),
659
660 /* Other unallocated instructions... */
661 DECODE_END
662};
663
519const union decode_item kprobe_decode_thumb32_table[] = { 664const union decode_item kprobe_decode_thumb32_table[] = {
520 665
521 /* 666 /*
@@ -573,6 +718,14 @@ const union decode_item kprobe_decode_thumb32_table[] = {
573 DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111), 718 DECODE_TABLE (0xfe50f000, 0xf810f000, t32_table_1111_100x_x0x1__1111),
574 719
575 /* 720 /*
721 * Store single data item
722 * 1111 1000 xxx0 xxxx xxxx xxxx xxxx xxxx
723 * Load single data items
724 * 1111 100x xxx1 xxxx xxxx xxxx xxxx xxxx
725 */
726 DECODE_TABLE (0xfe000000, 0xf8000000, t32_table_1111_100x),
727
728 /*
576 * Coprocessor instructions 729 * Coprocessor instructions
577 * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx 730 * 1111 11xx xxxx xxxx xxxx xxxx xxxx xxxx
578 */ 731 */