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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).