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:
committed by
Zbigniew Jędrzejewski-Szmek
parent
45af01d311
commit
8e495bf0b7
@@ -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));
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user