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
This commit is contained in:
Luca Boccassi
2024-05-29 08:29:47 +02:00
committed by Zbigniew Jędrzejewski-Szmek
parent 45af01d311
commit 8e495bf0b7
7 changed files with 32 additions and 11 deletions
+2 -2
View File
@@ -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));
+2 -2
View File
@@ -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");
+2 -2
View File
@@ -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));
+2 -2
View File
@@ -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");
+17
View File
@@ -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) {
+5 -1
View File
@@ -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);
+2 -2
View File
@@ -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));