From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752774AbdC2FBY (ORCPT ); Wed, 29 Mar 2017 01:01:24 -0400 Received: from mail.kernel.org ([198.145.29.136]:42224 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752258AbdC2FBW (ORCPT ); Wed, 29 Mar 2017 01:01:22 -0400 From: Masami Hiramatsu To: linux-kernel@vger.kernel.org, Ingo Molnar Cc: Peter Zijlstra , Thomas Gleixner , "H . Peter Anvin" , Ananth N Mavinakayanahalli , Anil S Keshavamurthy , "David S . Miller" , Andrey Ryabinin , Ye Xiaolong , mhiramat@kernel.org Subject: [RFC PATCH tip/master V3 4/8] kprobes/x86: Do not modify singlestep buffer while resuming Date: Wed, 29 Mar 2017 14:00:25 +0900 Message-Id: <149076361560.22469.1610155860343077495.stgit@devbox> X-Mailer: git-send-email 2.9.3 In-Reply-To: <149076333370.22469.11135086121721120819.stgit@devbox> References: <149076333370.22469.11135086121721120819.stgit@devbox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- Changes in v3: - Fix imbalance curly braces. - Remove unneeded (void *) casting. --- 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..a654054 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(p->ainsn.insn + length, 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: