All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexei Starovoitov <alexei.starovoitov@gmail.com>
To: davem@davemloft.net
Cc: daniel@iogearbox.net, andrii@kernel.org,
	john.fastabend@gmail.com, lmb@cloudflare.com,
	mcroce@microsoft.com, bpf@vger.kernel.org, kernel-team@fb.com
Subject: [PATCH RFC bpf-next 04/10] bpf: Add bpf_core_add_cands() and wire it into bpf_core_apply_relo_insn().
Date: Fri, 17 Sep 2021 14:57:15 -0700	[thread overview]
Message-ID: <20210917215721.43491-5-alexei.starovoitov@gmail.com> (raw)
In-Reply-To: <20210917215721.43491-1-alexei.starovoitov@gmail.com>

From: Alexei Starovoitov <ast@kernel.org>

Given BPF program's BTF perform a linear search through kernel BTFs for
a possible candidate.
Then wire the result into bpf_core_apply_relo_insn().

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 kernel/bpf/btf.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 147 insertions(+), 2 deletions(-)

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 9bb1247346ce..e04b5e669d12 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -25,6 +25,7 @@
 #include <linux/kobject.h>
 #include <linux/sysfs.h>
 #include <net/sock.h>
+#include "../tools/lib/bpf/relo_core.h"
 
 /* BTF (BPF Type Format) is the meta data format which describes
  * the data types of BPF program/map.  Hence, it basically focus
@@ -6370,15 +6371,159 @@ size_t bpf_core_essential_name_len(const char *name)
 	return n;
 }
 
+static void bpf_core_free_cands(struct bpf_core_cand_list *cands)
+{
+        kfree(cands->cands);
+        kfree(cands);
+}
+
+static int bpf_core_add_cands(struct bpf_core_cand *local_cand,
+                              size_t local_essent_len,
+                              const struct btf *targ_btf,
+                              int targ_start_id,
+                              struct bpf_core_cand_list *cands)
+{
+	struct bpf_core_cand *new_cands, *cand;
+	const struct btf_type *t;
+	const char *targ_name;
+	size_t targ_essent_len;
+	int n, i;
+
+	n = btf_nr_types(targ_btf);
+	for (i = targ_start_id; i < n; i++) {
+		t = btf__type_by_id(targ_btf, i);
+		if (btf_kind(t) != btf_kind(local_cand->t))
+			continue;
+
+		targ_name = btf_name_by_offset(targ_btf, t->name_off);
+		if (str_is_empty(targ_name))
+			continue;
+
+		targ_essent_len = bpf_core_essential_name_len(targ_name);
+		if (targ_essent_len != local_essent_len)
+			continue;
+
+		if (strncmp(local_cand->name, targ_name, local_essent_len) != 0)
+			continue;
+
+/*		printk("CO-RE relocating [%d] %s %s: found target candidate [%d] %s %s\n",
+		       local_cand->id, btf_type_str(local_cand->t),
+		       local_cand->name, i, btf_type_str(t), targ_name);*/
+		new_cands = krealloc(cands->cands,
+				     (cands->len + 1) * sizeof(*cands->cands), GFP_KERNEL);
+		if (!new_cands)
+			return -ENOMEM;
+
+		cand = &new_cands[cands->len];
+		cand->btf = targ_btf;
+		cand->t = t;
+		cand->name = targ_name;
+		cand->id = i;
+
+		cands->cands = new_cands;
+		cands->len++;
+	}
+	return 0;
+}
+
+static struct bpf_core_cand_list *
+bpf_core_find_cands(const struct btf *local_btf, u32 local_type_id)
+{
+	struct bpf_core_cand local_cand = {};
+	struct bpf_core_cand_list *cands;
+	const struct btf *main_btf;
+	size_t local_essent_len;
+	struct btf *mod_btf;
+	int err;
+	int id;
+
+	local_cand.btf = local_btf;
+	local_cand.t = btf__type_by_id(local_btf, local_type_id);
+	if (!local_cand.t)
+		return ERR_PTR(-EINVAL);
+
+	local_cand.name = btf_name_by_offset(local_btf, local_cand.t->name_off);
+	if (str_is_empty(local_cand.name))
+		return ERR_PTR(-EINVAL);
+	local_essent_len = bpf_core_essential_name_len(local_cand.name);
+
+	cands = kcalloc(1, sizeof(*cands), GFP_KERNEL);
+	if (!cands)
+		return ERR_PTR(-ENOMEM);
+
+	/* Attempt to find target candidates in vmlinux BTF first */
+	main_btf = bpf_get_btf_vmlinux();
+	err = bpf_core_add_cands(&local_cand, local_essent_len, main_btf, 1, cands);
+	if (err)
+		goto err_out;
+
+	/* if vmlinux BTF has any candidate, don't got for module BTFs */
+	if (cands->len)
+		return cands;
+
+	/* If candidate is not found in vmlinux's BTF then search in module's BTFs */
+	spin_lock_bh(&btf_idr_lock);
+	idr_for_each_entry(&btf_idr, mod_btf, id) {
+		if (!btf_is_module(mod_btf))
+			continue;
+		/* linear search could be slow hence unlock/lock
+		 * the IDR to avoiding holding it for too long
+		 */
+		btf_get(mod_btf);
+		spin_unlock_bh(&btf_idr_lock);
+		err = bpf_core_add_cands(&local_cand, local_essent_len,
+					 mod_btf,
+					 btf_nr_types(main_btf),
+					 cands);
+		if (err)
+			btf_put(mod_btf);
+		goto err_out;
+		spin_lock_bh(&btf_idr_lock);
+		btf_put(mod_btf);
+	}
+	spin_unlock_bh(&btf_idr_lock);
+
+	return cands;
+err_out:
+	bpf_core_free_cands(cands);
+	return ERR_PTR(err);
+}
+
 BPF_CALL_5(bpf_core_apply_relo, int, btf_fd, struct bpf_core_relo_desc *, relo,
 	   int, relo_sz, void *, insn, int, flags)
 {
+	struct bpf_core_cand_list *cands = NULL;
+	struct bpf_core_relo core_relo = {};
 	struct btf *btf;
-	long ret;
+	int err;
 
 	if (flags)
 		return -EINVAL;
-	return -EOPNOTSUPP;
+
+	if (sizeof(*relo) != relo_sz)
+		return -EINVAL;
+	btf = btf_get_by_fd(btf_fd);
+	if (IS_ERR(btf))
+		return PTR_ERR(btf);
+	if (btf_is_kernel(btf)) {
+		btf_put(btf);
+		return -EACCES;
+	}
+	if (relo->kind != BPF_CORE_TYPE_ID_LOCAL) {
+		cands = bpf_core_find_cands(btf, relo->type_id);
+		if (IS_ERR(cands)) {
+			btf_put(btf);
+			printk("target candidate search failed for %d\n",
+			       relo->type_id);
+                        return PTR_ERR(cands);
+                }
+	}
+	core_relo.type_id = relo->type_id;
+	core_relo.access_str_off = relo->access_str_off;
+	core_relo.kind = relo->kind;
+	err = bpf_core_apply_relo_insn("prog_name", insn, 0, &core_relo, 0, btf, cands);
+	btf_put(btf);
+	return 0;
 }
 
 const struct bpf_func_proto bpf_core_apply_relo_proto = {
-- 
2.30.2


  parent reply	other threads:[~2021-09-17 21:57 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-17 21:57 [PATCH RFC bpf-next 00/10] bpf: CO-RE support in the kernel Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 01/10] bpf: Prepare relo_core.c for kernel duty Alexei Starovoitov
2021-09-21 21:25   ` Andrii Nakryiko
2021-09-28 14:45   ` Matteo Croce
2021-09-28 16:37     ` Alexei Starovoitov
2021-09-28 17:11       ` Matteo Croce
2021-09-28 20:34         ` Alexei Starovoitov
2021-09-29 12:32           ` Matteo Croce
2021-09-29 17:38             ` Matteo Croce
2021-09-29 23:00               ` Alexei Starovoitov
2021-09-29 23:49                 ` Matteo Croce
2021-10-22  0:48                   ` Matteo Croce
2021-10-22  0:51                     ` Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 02/10] bpf: Define enum bpf_core_relo_kind as uapi Alexei Starovoitov
2021-09-21 21:27   ` Andrii Nakryiko
2021-09-17 21:57 ` [PATCH RFC bpf-next 03/10] bpf: Add proto of bpf_core_apply_relo() Alexei Starovoitov
2021-09-23 11:21   ` Lorenz Bauer
2021-09-23 18:48     ` Andrii Nakryiko
2021-09-17 21:57 ` Alexei Starovoitov [this message]
2021-09-21 21:34   ` [PATCH RFC bpf-next 04/10] bpf: Add bpf_core_add_cands() and wire it into bpf_core_apply_relo_insn() Andrii Nakryiko
2021-09-27 18:04   ` Matteo Croce
2021-09-17 21:57 ` [PATCH RFC bpf-next 05/10] libbpf: Use CO-RE in the kernel in light skeleton Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 06/10] libbpf: Make gen_loader data aligned Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 07/10] libbpf: Support init of inner maps in light skeleton Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 08/10] selftests/bpf: Convert kfunc test with CO-RE to lskel Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 09/10] selftests/bpf: Improve inner_map test coverage Alexei Starovoitov
2021-09-17 21:57 ` [PATCH RFC bpf-next 10/10] selftests/bpf: Convert map_ptr_kern test to use light skeleton Alexei Starovoitov
2021-09-23 11:33 ` [PATCH RFC bpf-next 00/10] bpf: CO-RE support in the kernel Lorenz Bauer
2021-09-23 18:52   ` Andrii Nakryiko
2021-09-24 23:13   ` Alexei Starovoitov
2021-09-27 16:12     ` Lorenz Bauer
2021-09-27 16:50       ` Alexei Starovoitov
2021-09-28  8:30         ` Lorenz Bauer
2021-09-28 16:35           ` Alexei Starovoitov

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=20210917215721.43491-5-alexei.starovoitov@gmail.com \
    --to=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=john.fastabend@gmail.com \
    --cc=kernel-team@fb.com \
    --cc=lmb@cloudflare.com \
    --cc=mcroce@microsoft.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.