lkml.org 
[lkml]   [2017]   [Mar]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH tip/master V2 4/8] kprobes/x86: Do not modify singlestep buffer while resuming
    Date
    Do not modify singlestep execution buffer (kprobe.ainsn.insn)
    while resuming from single-stepping, instead, modifies
    the buffer to add a jump back instruction at preparing
    buffer.

    Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
    ---
    arch/x86/kernel/kprobes/core.c | 42 +++++++++++++++++++---------------------
    1 file changed, 20 insertions(+), 22 deletions(-)

    diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
    index 6327f95..ea3b8e5 100644
    --- a/arch/x86/kernel/kprobes/core.c
    +++ b/arch/x86/kernel/kprobes/core.c
    @@ -399,23 +399,36 @@ int __copy_instruction(u8 *dest, u8 *src)
    return length;
    }

    +/* Prepare reljump right after instruction to boost */
    +static void prepare_boost(struct kprobe *p, int length)
    +{
    + if (can_boost(p->ainsn.insn, p->addr) &&
    + MAX_INSN_SIZE - length >= RELATIVEJUMP_SIZE) {
    + /*
    + * These instructions can be executed directly if it
    + * jumps back to correct address.
    + */
    + synthesize_reljump((void *)p->ainsn.insn + length,
    + (void *)p->addr + length);
    + p->ainsn.boostable = 1;
    + } else
    + p->ainsn.boostable = -1;
    +}
    +
    static int arch_copy_kprobe(struct kprobe *p)
    {
    - int ret;
    + int len;

    /* Copy an instruction with recovering if other optprobe modifies it.*/
    - ret = __copy_instruction(p->ainsn.insn, p->addr);
    - if (!ret)
    + len = __copy_instruction(p->ainsn.insn, p->addr);
    + if (!len)
    return -EINVAL;

    /*
    * __copy_instruction can modify the displacement of the instruction,
    * but it doesn't affect boostable check.
    */
    - if (can_boost(p->ainsn.insn, p->addr))
    - p->ainsn.boostable = 0;
    - else
    - p->ainsn.boostable = -1;
    + prepare_boost(p, len);

    /* Check whether the instruction modifies Interrupt Flag or not */
    p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn);
    @@ -878,21 +891,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs,
    break;
    }

    - if (p->ainsn.boostable == 0) {
    - if ((regs->ip > copy_ip) &&
    - (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
    - /*
    - * These instructions can be executed directly if it
    - * jumps back to correct address.
    - */
    - synthesize_reljump((void *)regs->ip,
    - (void *)orig_ip + (regs->ip - copy_ip));
    - p->ainsn.boostable = 1;
    - } else {
    - p->ainsn.boostable = -1;
    - }
    - }
    -
    regs->ip += orig_ip - copy_ip;

    no_change:
    \
     
     \ /
      Last update: 2017-03-27 10:03    [W:2.583 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site