linux/tools/lib/bpf
Quentin Monnet 6a5d02ae6f libbpf: Fix segfault due to libelf functions not setting errno
[ Upstream commit e10500b69c ]

Libelf functions do not set errno on failure. Instead, it relies on its
internal _elf_errno value, that can be retrieved via elf_errno (or the
corresponding message via elf_errmsg()). From "man libelf":

    If a libelf function encounters an error it will set an internal
    error code that can be retrieved with elf_errno. Each thread
    maintains its own separate error code. The meaning of each error
    code can be determined with elf_errmsg, which returns a string
    describing the error.

As a consequence, libbpf should not return -errno when a function from
libelf fails, because an empty value will not be interpreted as an error
and won't prevent the program to stop. This is visible in
bpf_linker__add_file(), for example, where we call a succession of
functions that rely on libelf:

    err = err ?: linker_load_obj_file(linker, filename, opts, &obj);
    err = err ?: linker_append_sec_data(linker, &obj);
    err = err ?: linker_append_elf_syms(linker, &obj);
    err = err ?: linker_append_elf_relos(linker, &obj);
    err = err ?: linker_append_btf(linker, &obj);
    err = err ?: linker_append_btf_ext(linker, &obj);

If the object file that we try to process is not, in fact, a correct
object file, linker_load_obj_file() may fail with errno not being set,
and return 0. In this case we attempt to run linker_append_elf_sysms()
and may segfault.

This can happen (and was discovered) with bpftool:

    $ bpftool gen object output.o sample_ret0.bpf.c
    libbpf: failed to get ELF header for sample_ret0.bpf.c: invalid `Elf' handle
    zsh: segmentation fault (core dumped)  bpftool gen object output.o sample_ret0.bpf.c

Fix the issue by returning a non-null error code (-EINVAL) when libelf
functions fail.

Fixes: faf6ed321c ("libbpf: Add BPF static linker APIs")
Signed-off-by: Quentin Monnet <qmo@kernel.org>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20241205135942.65262-1-qmo@kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2025-03-13 12:50:00 +01:00
..
.gitignore libbpf: Stop using feature-detection Makefiles 2021-02-04 01:22:00 +01:00
bpf.c libbpf: Fix lookup_and_delete_elem_flags error reporting 2021-11-18 19:17:09 +01:00
bpf.h libbpf: Avoid enum forward-declarations in public API in C++ mode 2022-12-31 13:14:43 +01:00
bpf_core_read.h bpf: Avoid uninitialized value in BPF_CORE_READ_BITFIELD 2024-07-18 13:07:29 +02:00
bpf_endian.h libbpf: Make bpf_endian co-exist with vmlinux.h 2020-07-01 09:06:12 +02:00
bpf_gen_internal.h libbpf: Cleanup temp FDs when intermediate sys_bpf fails. 2021-05-19 00:40:44 +02:00
bpf_helpers.h libbpf: fix offsetof() and container_of() to work with CO-RE 2023-07-23 13:46:49 +02:00
bpf_prog_linfo.c libbpf: Streamline error reporting for high-level APIs 2021-05-25 17:32:35 -07:00
bpf_tracing.h libbpf: Fail compilation if target arch is missing 2021-06-16 20:15:30 -07:00
btf.c libbpf: Fix btf__align_of() by taking into account field offsets 2023-03-10 09:39:06 +01:00
btf.h libbpf: Fix potential misaligned memory access in btf_ext__new() 2022-01-27 11:03:16 +01:00
btf_dump.c libbpf: Fix no-args func prototype BTF dumping syntax 2024-08-19 05:45:23 +02:00
Build libbpf: Split CO-RE logic into relo_core.c. 2021-07-26 12:29:14 -07:00
gen_loader.c libbpf: fix an snprintf() overflow check 2022-08-17 14:23:32 +02:00
hashmap.c libbpf: Centralize poisoning and poison reallocarray() 2020-08-18 18:38:25 -07:00
hashmap.h libbpf, hashmap: Fix undefined behavior in hash_bits 2020-11-02 23:33:51 +01:00
libbpf.c libbpf: fix sym_is_subprog() logic for weak global subprogs 2024-12-14 19:50:54 +01:00
libbpf.h libbpf: Add uprobe ref counter offset support for USDT semaphores 2021-08-17 00:45:08 +02:00
libbpf.map libbpf: Add bpf_cookie to perf_event, kprobe, uprobe, and tp attach APIs 2021-08-17 00:45:08 +02:00
libbpf.pc.template libbpf: Add zlib as a dependency in pkg-config template 2019-12-16 14:55:29 -08:00
libbpf_common.h libbpf: Implement generalized .BTF.ext func/line info adjustment 2020-09-03 17:14:40 -07:00
libbpf_errno.c libbpf: Streamline error reporting for high-level APIs 2021-05-25 17:32:35 -07:00
libbpf_internal.h libbpf: Add bpf_cookie support to bpf_link_create() API 2021-08-17 00:45:08 +02:00
libbpf_legacy.h libbpf: Streamline error reporting for low-level APIs 2021-05-25 17:32:35 -07:00
libbpf_probes.c libbpf: Use page size as max_entries when probing ring buffer map 2022-12-19 12:36:41 +01:00
linker.c libbpf: Fix segfault due to libelf functions not setting errno 2025-03-13 12:50:00 +01:00
Makefile libbpf: Fix build issue with llvm-readelf 2022-04-13 20:59:03 +02:00
netlink.c libbpf: Fix memleak in libbpf_netlink_recv() 2022-04-08 14:23:31 +02:00
nlattr.c libbpf: Fix alen calculation in libbpf_nla_dump_errormsg() 2023-03-10 09:39:16 +01:00
nlattr.h libbpf: Switch to void * casting in netlink helpers 2021-06-22 17:04:02 +02:00
relo_core.c libbpf: Split CO-RE logic into relo_core.c. 2021-07-26 12:29:14 -07:00
relo_core.h libbpf: Split CO-RE logic into relo_core.c. 2021-07-26 12:29:14 -07:00
ringbuf.c libbpf: Handle size overflow for ringbuf mmap 2022-12-08 11:28:39 +01:00
skel_internal.h libbpf: Fix skel_internal.h to set errno on loader retval < 0 2021-11-18 19:16:27 +01:00
str_error.c libbpf: Poison kernel-only integer types 2020-01-10 10:38:00 -08:00
str_error.h libbpf: relicense libbpf as LGPL-2.1 OR BSD-2-Clause 2018-10-08 10:09:48 +02:00
strset.c libbpf: Fix memory leak in strset 2021-10-01 22:54:38 +02:00
strset.h libbpf: Extract internal set-of-strings datastructure APIs 2021-03-18 16:14:22 -07:00
xsk.c selftests/xsk: Avoid use-after-free on ctx 2022-10-26 12:34:41 +02:00
xsk.h libbpf: xsk: Move barriers from libbpf_util.h to xsk.h 2021-03-10 13:45:16 -08:00