From: tixy@yxit.co.uk (Tixy)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] Fix ldrd/strd emulation for kprobes/ARM
Date: Tue, 29 Mar 2011 13:55:01 +0100 [thread overview]
Message-ID: <1301403301.2519.125.camel@computer2.home> (raw)
In-Reply-To: <1301327765-6996-1-git-send-email-viktor.rosendahl@nokia.com>
On Mon, 2011-03-28 at 18:56 +0300, Viktor Rosendahl wrote:
> On 03/25/2011 11:19 PM, ext Tixy wrote:
> > On Fri, 2011-03-25 at 19:01 +0200, Viktor Rosendahl wrote:
> >> The Rn value from the emulation is unconditionally written back; this is fine
> >> as long as Rn != PC because in that case, even if the instruction isn't a write
> >> back instruction, it will only result in the same value being written back.
> >>
> >> In case Rn == PC, then the emulated instruction doesn't have the actual PC
> >> value in Rn but an adjusted value; when this is written back, it will result in
> >> the PC being incorrectly updated.
> > It looks like we have the same problem with emulate_ldrd and
> > emulate_strd as well.
>
> Yes, it seems so. Currently emulate_ldrd and emulate_strd don't even have the
> adjustment of the PC value, so in case of Rn == PC, it will not update the PC
> incorrectly but instead load/store from the wrong address. Below is a patch
> that adds both the adjustment of the PC value and the check for PC == PC.
>
> I haven't tested this code at all and I am not sure of how to test it.
In a day or two I should have support in my test code for these sorts of
instructions. From looking at them, the changes look functionally
correct though. I do have a suggestion for slight change, see inline
comments below...
>
> Signed-off-by: Viktor Rosendahl <viktor.rosendahl@nokia.com>
> ---
> arch/arm/kernel/kprobes-decode.c | 20 +++++++++++++++-----
> 1 files changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c
> index 2389131..3b0cf90 100644
> --- a/arch/arm/kernel/kprobes-decode.c
> +++ b/arch/arm/kernel/kprobes-decode.c
> @@ -540,9 +540,12 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
> {
> insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
> kprobe_opcode_t insn = p->opcode;
> + long ppc = (long)p->addr + 8;
> int rd = (insn >> 12) & 0xf;
> int rn = (insn >> 16) & 0xf;
> int rm = insn & 0xf; /* rm may be invalid, don't care. */
> + long rmv = (rm == 15) ? ppc : regs->uregs[rm];
> + long rnv = (rn == 15) ? ppc : regs->uregs[rn];
>
> /* Not following the C calling convention here, so need asm(). */
> __asm__ __volatile__ (
> @@ -554,29 +557,36 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
> "str r0, %[rn] \n\t" /* in case of writeback */
> "str r2, %[rd0] \n\t"
> "str r3, %[rd1] \n\t"
> - : [rn] "+m" (regs->uregs[rn]),
> + : [rn] "+m" (rnv),
> [rd0] "=m" (regs->uregs[rd]),
> [rd1] "=m" (regs->uregs[rd+1])
> - : [rm] "m" (regs->uregs[rm]),
> + : [rm] "m" (rmv),
> [cpsr] "r" (regs->ARM_cpsr),
> [i_fn] "r" (i_fn)
> : "r0", "r1", "r2", "r3", "lr", "cc"
> );
> + if (rn != 15)
> + regs->uregs[rn] = rnv; /* Save Rn in case of writeback. */
> }
If the variables rnv and rmv were declared as registers then we could
avoid 3 stores and 3 loads of stack values. This would require changing
the the assembler as well, e.g. something like this...
register long rnv asm("r0");
register long rmv asm("r1");
rnv = (rn == 15) ? ppc : regs->uregs[rn];
rmv = (rm == 15) ? ppc : regs->uregs[rm];
__asm__ __volatile__ (
"msr cpsr_fs, %[cpsr]\n\t"
"mov lr, pc \n\t"
"mov pc, %[i_fn] \n\t"
"str r2, %[rd0] \n\t"
"str r3, %[rd1] \n\t"
: "=r" (rnv),
[rd0] "=m" (regs->uregs[rd]),
[rd1] "=m" (regs->uregs[rd+1])
: "0" (rnv),
"r" (rmv),
[cpsr] "r" (regs->ARM_cpsr),
[i_fn] "r" (i_fn)
: "r2", "r3", "lr", "cc"
);
if (rn != 15)
regs->uregs[rn] = rnv;
>
> static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
> {
> insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
> kprobe_opcode_t insn = p->opcode;
> + long ppc = (long)p->addr + 8;
> int rd = (insn >> 12) & 0xf;
> int rn = (insn >> 16) & 0xf;
> int rm = insn & 0xf;
> - long rnv = regs->uregs[rn];
> - long rmv = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */
> + long rnv = (rn == 15) ? ppc : regs->uregs[rn];
> + /* rm/rmv may be invalid, don't care. */
> + long rmv = (rm == 15) ? ppc : regs->uregs[rm];
> + long rnv_wb;
>
> - regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
> + rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
> regs->uregs[rd+1],
> regs->ARM_cpsr, i_fn);
> + if (rn != 15)
> + regs->uregs[rn] = rnv_wb; /* Save Rn in case of writeback. */
> }
>
> static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
--
Tixy
next prev parent reply other threads:[~2011-03-29 12:55 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-25 17:01 [PATCH] kprobes/arm: fix emulation of LDR/STR instruction when Rn == PC Viktor Rosendahl
2011-03-25 21:19 ` Tixy
2011-03-28 15:56 ` [PATCH] Fix ldrd/strd emulation for kprobes/ARM Viktor Rosendahl
2011-03-28 22:39 ` Nicolas Pitre
2011-03-29 11:26 ` Viktor Rosendahl
2011-03-29 16:55 ` Nicolas Pitre
2011-03-29 18:31 ` Russell King - ARM Linux
2011-03-29 18:44 ` Nicolas Pitre
2011-03-30 13:42 ` [PATCH] Reject kprobes when Rn==15 and writeback is set Viktor Rosendahl
2011-03-30 15:52 ` Tixy
2011-03-30 16:46 ` Viktor Rosendahl
2011-03-30 17:20 ` Tixy
2011-03-30 17:59 ` Nicolas Pitre
2011-03-30 19:39 ` Tixy
2011-03-30 20:48 ` Nicolas Pitre
2011-03-30 14:09 ` [PATCH] Fix ldrd/strd emulation for kprobes/ARM Viktor Rosendahl
2011-03-29 12:55 ` Tixy [this message]
2011-03-29 13:46 ` Viktor Rosendahl
2011-03-29 14:03 ` Tixy
2011-03-29 17:07 ` Nicolas Pitre
2011-03-28 16:27 ` [PATCH] kprobes/arm: fix emulation of LDR/STR instruction when Rn == PC Viktor Rosendahl
2011-03-29 9:12 ` Tixy
2011-03-26 2:03 ` Nicolas Pitre
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1301403301.2519.125.camel@computer2.home \
--to=tixy@yxit.co.uk \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).