Signed-off-by: zhang-mingyi66 <zhangmingyi5@huawei.com> (cherry picked from commit c93fa88cb0c11cd67c85e48654dc403447bc9df0)
150 lines
5.4 KiB
Diff
150 lines
5.4 KiB
Diff
From f6f24022d3054d2855612e642f8fe9f1148b4275 Mon Sep 17 00:00:00 2001
|
|
From: Andrii Nakryiko <andrii@kernel.org>
|
|
Date: Tue, 27 Aug 2024 13:37:21 -0700
|
|
Subject: [PATCH] libbpf: Fix bpf_object__open_skeleton()'s mishandling of
|
|
options
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
We do an ugly copying of options in bpf_object__open_skeleton() just to
|
|
be able to set object name from skeleton's recorded name (while still
|
|
allowing user to override it through opts->object_name).
|
|
|
|
This is not just ugly, but it also is broken due to memcpy() that
|
|
doesn't take into account potential skel_opts' and user-provided opts'
|
|
sizes differences due to backward and forward compatibility. This leads
|
|
to copying over extra bytes and then failing to validate options
|
|
properly. It could, technically, lead also to SIGSEGV, if we are unlucky.
|
|
|
|
So just get rid of that memory copy completely and instead pass
|
|
default object name into bpf_object_open() directly, simplifying all
|
|
this significantly. The rule now is that obj_name should be non-NULL for
|
|
bpf_object_open() when called with in-memory buffer, so validate that
|
|
explicitly as well.
|
|
|
|
We adopt bpf_object__open_mem() to this as well and generate default
|
|
name (based on buffer memory address and size) outside of bpf_object_open().
|
|
|
|
Fixes: d66562fba1ce ("libbpf: Add BPF object skeleton support")
|
|
Reported-by: Daniel Müller <deso@posteo.net>
|
|
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
|
|
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
Reviewed-by: Daniel Müller <deso@posteo.net>
|
|
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
|
|
Link: https://lore.kernel.org/bpf/20240827203721.1145494-1-andrii@kernel.org
|
|
---
|
|
src/libbpf.c | 52 +++++++++++++++++++---------------------------------
|
|
1 file changed, 19 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/src/libbpf.c b/src/libbpf.c
|
|
index e55353887..d3a542649 100644
|
|
--- a/src/libbpf.c
|
|
+++ b/src/libbpf.c
|
|
@@ -7905,16 +7905,19 @@ static int bpf_object_init_progs(struct bpf_object *obj, const struct bpf_object
|
|
}
|
|
|
|
static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf, size_t obj_buf_sz,
|
|
+ const char *obj_name,
|
|
const struct bpf_object_open_opts *opts)
|
|
{
|
|
- const char *obj_name, *kconfig, *btf_tmp_path;
|
|
+ const char *kconfig, *btf_tmp_path;
|
|
struct bpf_object *obj;
|
|
- char tmp_name[64];
|
|
int err;
|
|
char *log_buf;
|
|
size_t log_size;
|
|
__u32 log_level;
|
|
|
|
+ if (obj_buf && !obj_name)
|
|
+ return ERR_PTR(-EINVAL);
|
|
+
|
|
if (elf_version(EV_CURRENT) == EV_NONE) {
|
|
pr_warn("failed to init libelf for %s\n",
|
|
path ? : "(mem buf)");
|
|
@@ -7924,16 +7927,12 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
|
|
if (!OPTS_VALID(opts, bpf_object_open_opts))
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- obj_name = OPTS_GET(opts, object_name, NULL);
|
|
+ obj_name = OPTS_GET(opts, object_name, NULL) ?: obj_name;
|
|
if (obj_buf) {
|
|
- if (!obj_name) {
|
|
- snprintf(tmp_name, sizeof(tmp_name), "%lx-%lx",
|
|
- (unsigned long)obj_buf,
|
|
- (unsigned long)obj_buf_sz);
|
|
- obj_name = tmp_name;
|
|
- }
|
|
path = obj_name;
|
|
pr_debug("loading object '%s' from buffer\n", obj_name);
|
|
+ } else {
|
|
+ pr_debug("loading object from %s\n", path);
|
|
}
|
|
|
|
log_buf = OPTS_GET(opts, kernel_log_buf, NULL);
|
|
@@ -8017,9 +8016,7 @@ bpf_object__open_file(const char *path, const struct bpf_object_open_opts *opts)
|
|
if (!path)
|
|
return libbpf_err_ptr(-EINVAL);
|
|
|
|
- pr_debug("loading %s\n", path);
|
|
-
|
|
- return libbpf_ptr(bpf_object_open(path, NULL, 0, opts));
|
|
+ return libbpf_ptr(bpf_object_open(path, NULL, 0, NULL, opts));
|
|
}
|
|
|
|
struct bpf_object *bpf_object__open(const char *path)
|
|
@@ -8031,10 +8028,15 @@ struct bpf_object *
|
|
bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz,
|
|
const struct bpf_object_open_opts *opts)
|
|
{
|
|
+ char tmp_name[64];
|
|
+
|
|
if (!obj_buf || obj_buf_sz == 0)
|
|
return libbpf_err_ptr(-EINVAL);
|
|
|
|
- return libbpf_ptr(bpf_object_open(NULL, obj_buf, obj_buf_sz, opts));
|
|
+ /* create a (quite useless) default "name" for this memory buffer object */
|
|
+ snprintf(tmp_name, sizeof(tmp_name), "%lx-%zx", (unsigned long)obj_buf, obj_buf_sz);
|
|
+
|
|
+ return libbpf_ptr(bpf_object_open(NULL, obj_buf, obj_buf_sz, tmp_name, opts));
|
|
}
|
|
|
|
static int bpf_object_unload(struct bpf_object *obj)
|
|
@@ -13761,29 +13763,13 @@ static int populate_skeleton_progs(const struct bpf_object *obj,
|
|
int bpf_object__open_skeleton(struct bpf_object_skeleton *s,
|
|
const struct bpf_object_open_opts *opts)
|
|
{
|
|
- DECLARE_LIBBPF_OPTS(bpf_object_open_opts, skel_opts,
|
|
- .object_name = s->name,
|
|
- );
|
|
struct bpf_object *obj;
|
|
int err;
|
|
|
|
- /* Attempt to preserve opts->object_name, unless overriden by user
|
|
- * explicitly. Overwriting object name for skeletons is discouraged,
|
|
- * as it breaks global data maps, because they contain object name
|
|
- * prefix as their own map name prefix. When skeleton is generated,
|
|
- * bpftool is making an assumption that this name will stay the same.
|
|
- */
|
|
- if (opts) {
|
|
- memcpy(&skel_opts, opts, sizeof(*opts));
|
|
- if (!opts->object_name)
|
|
- skel_opts.object_name = s->name;
|
|
- }
|
|
-
|
|
- obj = bpf_object__open_mem(s->data, s->data_sz, &skel_opts);
|
|
- err = libbpf_get_error(obj);
|
|
- if (err) {
|
|
- pr_warn("failed to initialize skeleton BPF object '%s': %d\n",
|
|
- s->name, err);
|
|
+ obj = bpf_object_open(NULL, s->data, s->data_sz, s->name, opts);
|
|
+ if (IS_ERR(obj)) {
|
|
+ err = PTR_ERR(obj);
|
|
+ pr_warn("failed to initialize skeleton BPF object '%s': %d\n", s->name, err);
|
|
return libbpf_err(err);
|
|
}
|
|
|
|
|
|
|