aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-04-07 13:25:16 +0100
committerNicolas Pitre <nicolas.pitre@linaro.org>2011-04-28 23:40:55 -0400
commitc412aba2a1243192a4d53736805a96bdda915608 (patch)
treef04010b8c82fcc4ef9934144dd8eb8cbf6f8ad1c /arch/arm/kernel
parentARM: kprobes: Reject probing MRS instructions which read SPSR (diff)
downloadlinux-dev-c412aba2a1243192a4d53736805a96bdda915608.tar.xz
linux-dev-c412aba2a1243192a4d53736805a96bdda915608.zip
ARM: kprobes: Fix emulation of MRS instruction
The MRS instruction should set mode and interrupt bits in the read value so it is simpler to use a new simulation routine (simulate_mrs) rather than some modified emulation. prep_emulate_rd12 is now unused and removed. Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/kprobes-decode.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
index e5bc576ba3fb..4ab83f4c47cf 100644
--- a/arch/arm/kernel/kprobes-decode.c
+++ b/arch/arm/kernel/kprobes-decode.c
@@ -451,6 +451,14 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
regs->ARM_cpsr |= PSR_T_BIT;
}
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+ kprobe_opcode_t insn = p->opcode;
+ int rd = (insn >> 12) & 0xf;
+ unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+ regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
{
kprobe_opcode_t insn = p->opcode;
@@ -896,15 +904,6 @@ prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
}
static enum kprobe_insn __kprobes
-prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
-{
- insn &= 0xffff0fff; /* Rd = r0 */
- asi->insn[0] = insn;
- asi->insn_handler = emulate_rd12;
- return INSN_GOOD;
-}
-
-static enum kprobe_insn __kprobes
prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
struct arch_specific_insn *asi)
{
@@ -1035,8 +1034,10 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
return INSN_REJECTED;
/* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
- if ((insn & 0x0ff000f0) == 0x01000000)
- return prep_emulate_rd12(insn, asi);
+ if ((insn & 0x0ff000f0) == 0x01000000) {
+ asi->insn_handler = simulate_mrs;
+ return INSN_GOOD_NO_SLOT;
+ }
/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
if ((insn & 0x0ff00090) == 0x01400080)