diff options
author | Luca Boccassi <bluca@debian.org> | 2024-05-28 19:59:24 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2024-05-29 08:29:47 +0200 |
commit | 8e495bf0b7c2c6a86ce2af9f49f888c281203eb6 (patch) | |
tree | 0f139c6bf14e88e23b385e479bd7fc2897afad19 /src | |
parent | test-network: update comment about status of kernel regression (diff) | |
download | systemd-8e495bf0b7c2c6a86ce2af9f49f888c281203eb6.tar.xz systemd-8e495bf0b7c2c6a86ce2af9f49f888c281203eb6.zip |
bpf: add helper to translate kernel error codes from libbpf
libbpf returns error codes from the kernel unmodified, and we don't understand
them so non-fatal ones are handled as hard errors.
Add a translation helper, and start by translating 524 to EOPNOTSUPP, which is
returned when nsresourced tries to use LSM BPF hooks that are not
implemented on a given arch (in this case, arm64 is misssing trampolines).
Fixes https://github.com/systemd/systemd/issues/32170
Diffstat (limited to '')
-rw-r--r-- | src/core/bpf-restrict-fs.c | 4 | ||||
-rw-r--r-- | src/core/bpf-restrict-ifaces.c | 4 | ||||
-rw-r--r-- | src/core/bpf-socket-bind.c | 4 | ||||
-rw-r--r-- | src/nsresourced/userns-restrict.c | 4 | ||||
-rw-r--r-- | src/shared/bpf-dlopen.c | 17 | ||||
-rw-r--r-- | src/shared/bpf-dlopen.h | 6 | ||||
-rw-r--r-- | src/shared/bpf-link.c | 4 |
7 files changed, 32 insertions, 11 deletions
diff --git a/src/core/bpf-restrict-fs.c b/src/core/bpf-restrict-fs.c index 9300c19390..d36bfb5d5e 100644 --- a/src/core/bpf-restrict-fs.c +++ b/src/core/bpf-restrict-fs.c @@ -51,7 +51,7 @@ static bool bpf_can_link_lsm_program(struct bpf_program *prog) { /* If bpf_program__attach_lsm fails the resulting value stores libbpf error code instead of memory * pointer. That is the case when the helper is called on architectures where BPF trampoline (hence * BPF_LSM_MAC attach type) is not supported. */ - return sym_libbpf_get_error(link) == 0; + return bpf_get_error_translated(link) == 0; } static int prepare_restrict_fs_bpf(struct restrict_fs_bpf **ret_obj) { @@ -139,7 +139,7 @@ int bpf_restrict_fs_setup(Manager *m) { return r; link = sym_bpf_program__attach_lsm(obj->progs.restrict_filesystems); - r = sym_libbpf_get_error(link); + r = bpf_get_error_translated(link); if (r != 0) return log_error_errno(r, "bpf-restrict-fs: Failed to link '%s' LSM BPF program: %m", sym_bpf_program__name(obj->progs.restrict_filesystems)); diff --git a/src/core/bpf-restrict-ifaces.c b/src/core/bpf-restrict-ifaces.c index ddecd3f866..64d8d1a7e5 100644 --- a/src/core/bpf-restrict-ifaces.c +++ b/src/core/bpf-restrict-ifaces.c @@ -133,12 +133,12 @@ static int restrict_ifaces_install_impl(Unit *u) { return -errno; ingress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_i, cgroup_fd); - r = sym_libbpf_get_error(ingress_link); + r = bpf_get_error_translated(ingress_link); if (r != 0) return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create ingress cgroup link: %m"); egress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_e, cgroup_fd); - r = sym_libbpf_get_error(egress_link); + r = bpf_get_error_translated(egress_link); if (r != 0) return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create egress cgroup link: %m"); diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index 3008d8249c..2a1a0278d5 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -201,13 +201,13 @@ static int socket_bind_install_impl(Unit *u) { return log_unit_error_errno(u, errno, "bpf-socket-bind: Failed to open cgroup %s for reading: %m", cgroup_path); ipv4 = sym_bpf_program__attach_cgroup(obj->progs.sd_bind4, cgroup_fd); - r = sym_libbpf_get_error(ipv4); + r = bpf_get_error_translated(ipv4); if (r != 0) return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m", sym_bpf_program__name(obj->progs.sd_bind4)); ipv6 = sym_bpf_program__attach_cgroup(obj->progs.sd_bind6, cgroup_fd); - r = sym_libbpf_get_error(ipv6); + r = bpf_get_error_translated(ipv6); if (r != 0) return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to link '%s' cgroup-bpf program: %m", sym_bpf_program__name(obj->progs.sd_bind6)); diff --git a/src/nsresourced/userns-restrict.c b/src/nsresourced/userns-restrict.c index 241a655e62..be33f49f55 100644 --- a/src/nsresourced/userns-restrict.c +++ b/src/nsresourced/userns-restrict.c @@ -131,7 +131,7 @@ int userns_restrict_install( return log_oom(); link = sym_bpf_link__open(fn); - r = sym_libbpf_get_error(link); + r = bpf_get_error_translated(link); if (r < 0) { if (r != -ENOENT) return log_error_errno(r, "Unable to open pinned program link: %m"); @@ -144,7 +144,7 @@ int userns_restrict_install( if (!link) { link = sym_bpf_program__attach(*ps->prog); - r = sym_libbpf_get_error(link); + r = bpf_get_error_translated(link); if (r < 0) return log_error_errno(r, "Failed to attach LSM BPF program: %m"); diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c index d4ae24053e..50491fc6aa 100644 --- a/src/shared/bpf-dlopen.c +++ b/src/shared/bpf-dlopen.c @@ -181,6 +181,23 @@ int dlopen_bpf(void) { return r; } +int bpf_get_error_translated(const void *ptr) { + int r; + + r = sym_libbpf_get_error(ptr); + + switch (r) { + case -524: + /* Workaround for kernel bug, BPF returns an internal error instead of translating it, until + * it is fixed: + * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/errno.h?h=v6.9&id=a38297e3fb012ddfa7ce0321a7e5a8daeb1872b6#n27 + */ + return -EOPNOTSUPP; + default: + return r; + } +} + #else int dlopen_bpf(void) { diff --git a/src/shared/bpf-dlopen.h b/src/shared/bpf-dlopen.h index 6deca829f1..df12d08e50 100644 --- a/src/shared/bpf-dlopen.h +++ b/src/shared/bpf-dlopen.h @@ -35,13 +35,17 @@ DLSYM_PROTOTYPE(bpf_program__attach); DLSYM_PROTOTYPE(bpf_program__attach_cgroup); DLSYM_PROTOTYPE(bpf_program__attach_lsm); DLSYM_PROTOTYPE(bpf_program__name); -DLSYM_PROTOTYPE(libbpf_get_error); DLSYM_PROTOTYPE(libbpf_set_print); DLSYM_PROTOTYPE(ring_buffer__epoll_fd); DLSYM_PROTOTYPE(ring_buffer__free); DLSYM_PROTOTYPE(ring_buffer__new); DLSYM_PROTOTYPE(ring_buffer__poll); +/* libbpf sometimes returns error codes that make sense only in the kernel, like 524 for EOPNOTSUPP. Use + * this helper instead of libbpf_get_error() to ensure some of the known ones are translated into errnos + * we understand. */ +int bpf_get_error_translated(const void *ptr); + #endif int dlopen_bpf(void); diff --git a/src/shared/bpf-link.c b/src/shared/bpf-link.c index fea49b2ecb..77f6a4ee9a 100644 --- a/src/shared/bpf-link.c +++ b/src/shared/bpf-link.c @@ -16,7 +16,7 @@ bool bpf_can_link_program(struct bpf_program *prog) { link = sym_bpf_program__attach_cgroup(prog, /*cgroup_fd=*/-1); /* EBADF indicates that bpf_link is supported by kernel. */ - return sym_libbpf_get_error(link) == -EBADF; + return bpf_get_error_translated(link) == -EBADF; } int bpf_serialize_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *link) { @@ -25,7 +25,7 @@ int bpf_serialize_link(FILE *f, FDSet *fds, const char *key, struct bpf_link *li if (!link) return -ENOENT; - if (sym_libbpf_get_error(link) != 0) + if (bpf_get_error_translated(link) != 0) return -EINVAL; return serialize_fd(f, fds, key, sym_bpf_link__fd(link)); |