From patchwork Mon Mar 2 14:25:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 5913951 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AC312BF440 for ; Mon, 2 Mar 2015 14:42:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5F105201FB for ; Mon, 2 Mar 2015 14:42:44 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 66048200E1 for ; Mon, 2 Mar 2015 14:42:43 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YSRVl-0007Va-3C; Mon, 02 Mar 2015 14:39:57 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YSRJI-00045u-4S for linux-arm-kernel@bombadil.infradead.org; Mon, 02 Mar 2015 14:27:04 +0000 Received: from szxga02-in.huawei.com ([119.145.14.65]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YSRJE-0003SO-O1 for linux-arm-kernel@lists.infradead.org; Mon, 02 Mar 2015 14:27:03 +0000 Received: from 172.24.2.119 (EHLO lggeml422-hub.china.huawei.com) ([172.24.2.119]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id CHW85030; Mon, 02 Mar 2015 22:26:01 +0800 (CST) Received: from kernel-host.huawei (10.107.197.247) by lggeml422-hub.china.huawei.com (10.72.61.32) with Microsoft SMTP Server id 14.3.158.1; Mon, 2 Mar 2015 22:25:51 +0800 From: Wang Nan To: , , , , Subject: [RFC PATCH v4 26/34] early kprobes on ftrace: x86: arch code for retrieving kprobed instruction. Date: Mon, 2 Mar 2015 22:25:04 +0800 Message-ID: <1425306312-3437-27-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1425306312-3437-1-git-send-email-wangnan0@huawei.com> References: <1425306312-3437-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.197.247] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150302_092701_368872_078B1B53 X-CRM114-Status: GOOD ( 10.52 ) X-Spam-Score: -4.2 (----) Cc: x86@kernel.org, lizefan@huawei.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP arch_kprobe_on_ftrace_get_old_insn() is for retriving kprobed instrution, which is for ftrace used. When ftrace trying to make call, it compares original instruction against exoected instruction (usually nop), and deny to work if they are different. This newly introduced function returns the bytes pattern of kprobe probed instruction. It doesn't re-read the bytes and returns it to ftrace. Instead, it regenerates the probed instruction for comparing. Signed-off-by: Wang Nan --- arch/x86/kernel/kprobes/core.c | 22 ++++++++++++++++++++++ arch/x86/kernel/kprobes/opt.c | 19 ++++++++++++++----- include/linux/kprobes.h | 6 ++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index ead5b51..87beb64 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1159,4 +1159,26 @@ void arch_fix_ftrace_early_kprobe(struct kprobe *kp, } } +const unsigned char *arch_kprobe_on_ftrace_get_old_insn(struct kprobe *kp, + const unsigned char *ftrace_nop, + unsigned char *dest, size_t insn_size) +{ + u8 brkp[] = {BREAKPOINT_INSTRUCTION}; + struct optimized_kprobe *op; + + if (kp->flags & KPROBE_FLAG_OPTIMIZED) { +#ifndef CONFIG_OPTPROBES + BUG_ON(1); +#else + op = container_of(kp, struct optimized_kprobe, kp); + arch_optimize_kprobes_genbranch(op, dest, insn_size); + return dest; +#endif + } + + memcpy(dest, brkp, INT3_SIZE); + memcpy(dest + INT3_SIZE, ftrace_nop + INT3_SIZE, + insn_size - INT3_SIZE); + return dest; +} #endif diff --git a/arch/x86/kernel/kprobes/opt.c b/arch/x86/kernel/kprobes/opt.c index ef3c0be..9b54148 100644 --- a/arch/x86/kernel/kprobes/opt.c +++ b/arch/x86/kernel/kprobes/opt.c @@ -392,6 +392,19 @@ static int optimize_kprobe_stop_machine(void *data) return 0; } +const unsigned char *arch_optimize_kprobes_genbranch(struct optimized_kprobe *op, + unsigned char *insn_buf, size_t buf_length) +{ + s32 rel = (s32)((long)op->optinsn.insn - + ((long)op->kp.addr + RELATIVEJUMP_SIZE)); + + BUG_ON(buf_length < RELATIVEJUMP_SIZE); + + insn_buf[0] = RELATIVEJUMP_OPCODE; + *(s32 *)(&insn_buf[1]) = rel; + return insn_buf; +} + /* * Replace breakpoints (int3) with relative jumps. * Caller must call with locking kprobe_mutex and text_mutex. @@ -402,8 +415,7 @@ void arch_optimize_kprobes(struct list_head *oplist) u8 insn_buf[RELATIVEJUMP_SIZE]; list_for_each_entry_safe(op, tmp, oplist, list) { - s32 rel = (s32)((long)op->optinsn.insn - - ((long)op->kp.addr + RELATIVEJUMP_SIZE)); + arch_optimize_kprobes_genbranch(op, insn_buf, RELATIVEJUMP_SIZE); WARN_ON(kprobe_disabled(&op->kp)); @@ -411,9 +423,6 @@ void arch_optimize_kprobes(struct list_head *oplist) memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE, RELATIVE_ADDR_SIZE); - insn_buf[0] = RELATIVEJUMP_OPCODE; - *(s32 *)(&insn_buf[1]) = rel; - if (unlikely(kprobes_is_early())) { struct optimize_kprobe_early_param p = { .op = op, diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index ab1a330..5a5290f 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -276,10 +276,16 @@ extern bool arch_within_kprobe_blacklist(unsigned long addr); * its pointer in function decl list. */ struct optimized_kprobe; +#ifdef CONFIG_OPTPROBES +extern const unsigned char *arch_optimize_kprobes_genbranch(struct optimized_kprobe *op, + unsigned char *insn_buf, size_t buf_length); +#endif #if defined(CONFIG_EARLY_KPROBES) && defined(CONFIG_KPROBES_ON_FTRACE) extern void arch_fix_ftrace_early_kprobe(struct kprobe *kp, struct optimized_kprobe *op, int optimized); +extern const unsigned char *arch_kprobe_on_ftrace_get_old_insn(struct kprobe *kp, + const unsigned char *ftrace_nop, unsigned char *dest, size_t insn_size); extern void init_kprobes_on_ftrace(void); extern bool kprobe_fix_ftrace_make_nop(struct dyn_ftrace *rec);