Skip to content

Commit c634d6f

Browse files
anakryikoborkmann
authored andcommitted
libbpf: Fix bpf_object__open_skeleton()'s mishandling of options
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: d66562f ("libbpf: Add BPF object skeleton support") Reported-by: Daniel Müller <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Daniel Müller <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 6db59c4 commit c634d6f

File tree

1 file changed

+19
-33
lines changed

1 file changed

+19
-33
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7905,16 +7905,19 @@ static int bpf_object_init_progs(struct bpf_object *obj, const struct bpf_object
79057905
}
79067906

79077907
static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf, size_t obj_buf_sz,
7908+
const char *obj_name,
79087909
const struct bpf_object_open_opts *opts)
79097910
{
7910-
const char *obj_name, *kconfig, *btf_tmp_path, *token_path;
7911+
const char *kconfig, *btf_tmp_path, *token_path;
79117912
struct bpf_object *obj;
7912-
char tmp_name[64];
79137913
int err;
79147914
char *log_buf;
79157915
size_t log_size;
79167916
__u32 log_level;
79177917

7918+
if (obj_buf && !obj_name)
7919+
return ERR_PTR(-EINVAL);
7920+
79187921
if (elf_version(EV_CURRENT) == EV_NONE) {
79197922
pr_warn("failed to init libelf for %s\n",
79207923
path ? : "(mem buf)");
@@ -7924,16 +7927,12 @@ static struct bpf_object *bpf_object_open(const char *path, const void *obj_buf,
79247927
if (!OPTS_VALID(opts, bpf_object_open_opts))
79257928
return ERR_PTR(-EINVAL);
79267929

7927-
obj_name = OPTS_GET(opts, object_name, NULL);
7930+
obj_name = OPTS_GET(opts, object_name, NULL) ?: obj_name;
79287931
if (obj_buf) {
7929-
if (!obj_name) {
7930-
snprintf(tmp_name, sizeof(tmp_name), "%lx-%lx",
7931-
(unsigned long)obj_buf,
7932-
(unsigned long)obj_buf_sz);
7933-
obj_name = tmp_name;
7934-
}
79357932
path = obj_name;
79367933
pr_debug("loading object '%s' from buffer\n", obj_name);
7934+
} else {
7935+
pr_debug("loading object from %s\n", path);
79377936
}
79387937

79397938
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)
80178016
if (!path)
80188017
return libbpf_err_ptr(-EINVAL);
80198018

8020-
pr_debug("loading %s\n", path);
8021-
8022-
return libbpf_ptr(bpf_object_open(path, NULL, 0, opts));
8019+
return libbpf_ptr(bpf_object_open(path, NULL, 0, NULL, opts));
80238020
}
80248021

80258022
struct bpf_object *bpf_object__open(const char *path)
@@ -8031,10 +8028,15 @@ struct bpf_object *
80318028
bpf_object__open_mem(const void *obj_buf, size_t obj_buf_sz,
80328029
const struct bpf_object_open_opts *opts)
80338030
{
8031+
char tmp_name[64];
8032+
80348033
if (!obj_buf || obj_buf_sz == 0)
80358034
return libbpf_err_ptr(-EINVAL);
80368035

8037-
return libbpf_ptr(bpf_object_open(NULL, obj_buf, obj_buf_sz, opts));
8036+
/* create a (quite useless) default "name" for this memory buffer object */
8037+
snprintf(tmp_name, sizeof(tmp_name), "%lx-%zx", (unsigned long)obj_buf, obj_buf_sz);
8038+
8039+
return libbpf_ptr(bpf_object_open(NULL, obj_buf, obj_buf_sz, tmp_name, opts));
80388040
}
80398041

80408042
static int bpf_object_unload(struct bpf_object *obj)
@@ -13761,29 +13763,13 @@ static int populate_skeleton_progs(const struct bpf_object *obj,
1376113763
int bpf_object__open_skeleton(struct bpf_object_skeleton *s,
1376213764
const struct bpf_object_open_opts *opts)
1376313765
{
13764-
DECLARE_LIBBPF_OPTS(bpf_object_open_opts, skel_opts,
13765-
.object_name = s->name,
13766-
);
1376713766
struct bpf_object *obj;
1376813767
int err;
1376913768

13770-
/* Attempt to preserve opts->object_name, unless overriden by user
13771-
* explicitly. Overwriting object name for skeletons is discouraged,
13772-
* as it breaks global data maps, because they contain object name
13773-
* prefix as their own map name prefix. When skeleton is generated,
13774-
* bpftool is making an assumption that this name will stay the same.
13775-
*/
13776-
if (opts) {
13777-
memcpy(&skel_opts, opts, sizeof(*opts));
13778-
if (!opts->object_name)
13779-
skel_opts.object_name = s->name;
13780-
}
13781-
13782-
obj = bpf_object__open_mem(s->data, s->data_sz, &skel_opts);
13783-
err = libbpf_get_error(obj);
13784-
if (err) {
13785-
pr_warn("failed to initialize skeleton BPF object '%s': %d\n",
13786-
s->name, err);
13769+
obj = bpf_object_open(NULL, s->data, s->data_sz, s->name, opts);
13770+
if (IS_ERR(obj)) {
13771+
err = PTR_ERR(obj);
13772+
pr_warn("failed to initialize skeleton BPF object '%s': %d\n", s->name, err);
1378713773
return libbpf_err(err);
1378813774
}
1378913775

0 commit comments

Comments
 (0)