From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
To: Petr Mladek <pmladek@suse.cz>, Ingo Molnar <mingo@elte.hu>
Cc: "David S. Miller" <davem@davemloft.net>,
Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
Ananth NMavinakayanahalli <ananth@in.ibm.com>,
Frederic Weisbecker <fweisbec@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
Jiri Kosina <jkosina@suse.cz>,
linux-kernel@vger.kernel.org, Ingo Molnar <mingo@redhat.com>
Subject: Re: [PATCH v2] kprobes/x86: Use 5-byte NOP when the code might be modified by ftrace
Date: Tue, 03 Feb 2015 16:41:39 +0900 [thread overview]
Message-ID: <54D07BB3.1020806@hitachi.com> (raw)
In-Reply-To: <1422899338-26399-1-git-send-email-pmladek@suse.cz>
(2015/02/03 2:48), Petr Mladek wrote:
> can_probe() checks if the given address points to the beginning of
> an instruction. It analyzes all the instructions from the beginning
> of the function until the given address. The code might be modified
> by another Kprobe. In this case, the current code is read into a buffer,
> int3 breakpoint is replaced by the saved opcode in the buffer, and
> can_probe() analyzes the buffer instead.
>
> There is a bug that __recover_probed_insn() tries to restore
> the original code even for Kprobes using the ftrace framework.
> But in this case, the opcode is not stored. See the difference
> between arch_prepare_kprobe() and arch_prepare_kprobe_ftrace().
> The opcode is stored by arch_copy_kprobe() only from
> arch_prepare_kprobe().
>
> This patch makes Kprobe to use the ideal 5-byte NOP when the code
> can be modified by ftrace. It is the original instruction, see
> ftrace_make_nop() and ftrace_nop_replace().
>
> Note that we always need to use the NOP for ftrace locations. Kprobes
> do not block ftrace and the instruction might get modified at anytime.
> It might even be in an inconsistent state because it is modified step
> by step using the int3 breakpoint.
>
> The patch also fixes indentation of the touched comment.
>
> Note that I found this problem when playing with Kprobes. I did it
> on x86_64 with gcc-4.8.3 that supported -mfentry. I modified
> samples/kprobes/kprobe_example.c and added offset 5 to put
> the probe right after the fentry area:
>
> --- cut ---
> static struct kprobe kp = {
> .symbol_name = "do_fork",
> + .offset = 5,
> };
> --- cut ---
>
> Then I was able to load kprobe_example before jprobe_example
> but not the other way around:
>
> $> modprobe jprobe_example
> $> modprobe kprobe_example
> modprobe: ERROR: could not insert 'kprobe_example': Invalid or incomplete multibyte or wide character
>
> It did not make much sense and debugging pointed to the bug
> described above.
>
This looks good to me :)
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Ingo, could you merge this as an urgent fix?
Thank you!
> Signed-off-by: Petr Mladek <pmladek@suse.cz>
> ---
> arch/x86/kernel/kprobes/core.c | 42 ++++++++++++++++++++++++++++--------------
> 1 file changed, 28 insertions(+), 14 deletions(-)
>
> Changes against v1:
>
> + always use 5-byte NOP for ftrace location
> + fix indentation of the touched comment
>
> diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
> index 98f654d466e5..2f464b56766a 100644
> --- a/arch/x86/kernel/kprobes/core.c
> +++ b/arch/x86/kernel/kprobes/core.c
> @@ -223,27 +223,41 @@ static unsigned long
> __recover_probed_insn(kprobe_opcode_t *buf, unsigned long addr)
> {
> struct kprobe *kp;
> + unsigned long faddr;
>
> kp = get_kprobe((void *)addr);
> - /* There is no probe, return original address */
> - if (!kp)
> + faddr = ftrace_location(addr);
> + /*
> + * Use the current code if it is not modified by Kprobe
> + * and it cannot be modified by ftrace.
> + */
> + if (!kp && !faddr)
> return addr;
>
> /*
> - * Basically, kp->ainsn.insn has an original instruction.
> - * However, RIP-relative instruction can not do single-stepping
> - * at different place, __copy_instruction() tweaks the displacement of
> - * that instruction. In that case, we can't recover the instruction
> - * from the kp->ainsn.insn.
> + * Basically, kp->ainsn.insn has an original instruction.
> + * However, RIP-relative instruction can not do single-stepping
> + * at different place, __copy_instruction() tweaks the displacement of
> + * that instruction. In that case, we can't recover the instruction
> + * from the kp->ainsn.insn.
> *
> - * On the other hand, kp->opcode has a copy of the first byte of
> - * the probed instruction, which is overwritten by int3. And
> - * the instruction at kp->addr is not modified by kprobes except
> - * for the first byte, we can recover the original instruction
> - * from it and kp->opcode.
> + * On the other hand, in case on normal Kprobe, kp->opcode has a copy
> + * of the first byte of the probed instruction, which is overwritten
> + * by int3. And the instruction at kp->addr is not modified by kprobes
> + * except for the first byte, we can recover the original instruction
> + * from it and kp->opcode.
> + *
> + * In case of Kprobes using ftrace, we do not have a copy of
> + * the original instruction. In fact, the ftrace location might
> + * be modified at anytime and even could be in an inconsistent state.
> + * Fortunately, we know that the original code is the ideal 5-byte
> + * long NOP.
> */
> - memcpy(buf, kp->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
> - buf[0] = kp->opcode;
> + memcpy(buf, (void *)addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
> + if (faddr)
> + memcpy(buf, ideal_nops[NOP_ATOMIC5], MCOUNT_INSN_SIZE);
> + else
> + buf[0] = kp->opcode;
> return (unsigned long)buf;
> }
>
>
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Research Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
next prev parent reply other threads:[~2015-02-03 7:41 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-02 17:48 [PATCH v2] kprobes/x86: Use 5-byte NOP when the code might be modified by ftrace Petr Mladek
2015-02-03 7:41 ` Masami Hiramatsu [this message]
2015-02-03 11:38 ` Petr Mladek
2015-02-03 11:52 ` Masami Hiramatsu
2015-02-03 12:00 ` Petr Mladek
2015-02-18 21:22 ` Ingo Molnar
2015-02-20 10:16 ` Petr Mladek
2015-02-20 10:16 ` [PATCH 1/2] " Petr Mladek
2015-02-20 10:26 ` Ingo Molnar
2015-02-20 12:38 ` Masami Hiramatsu
2015-02-20 12:52 ` Ingo Molnar
2015-02-20 13:25 ` Masami Hiramatsu
2015-02-20 13:34 ` Petr Mladek
2015-02-20 10:16 ` [PATCH 2/2] kprobes/x86: Check for invalid ftrace location in __recover_probed_insn() Petr Mladek
2015-02-20 10:19 ` Ingo Molnar
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=54D07BB3.1020806@hitachi.com \
--to=masami.hiramatsu.pt@hitachi.com \
--cc=ananth@in.ibm.com \
--cc=anil.s.keshavamurthy@intel.com \
--cc=davem@davemloft.net \
--cc=fweisbec@gmail.com \
--cc=jkosina@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=mingo@redhat.com \
--cc=pmladek@suse.cz \
--cc=rostedt@goodmis.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.