Received: by 2002:a05:6a10:413:0:0:0:0 with SMTP id 19csp3475217pxp; Tue, 8 Mar 2022 15:24:59 -0800 (PST) X-Google-Smtp-Source: ABdhPJwdKlCgIRRfR03dnon2uTa+OdeC/AwUqI3qlZbqbCBxwC+3GV4RrL6rF+gxNbOXNGOP4LC5 X-Received: by 2002:a63:81c8:0:b0:380:2ff3:514c with SMTP id t191-20020a6381c8000000b003802ff3514cmr11962172pgd.428.1646781899513; Tue, 08 Mar 2022 15:24:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1646781899; cv=none; d=google.com; s=arc-20160816; b=G/MVvQpkrQCVPlIqMXpxPHeFlVsksShpFHCQk4J2BVs92SAaanJ8IwhbJZd2iH7n2J ETEkaAEoMhRFBcb7WoHei8s1QuqPBXctECJHDllOxBBWZTA7em3CuG9mRWm70Z/+BiNv m0dmP6SM12CI+Vm3CjM1GURJNe6p7x+z5QO08ahvLNfB073Fh/lEPO1W6ojSpACVFlir a+PyZc+2CmRBO2OcXQxZ10TxUpGvqws+Dwf/HQsTtvzExjmdSfMdpFDK5kskWC0+RMrQ xM5WQZXIA2BBv5+g3UNwMHOJI+A3oNHxRk8ikJJNBaHM2Wi+oW4JG/NI2+Q882cokHte AQ3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=09tllMBxYLWT7MVGDhQmyZJeT8jYNPnlOaA4y5vUdmM=; b=YTDSO1X4cKqa+dvIyIjI1Av1sBSOv8pMWAbujkLgCGu7lzuidkgI0muC5dut1m447n jZOS1iaTX6IXz3V2cRC/zElaMUtVVP5uyqUllAu+MZZyP79VXOraGbsXpSmaiqjZ7run rH+SEFi3FlLEYmDWQqoooY3KObxgsNwMbjksuXHWRlf32zwoCpDXOzDKGZFe6wQd/prD EBEE87+CZ+UENPOC+npmsg0zXQ2yVjAU+GnAm/n6TMmoXgKip4di95+6+PeUcOvinKUo Ebe3Ew9+PHlUWxPDPpQhfj0ynKpZxCAq9u21d6Zofu5Y2Sw8yzJog/LTN4n90sIFV6A+ ueKA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=FVVDN0E4; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id d16-20020a170902ced000b0015301b286aesi189357plg.624.2022.03.08.15.24.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Mar 2022 15:24:59 -0800 (PST) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=FVVDN0E4; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 4361B91345; Tue, 8 Mar 2022 15:16:14 -0800 (PST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346354AbiCHLLm (ORCPT + 99 others); Tue, 8 Mar 2022 06:11:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50434 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346357AbiCHLLb (ORCPT ); Tue, 8 Mar 2022 06:11:31 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1650246177; Tue, 8 Mar 2022 03:10:31 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 8CC5E61602; Tue, 8 Mar 2022 11:10:31 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 82741C340EB; Tue, 8 Mar 2022 11:10:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1646737831; bh=11oxb9yaROPxs0+LsOoCAd2B2Rmo0siA0o2ZuHPqprA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FVVDN0E4ZPzd80xSpRjPfsn2wTf3ie3zCJoGCUFtRhW4GWSDw5GHvOv28kb2SEpZ4 mvQRlBtjvJmV8v0fGOVB7yKZe+GnZVQrfK5ZIrexfRALtuFvcf7NY1bo7peALaqa4C V+bOaXfWZIv1SQn6MQFwUWJ7QT23jihhe+Yz5bYX0n63zkrYA1U2rLETD5W47Z2Skl BIESfHUiNyVn3+kk41MeBmsUsz6lL/0yQTFoloGj8WyTy7lJMJ/TctmpuBX21iHU3m rq5d70fMVaa/X8i0by9q3aidtxJTDOqvyDEk87A1sj7aIbqwUT7IWuuBK9ob3Htnbk bo2sKdU7XQ5IA== From: Masami Hiramatsu To: Jiri Olsa , Alexei Starovoitov Cc: Daniel Borkmann , Andrii Nakryiko , Masami Hiramatsu , netdev@vger.kernel.org, bpf@vger.kernel.org, lkml , Martin KaFai Lau , Song Liu , Yonghong Song , John Fastabend , KP Singh , Steven Rostedt , "Naveen N . Rao" , Anil S Keshavamurthy , "David S . Miller" Subject: [PATCH v10 10/12] fprobe: Introduce FPROBE_FL_KPROBE_SHARED flag for fprobe Date: Tue, 8 Mar 2022 20:10:25 +0900 Message-Id: <164673782515.1984170.11213788690974992702.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <164673771096.1984170.8155877393151850116.stgit@devnote2> References: <164673771096.1984170.8155877393151850116.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Introduce FPROBE_FL_KPROBE_SHARED flag for sharing fprobe callback with kprobes safely from the viewpoint of recursion. Since the recursion safety of the fprobe (and ftrace) is a bit different from the kprobes, this may cause an issue if user wants to run the same code from the fprobe and the kprobes. The kprobes has per-cpu 'current_kprobe' variable which protects the kprobe handler from recursion in any case. On the other hand, the fprobe uses only ftrace_test_recursion_trylock(), which will allow interrupt context calls another (or same) fprobe during the fprobe user handler is running. This is not a matter in cases if the common callback shared among the kprobes and the fprobe has its own recursion detection, or it can handle the recursion in the different contexts (normal/interrupt/NMI.) But if it relies on the 'current_kprobe' recursion lock, it has to check kprobe_running() and use kprobe_busy_*() APIs. Fprobe has FPROBE_FL_KPROBE_SHARED flag to do this. If your common callback code will be shared with kprobes, please set FPROBE_FL_KPROBE_SHARED *before* registering the fprobe, like; fprobe.flags = FPROBE_FL_KPROBE_SHARED; register_fprobe(&fprobe, "func*", NULL); This will protect your common callback from the nested call. Signed-off-by: Masami Hiramatsu --- include/linux/fprobe.h | 12 ++++++++++++ include/linux/kprobes.h | 3 +++ kernel/trace/fprobe.c | 19 ++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index 8eefec2b485e..1c2bde0ead73 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -34,13 +34,25 @@ struct fprobe { void (*exit_handler)(struct fprobe *fp, unsigned long entry_ip, struct pt_regs *regs); }; +/* This fprobe is soft-disabled. */ #define FPROBE_FL_DISABLED 1 +/* + * This fprobe handler will be shared with kprobes. + * This flag must be set before registering. + */ +#define FPROBE_FL_KPROBE_SHARED 2 + static inline bool fprobe_disabled(struct fprobe *fp) { return (fp) ? fp->flags & FPROBE_FL_DISABLED : false; } +static inline bool fprobe_shared_with_kprobes(struct fprobe *fp) +{ + return (fp) ? fp->flags & FPROBE_FL_KPROBE_SHARED : false; +} + #ifdef CONFIG_FPROBE int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter); int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num); diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 19b884353b15..5f1859836deb 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -427,6 +427,9 @@ static inline struct kprobe *kprobe_running(void) { return NULL; } +#define kprobe_busy_begin() do {} while (0) +#define kprobe_busy_end() do {} while (0) + static inline int register_kprobe(struct kprobe *p) { return -EOPNOTSUPP; diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index 38073632bfe4..8b2dd5b9dcd1 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -56,6 +56,20 @@ static void fprobe_handler(unsigned long ip, unsigned long parent_ip, } NOKPROBE_SYMBOL(fprobe_handler); +static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *ops, struct ftrace_regs *fregs) +{ + struct fprobe *fp = container_of(ops, struct fprobe, ops); + + if (unlikely(kprobe_running())) { + fp->nmissed++; + return; + } + kprobe_busy_begin(); + fprobe_handler(ip, parent_ip, ops, fregs); + kprobe_busy_end(); +} + static void fprobe_exit_handler(struct rethook_node *rh, void *data, struct pt_regs *regs) { @@ -110,7 +124,10 @@ static unsigned long *get_ftrace_locations(const char **syms, int num) static void fprobe_init(struct fprobe *fp) { fp->nmissed = 0; - fp->ops.func = fprobe_handler; + if (fprobe_shared_with_kprobes(fp)) + fp->ops.func = fprobe_kprobe_handler; + else + fp->ops.func = fprobe_handler; fp->ops.flags |= FTRACE_OPS_FL_SAVE_REGS; }