public inbox for patches@lists.linux.dev
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	patches@lists.linux.dev, Andrii Nakryiko <andrii@kernel.org>,
	Jiri Olsa <jolsa@kernel.org>, Alexei Starovoitov <ast@kernel.org>
Subject: [PATCH 6.0 05/28] bpf: Take module reference on kprobe_multi link
Date: Mon, 19 Dec 2022 20:22:52 +0100	[thread overview]
Message-ID: <20221219182944.420203135@linuxfoundation.org> (raw)
In-Reply-To: <20221219182944.179389009@linuxfoundation.org>

From: Jiri Olsa <jolsa@kernel.org>

commit e22061b2d3095c12f90336479f24bf5eeb70e1bd upstream.

Currently we allow to create kprobe multi link on function from kernel
module, but we don't take the module reference to ensure it's not
unloaded while we are tracing it.

The multi kprobe link is based on fprobe/ftrace layer which takes
different approach and releases ftrace hooks when module is unloaded
even if there's tracer registered on top of it.

Adding code that gathers all the related modules for the link and takes
their references before it's attached. All kernel module references are
released after link is unregistered.

Note that we do it the same way already for trampoline probes
(but for single address).

Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20221025134148.3300700-5-jolsa@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 kernel/trace/bpf_trace.c |   92 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2264,6 +2264,8 @@ struct bpf_kprobe_multi_link {
 	unsigned long *addrs;
 	u64 *cookies;
 	u32 cnt;
+	u32 mods_cnt;
+	struct module **mods;
 };
 
 struct bpf_kprobe_multi_run_ctx {
@@ -2319,6 +2321,14 @@ error:
 	return err;
 }
 
+static void kprobe_multi_put_modules(struct module **mods, u32 cnt)
+{
+	u32 i;
+
+	for (i = 0; i < cnt; i++)
+		module_put(mods[i]);
+}
+
 static void free_user_syms(struct user_syms *us)
 {
 	kvfree(us->syms);
@@ -2331,6 +2341,7 @@ static void bpf_kprobe_multi_link_releas
 
 	kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
 	unregister_fprobe(&kmulti_link->fp);
+	kprobe_multi_put_modules(kmulti_link->mods, kmulti_link->mods_cnt);
 }
 
 static void bpf_kprobe_multi_link_dealloc(struct bpf_link *link)
@@ -2340,6 +2351,7 @@ static void bpf_kprobe_multi_link_deallo
 	kmulti_link = container_of(link, struct bpf_kprobe_multi_link, link);
 	kvfree(kmulti_link->addrs);
 	kvfree(kmulti_link->cookies);
+	kfree(kmulti_link->mods);
 	kfree(kmulti_link);
 }
 
@@ -2475,6 +2487,71 @@ static void symbols_swap_r(void *a, void
 	}
 }
 
+struct module_addr_args {
+	unsigned long *addrs;
+	u32 addrs_cnt;
+	struct module **mods;
+	int mods_cnt;
+	int mods_cap;
+};
+
+static int module_callback(void *data, const char *name,
+			   struct module *mod, unsigned long addr)
+{
+	struct module_addr_args *args = data;
+	struct module **mods;
+
+	/* We iterate all modules symbols and for each we:
+	 * - search for it in provided addresses array
+	 * - if found we check if we already have the module pointer stored
+	 *   (we iterate modules sequentially, so we can check just the last
+	 *   module pointer)
+	 * - take module reference and store it
+	 */
+	if (!bsearch(&addr, args->addrs, args->addrs_cnt, sizeof(addr),
+		       bpf_kprobe_multi_addrs_cmp))
+		return 0;
+
+	if (args->mods && args->mods[args->mods_cnt - 1] == mod)
+		return 0;
+
+	if (args->mods_cnt == args->mods_cap) {
+		args->mods_cap = max(16, args->mods_cap * 3 / 2);
+		mods = krealloc_array(args->mods, args->mods_cap, sizeof(*mods), GFP_KERNEL);
+		if (!mods)
+			return -ENOMEM;
+		args->mods = mods;
+	}
+
+	if (!try_module_get(mod))
+		return -EINVAL;
+
+	args->mods[args->mods_cnt] = mod;
+	args->mods_cnt++;
+	return 0;
+}
+
+static int get_modules_for_addrs(struct module ***mods, unsigned long *addrs, u32 addrs_cnt)
+{
+	struct module_addr_args args = {
+		.addrs     = addrs,
+		.addrs_cnt = addrs_cnt,
+	};
+	int err;
+
+	/* We return either err < 0 in case of error, ... */
+	err = module_kallsyms_on_each_symbol(module_callback, &args);
+	if (err) {
+		kprobe_multi_put_modules(args.mods, args.mods_cnt);
+		kfree(args.mods);
+		return err;
+	}
+
+	/* or number of modules found if everything is ok. */
+	*mods = args.mods;
+	return args.mods_cnt;
+}
+
 int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
 {
 	struct bpf_kprobe_multi_link *link = NULL;
@@ -2585,10 +2662,25 @@ int bpf_kprobe_multi_link_attach(const u
 		       bpf_kprobe_multi_cookie_cmp,
 		       bpf_kprobe_multi_cookie_swap,
 		       link);
+	} else {
+		/*
+		 * We need to sort addrs array even if there are no cookies
+		 * provided, to allow bsearch in get_modules_for_addrs.
+		 */
+		sort(addrs, cnt, sizeof(*addrs),
+		       bpf_kprobe_multi_addrs_cmp, NULL);
+	}
+
+	err = get_modules_for_addrs(&link->mods, addrs, cnt);
+	if (err < 0) {
+		bpf_link_cleanup(&link_primer);
+		return err;
 	}
+	link->mods_cnt = err;
 
 	err = register_fprobe_ips(&link->fp, addrs, cnt);
 	if (err) {
+		kprobe_multi_put_modules(link->mods, link->mods_cnt);
 		bpf_link_cleanup(&link_primer);
 		return err;
 	}



  parent reply	other threads:[~2022-12-19 19:26 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-19 19:22 [PATCH 6.0 00/28] 6.0.15-rc1 review Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 01/28] PCI: mt7621: Add sentinel to quirks table Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 02/28] kallsyms: Make module_kallsyms_on_each_symbol generally available Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 03/28] ftrace: Add support to resolve module symbols in ftrace_lookup_symbols Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 04/28] bpf: Rename __bpf_kprobe_multi_cookie_cmp to bpf_kprobe_multi_addrs_cmp Greg Kroah-Hartman
2022-12-19 19:22 ` Greg Kroah-Hartman [this message]
2022-12-19 19:22 ` [PATCH 6.0 06/28] selftests/bpf: Add load_kallsyms_refresh function Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 07/28] selftests/bpf: Add bpf_testmod_fentry_* functions Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 08/28] selftests/bpf: Add kprobe_multi check to module attach test Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 09/28] selftests/bpf: Add kprobe_multi kmod attach api tests Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 10/28] udf: Discard preallocation before extending file with a hole Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 11/28] udf: Fix preallocation discarding at indirect extent boundary Greg Kroah-Hartman
2022-12-19 19:22 ` [PATCH 6.0 12/28] udf: Do not bother looking for prealloc extents if i_lenExtents matches i_size Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 13/28] udf: Fix extending file within last block Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 14/28] usb: gadget: uvc: Prevent buffer overflow in setup handler Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 15/28] USB: serial: option: add Quectel EM05-G modem Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 16/28] USB: serial: cp210x: add Kamstrup RF sniffer PIDs Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 17/28] USB: serial: f81232: fix division by zero on line-speed change Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 18/28] USB: serial: f81534: " Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 19/28] ALSA: hda/realtek: fix mute/micmute LEDs for a HP ProBook Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 20/28] xhci: Apply XHCI_RESET_TO_DEFAULT quirk to ADL-N Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 21/28] igb: Initialize mailbox message for VF reset Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 22/28] usb: typec: ucsi: Resume in separate work Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 23/28] usb: dwc3: pci: Update PCIe device ID for USB3 controller on CPU sub-system for Raptor Lake Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 24/28] KEYS: encrypted: fix key instantiation with user-provided data Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 25/28] usb: ulpi: defer ulpi_register on ulpi_read_id timeout Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 26/28] Bluetooth: L2CAP: Fix u8 overflow Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 27/28] selftests: net: Use "grep -E" instead of "egrep" Greg Kroah-Hartman
2022-12-19 19:23 ` [PATCH 6.0 28/28] net: loopback: use NET_NAME_PREDICTABLE for name_assign_type Greg Kroah-Hartman
2022-12-19 23:55 ` [PATCH 6.0 00/28] 6.0.15-rc1 review Florian Fainelli
2022-12-20  0:16 ` Shuah Khan
2022-12-20  4:44 ` Bagas Sanjaya
2022-12-20  6:41 ` Naresh Kamboju
2022-12-20 11:21 ` Sudip Mukherjee (Codethink)
2022-12-20 14:49 ` Guenter Roeck
2022-12-20 15:33   ` Guenter Roeck
2022-12-21  1:07     ` Guenter Roeck
2022-12-20 17:44 ` Ron Economos
2022-12-20 17:50 ` Jon Hunter
2022-12-21  1:16 ` Slade Watkins
2022-12-21 16:04 ` Justin Forbes

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=20221219182944.420203135@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=jolsa@kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=stable@vger.kernel.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox