diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index 258d09dd45..ce3b76c512 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -543,7 +543,7 @@ int bpf_firewall_compile(Unit *u) { return supported; if (supported == BPF_FIREWALL_UNSUPPORTED) return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), - "BPF firewalling not supported on this manager, proceeding without."); + "bpf-firewall: BPF firewalling not supported, proceeding without."); if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) /* If BPF_F_ALLOW_MULTI is not supported we don't support any BPF magic on inner nodes (i.e. on slice * units), since that would mean leaf nodes couldn't do any BPF anymore at all. Under the assumption @@ -551,7 +551,7 @@ int bpf_firewall_compile(Unit *u) { * consistent with old systemd behaviour from before v238, where BPF wasn't supported in inner nodes at * all, either. */ return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), - "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units."); + "bpf-firewall: BPF_F_ALLOW_MULTI is not supported, not doing BPF firewall on slice units."); /* If BPF_F_ALLOW_MULTI flag is supported program name is also supported (both were added to v4.15 * kernel). */ @@ -582,24 +582,24 @@ int bpf_firewall_compile(Unit *u) { r = bpf_firewall_prepare_access_maps(u, ACCESS_ALLOWED, &u->ipv4_allow_map_fd, &u->ipv6_allow_map_fd, &ip_allow_any); if (r < 0) - return log_unit_error_errno(u, r, "Preparation of eBPF allow maps failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF allow maps failed: %m"); r = bpf_firewall_prepare_access_maps(u, ACCESS_DENIED, &u->ipv4_deny_map_fd, &u->ipv6_deny_map_fd, &ip_deny_any); if (r < 0) - return log_unit_error_errno(u, r, "Preparation of eBPF deny maps failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF deny maps failed: %m"); } r = bpf_firewall_prepare_accounting_maps(u, cc->ip_accounting, &u->ip_accounting_ingress_map_fd, &u->ip_accounting_egress_map_fd); if (r < 0) - return log_unit_error_errno(u, r, "Preparation of eBPF accounting maps failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Preparation of BPF accounting maps failed: %m"); r = bpf_firewall_compile_bpf(u, ingress_name, true, &u->ip_bpf_ingress, ip_allow_any, ip_deny_any); if (r < 0) - return log_unit_error_errno(u, r, "Compilation for ingress BPF program failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Compilation of ingress BPF program failed: %m"); r = bpf_firewall_compile_bpf(u, egress_name, false, &u->ip_bpf_egress, ip_allow_any, ip_deny_any); if (r < 0) - return log_unit_error_errno(u, r, "Compilation for egress BPF program failed: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Compilation of egress BPF program failed: %m"); return 0; } @@ -613,15 +613,15 @@ static int load_bpf_progs_from_fs_to_set(Unit *u, char **filter_paths, Set **set r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &prog); if (r < 0) - return log_unit_error_errno(u, r, "Can't allocate CGROUP SKB BPF program: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Allocation of SKB BPF program failed: %m"); r = bpf_program_load_from_bpf_fs(prog, *bpf_fs_path); if (r < 0) - return log_unit_error_errno(u, r, "Loading of ingress BPF program %s failed: %m", *bpf_fs_path); + return log_unit_error_errno(u, r, "bpf-firewall: Loading of ingress BPF program %s failed: %m", *bpf_fs_path); r = set_ensure_consume(set, &bpf_program_hash_ops, TAKE_PTR(prog)); if (r < 0) - return log_unit_error_errno(u, r, "Can't add program to BPF program set: %m"); + return log_oom(); } return 0; @@ -645,7 +645,8 @@ int bpf_firewall_load_custom(Unit *u) { return supported; if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF_F_ALLOW_MULTI not supported, cannot attach custom BPF programs."); r = load_bpf_progs_from_fs_to_set(u, cc->ip_filters_ingress, &u->ip_bpf_custom_ingress); if (r < 0) @@ -671,7 +672,7 @@ static int attach_custom_bpf_progs(Unit *u, const char *path, int attach_type, S SET_FOREACH_MOVE(prog, *set_installed, *set) { r = bpf_program_cgroup_attach(prog, attach_type, path, BPF_F_ALLOW_MULTI); if (r < 0) - return log_unit_error_errno(u, r, "Attaching custom egress BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, "bpf-firewall: Attaching custom egress BPF program to cgroup %s failed: %m", path); } return 0; } @@ -697,16 +698,19 @@ int bpf_firewall_install(Unit *u) { if (supported < 0) return supported; if (supported == BPF_FIREWALL_UNSUPPORTED) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF firewalling not supported on this manager, proceeding without."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF firewalling not supported, proceeding without."); if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF_F_ALLOW_MULTI not supported, not doing BPF firewall on slice units."); if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && (!set_isempty(u->ip_bpf_custom_ingress) || !set_isempty(u->ip_bpf_custom_egress))) - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "BPF_F_ALLOW_MULTI not supported on this manager, cannot attach custom BPF programs."); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-firewall: BPF_F_ALLOW_MULTI not supported, cannot attach custom BPF programs."); r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m"); + return log_unit_error_errno(u, r, "bpf-firewall: Failed to determine cgroup path: %m"); flags = supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI ? BPF_F_ALLOW_MULTI : 0; @@ -728,7 +732,8 @@ int bpf_firewall_install(Unit *u) { if (u->ip_bpf_egress) { r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags); if (r < 0) - return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, + "bpf-firewall: Attaching egress BPF program to cgroup %s failed: %m", path); /* Remember that this BPF program is installed now. */ u->ip_bpf_egress_installed = TAKE_PTR(u->ip_bpf_egress); @@ -737,7 +742,8 @@ int bpf_firewall_install(Unit *u) { if (u->ip_bpf_ingress) { r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags); if (r < 0) - return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, + "bpf-firewall: Attaching ingress BPF program to cgroup %s failed: %m", path); u->ip_bpf_ingress_installed = TAKE_PTR(u->ip_bpf_ingress); } @@ -824,11 +830,11 @@ int bpf_firewall_supported(void) { r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); if (r < 0) - return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + return log_error_errno(r, "bpf-firewall: Can't determine whether the unified hierarchy is used: %m"); if (r == 0) { bpf_firewall_unsupported_reason = log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN), - "Not running with unified cgroups, BPF firewalling is not supported."); + "bpf-firewall: Not running with unified cgroup hierarchy, BPF firewalling is not supported."); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -836,21 +842,21 @@ int bpf_firewall_supported(void) { r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, NULL, &program); if (r < 0) { bpf_firewall_unsupported_reason = - log_debug_errno(r, "Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + log_debug_errno(r, "bpf-firewall: Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } r = bpf_program_add_instructions(program, trivial, ELEMENTSOF(trivial)); if (r < 0) { bpf_firewall_unsupported_reason = - log_debug_errno(r, "Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + log_debug_errno(r, "bpf-firewall: Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } r = bpf_program_load_kernel(program, NULL, 0); if (r < 0) { bpf_firewall_unsupported_reason = - log_debug_errno(r, "Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m"); + log_debug_errno(r, "bpf-firewall: Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -874,7 +880,7 @@ int bpf_firewall_supported(void) { if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) { if (errno != EBADF) { bpf_firewall_unsupported_reason = - log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m"); + log_debug_errno(errno, "bpf-firewall: Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m"); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -882,7 +888,7 @@ int bpf_firewall_supported(void) { } else { bpf_firewall_unsupported_reason = log_debug_errno(SYNTHETIC_ERRNO(EBADE), - "Wut? Kernel accepted our invalid BPF_PROG_DETACH call? " + "bpf-firewall: Wut? Kernel accepted our invalid BPF_PROG_DETACH call? " "Something is weird, assuming BPF firewalling is broken and hence not supported."); return supported = BPF_FIREWALL_UNSUPPORTED; } @@ -902,20 +908,20 @@ int bpf_firewall_supported(void) { if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) { if (errno == EBADF) { - log_debug_errno(errno, "Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!"); + log_debug_errno(errno, "bpf-firewall: Got EBADF when using BPF_F_ALLOW_MULTI, which indicates it is supported. Yay!"); return supported = BPF_FIREWALL_SUPPORTED_WITH_MULTI; } if (errno == EINVAL) - log_debug_errno(errno, "Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported."); + log_debug_errno(errno, "bpf-firewall: Got EINVAL error when using BPF_F_ALLOW_MULTI, which indicates it's not supported."); else - log_debug_errno(errno, "Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m"); + log_debug_errno(errno, "bpf-firewall: Got unexpected error when using BPF_F_ALLOW_MULTI, assuming it's not supported: %m"); return supported = BPF_FIREWALL_SUPPORTED; } else { bpf_firewall_unsupported_reason = log_debug_errno(SYNTHETIC_ERRNO(EBADE), - "Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? " + "bpf-firewall: Wut? Kernel accepted our invalid BPF_PROG_ATTACH+BPF_F_ALLOW_MULTI call? " "Something is weird, assuming BPF firewalling is broken and hence not supported."); return supported = BPF_FIREWALL_UNSUPPORTED; } diff --git a/src/core/bpf-foreign.c b/src/core/bpf-foreign.c index 7f50f57389..83c3bac87f 100644 --- a/src/core/bpf-foreign.c +++ b/src/core/bpf-foreign.c @@ -63,7 +63,7 @@ static int attach_programs(Unit *u, const char *path, Hashmap* foreign_by_key, u HASHMAP_FOREACH_KEY(prog, key, foreign_by_key) { r = bpf_program_cgroup_attach(prog, key->attach_type, path, attach_flags); if (r < 0) - return log_unit_error_errno(u, r, "Attaching foreign BPF program to cgroup %s failed: %m", path); + return log_unit_error_errno(u, r, "bpf-foreign: Attaching foreign BPF program to cgroup %s failed: %m", path); } return 0; @@ -89,31 +89,31 @@ static int bpf_foreign_prepare( r = path_is_fs_type(bpffs_path, BPF_FS_MAGIC); if (r < 0) return log_unit_error_errno(u, r, - "Failed to determine filesystem type of %s: %m", bpffs_path); + "bpf-foreign: Failed to determine filesystem type of %s: %m", bpffs_path); if (r == 0) return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL), - "Path in BPF filesystem is expected."); + "bpf-foreign: Path in BPF filesystem is expected."); r = bpf_program_new_from_bpffs_path(bpffs_path, &prog); if (r < 0) - return log_unit_error_errno(u, r, "Failed to create foreign BPFProgram: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to create foreign BPF program: %m"); r = bpf_program_get_id_by_fd(prog->kernel_fd, &prog_id); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get BPF program id by fd: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to get BPF program id from fd: %m"); r = bpf_foreign_key_new(prog_id, attach_type, &key); if (r < 0) return log_unit_error_errno(u, r, - "Failed to create foreign BPF program key from path '%s': %m", bpffs_path); + "bpf-foreign: Failed to create foreign BPF program key from path '%s': %m", bpffs_path); r = hashmap_ensure_put(&u->bpf_foreign_by_key, &bpf_foreign_by_key_hash_ops, key, prog); if (r == -EEXIST) { - log_unit_warning_errno(u, r, "Foreign BPF program already exists, ignoring: %m"); + log_unit_warning_errno(u, r, "bpf-foreign: Foreign BPF program already exists, ignoring: %m"); return 0; } if (r < 0) - return log_unit_error_errno(u, r, "Failed to put foreign BPFProgram into map: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to put foreign BPF program into map: %m"); TAKE_PTR(key); TAKE_PTR(prog); @@ -134,17 +134,17 @@ int bpf_foreign_install(Unit *u) { r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get cgroup path: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to get cgroup path: %m"); LIST_FOREACH(programs, p, cc->bpf_foreign_programs) { r = bpf_foreign_prepare(u, p->attach_type, p->bpffs_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to prepare foreign BPF hashmap: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to prepare foreign BPF hashmap: %m"); } r = attach_programs(u, cgroup_path, u->bpf_foreign_by_key, BPF_F_ALLOW_MULTI); if (r < 0) - return log_unit_error_errno(u, r, "Failed to install foreign BPF programs: %m"); + return log_unit_error_errno(u, r, "bpf-foreign: Failed to install foreign BPF programs: %m"); return 0; } diff --git a/src/core/bpf-lsm.c b/src/core/bpf-lsm.c index d3e92b98a6..f3b9339558 100644 --- a/src/core/bpf-lsm.c +++ b/src/core/bpf-lsm.c @@ -26,6 +26,7 @@ /* libbpf, clang and llc compile time dependencies are satisfied */ #include "bpf-dlopen.h" #include "bpf-link.h" +#include "bpf-util.h" #include "bpf/restrict_fs/restrict-fs-skel.h" #define CGROUP_HASH_SIZE_MAX 2048 @@ -61,29 +62,29 @@ static int prepare_restrict_fs_bpf(struct restrict_fs_bpf **ret_obj) { obj = restrict_fs_bpf__open(); if (!obj) - return log_error_errno(errno, "Failed to open BPF object: %m"); + return log_error_errno(errno, "bpf-lsm: Failed to open BPF object: %m"); /* TODO Maybe choose a number based on runtime information? */ r = sym_bpf_map__resize(obj->maps.cgroup_hash, CGROUP_HASH_SIZE_MAX); assert(r <= 0); if (r < 0) - return log_error_errno(r, "Failed to resize BPF map '%s': %m", + return log_error_errno(r, "bpf-lsm: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.cgroup_hash)); /* Dummy map to satisfy the verifier */ inner_map_fd = sym_bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint32_t), 128, 0); if (inner_map_fd < 0) - return log_error_errno(errno, "Failed to create BPF map: %m"); + return log_error_errno(errno, "bpf-lsm: Failed to create BPF map: %m"); r = sym_bpf_map__set_inner_map_fd(obj->maps.cgroup_hash, inner_map_fd); assert(r <= 0); if (r < 0) - return log_error_errno(r, "Failed to set inner map fd: %m"); + return log_error_errno(r, "bpf-lsm: Failed to set inner map fd: %m"); r = restrict_fs_bpf__load(obj); assert(r <= 0); if (r < 0) - return log_error_errno(r, "Failed to load BPF object"); + return log_error_errno(r, "bpf-lsm: Failed to load BPF object: %m"); *ret_obj = TAKE_PTR(obj); @@ -103,7 +104,7 @@ static int mac_bpf_use(void) { r = read_one_line_file("/sys/kernel/security/lsm", &lsm_list); if (r < 0) { if (r != -ENOENT) - log_notice_errno(r, "Failed to read /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); + log_notice_errno(r, "bpf-lsm: Failed to read /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); return 0; } @@ -116,7 +117,7 @@ static int mac_bpf_use(void) { if (r == -ENOMEM) return log_oom(); if (r < 0) { - log_notice_errno(r, "Failed to parse /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); + log_notice_errno(r, "bpf-lsm: Failed to parse /sys/kernel/security/lsm, assuming bpf is unavailable: %m"); return 0; } @@ -135,33 +136,18 @@ bool lsm_bpf_supported(bool initialize) { if (!initialize) return false; - r = dlopen_bpf(); - if (r < 0) { - log_info_errno(r, "Failed to open libbpf, LSM BPF is not supported: %m"); + if (!cgroup_bpf_supported()) return (supported = false); - } - - r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); - if (r < 0) { - log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m"); - return (supported = false); - } - - if (r == 0) { - log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Not running with unified cgroup hierarchy, LSM BPF is not supported"); - return (supported = false); - } r = mac_bpf_use(); if (r < 0) { - log_warning_errno(r, "Can't determine whether the BPF LSM module is used: %m"); + log_warning_errno(r, "bpf-lsm: Can't determine whether the BPF LSM module is used: %m"); return (supported = false); } if (r == 0) { log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "BPF LSM hook not enabled in the kernel, LSM BPF not supported"); + "bpf-lsm: BPF LSM hook not enabled in the kernel, BPF LSM not supported"); return (supported = false); } @@ -171,7 +157,7 @@ bool lsm_bpf_supported(bool initialize) { if (!bpf_can_link_lsm_program(obj->progs.restrict_filesystems)) { log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Failed to link BPF program. Assuming BPF is not available"); + "bpf-lsm: Failed to link program; assuming BPF LSM is not available"); return (supported = false); } @@ -192,10 +178,10 @@ int lsm_bpf_setup(Manager *m) { link = sym_bpf_program__attach_lsm(obj->progs.restrict_filesystems); r = sym_libbpf_get_error(link); if (r != 0) - return log_error_errno(r, "Failed to link '%s' LSM BPF program: %m", + return log_error_errno(r, "bpf-lsm: Failed to link '%s' LSM BPF program: %m", sym_bpf_program__name(obj->progs.restrict_filesystems)); - log_info("LSM BPF program attached"); + log_info("bpf-lsm: LSM BPF program attached"); obj->links.restrict_filesystems = TAKE_PTR(link); m->restrict_fs = TAKE_PTR(obj); @@ -214,7 +200,7 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo if (!u->manager->restrict_fs) return log_unit_error_errno(u, SYNTHETIC_ERRNO(EINVAL), - "Restrict filesystems BPF object is not set, BPF LSM setup has failed?"); + "bpf-lsm: BPF LSM object is not installed, has setup failed?"); int inner_map_fd = sym_bpf_create_map( BPF_MAP_TYPE_HASH, @@ -223,39 +209,39 @@ int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, bool allo 128, /* Should be enough for all filesystem types */ 0); if (inner_map_fd < 0) - return log_unit_error_errno(u, errno, "Failed to create inner LSM map: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to create inner BPF map: %m"); int outer_map_fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash); if (outer_map_fd < 0) - return log_unit_error_errno(u, errno, "Failed to get BPF map fd: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m"); if (sym_bpf_map_update_elem(outer_map_fd, &u->cgroup_id, &inner_map_fd, BPF_ANY) != 0) - return log_unit_error_errno(u, errno, "Error populating LSM BPF map: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Error populating BPF map: %m"); uint32_t allow = allow_list; /* Use key 0 to store whether this is an allow list or a deny list */ if (sym_bpf_map_update_elem(inner_map_fd, &zero, &allow, BPF_ANY) != 0) - return log_unit_error_errno(u, errno, "Error initializing BPF map: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Error initializing map: %m"); SET_FOREACH(fs, filesystems) { r = fs_type_from_string(fs, &magic); if (r < 0) { - log_unit_warning(u, "Invalid filesystem name '%s', ignoring.", fs); + log_unit_warning(u, "bpf-lsm: Invalid filesystem name '%s', ignoring.", fs); continue; } - log_unit_debug(u, "Restricting filesystem access to '%s'", fs); + log_unit_debug(u, "bpf-lsm: Restricting filesystem access to '%s'", fs); for (int i = 0; i < FILESYSTEM_MAGIC_MAX; i++) { if (magic[i] == 0) break; if (sym_bpf_map_update_elem(inner_map_fd, &magic[i], &dummy_value, BPF_ANY) != 0) { - r = log_unit_error_errno(u, errno, "Failed to update BPF map: %m"); + r = log_unit_error_errno(u, errno, "bpf-lsm: Failed to update BPF map: %m"); if (sym_bpf_map_delete_elem(outer_map_fd, &u->cgroup_id) != 0) - log_unit_debug_errno(u, errno, "Failed to delete cgroup entry from LSM BPF map: %m"); + log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from BPF map: %m"); return r; } @@ -278,10 +264,10 @@ int lsm_bpf_cleanup(const Unit *u) { int fd = sym_bpf_map__fd(u->manager->restrict_fs->maps.cgroup_hash); if (fd < 0) - return log_unit_error_errno(u, errno, "Failed to get BPF map fd: %m"); + return log_unit_error_errno(u, errno, "bpf-lsm: Failed to get BPF map fd: %m"); if (sym_bpf_map_delete_elem(fd, &u->cgroup_id) != 0) - return log_unit_debug_errno(u, errno, "Failed to delete cgroup entry from LSM BPF map: %m"); + return log_unit_debug_errno(u, errno, "bpf-lsm: Failed to delete cgroup entry from LSM BPF map: %m"); return 0; } @@ -305,11 +291,11 @@ bool lsm_bpf_supported(bool initialize) { } int lsm_bpf_setup(Manager *m) { - return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to set up LSM BPF: %m"); + return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to set up LSM BPF: %m"); } int lsm_bpf_unit_restrict_filesystems(Unit *u, const Set *filesystems, const bool allow_list) { - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to restrict filesystems using LSM BPF: %m"); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-lsm: Failed to restrict filesystems using LSM BPF: %m"); } int lsm_bpf_cleanup(const Unit *u) { @@ -344,7 +330,7 @@ int lsm_bpf_parse_filesystem( set = filesystem_set_find(name); if (!set) { log_syntax(unit, flags & FILESYSTEM_PARSE_LOG ? LOG_WARNING : LOG_DEBUG, filename, line, 0, - "Unknown filesystem group, ignoring: %s", name); + "bpf-lsm: Unknown filesystem group, ignoring: %s", name); return 0; } diff --git a/src/core/bpf-socket-bind.c b/src/core/bpf-socket-bind.c index 09f83dc667..3aa1bfa1f1 100644 --- a/src/core/bpf-socket-bind.c +++ b/src/core/bpf-socket-bind.c @@ -11,8 +11,9 @@ /* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */ #include "bpf-dlopen.h" #include "bpf-link.h" -#include "bpf/socket_bind/socket-bind-skel.h" +#include "bpf-util.h" #include "bpf/socket_bind/socket-bind-api.bpf.h" +#include "bpf/socket_bind/socket-bind-skel.h" static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) { /* socket_bind_bpf__destroy handles object == NULL case */ @@ -68,27 +69,27 @@ static int prepare_socket_bind_bpf( if (allow_count > SOCKET_BIND_MAX_RULES) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL), - "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); + "bpf-socket-bind: Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); if (deny_count > SOCKET_BIND_MAX_RULES) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, SYNTHETIC_ERRNO(EINVAL), - "Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); + "bpf-socket-bind: Maximum number of socket bind rules=%u is exceeded", SOCKET_BIND_MAX_RULES); obj = socket_bind_bpf__open(); if (!obj) - return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "Failed to open BPF object: %m"); + return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "bpf-socket-bind: Failed to open BPF object: %m"); if (sym_bpf_map__resize(obj->maps.sd_bind_allow, MAX(allow_count, 1u)) != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno, - "Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow)); + "bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_allow)); if (sym_bpf_map__resize(obj->maps.sd_bind_deny, MAX(deny_count, 1u)) != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno, - "Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny)); + "bpf-socket-bind: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_bind_deny)); if (socket_bind_bpf__load(obj) != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, - "Failed to load BPF object: %m"); + "bpf-socket-bind: Failed to load BPF object: %m"); allow_map_fd = sym_bpf_map__fd(obj->maps.sd_bind_allow); assert(allow_map_fd >= 0); @@ -96,7 +97,7 @@ static int prepare_socket_bind_bpf( r = update_rules_map(allow_map_fd, allow); if (r < 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r, - "Failed to put socket bind allow rules into BPF map '%s'", + "bpf-socket-bind: Failed to put socket bind allow rules into BPF map '%s'", sym_bpf_map__name(obj->maps.sd_bind_allow)); deny_map_fd = sym_bpf_map__fd(obj->maps.sd_bind_deny); @@ -105,7 +106,7 @@ static int prepare_socket_bind_bpf( r = update_rules_map(deny_map_fd, deny); if (r < 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r, - "Failed to put socket bind deny rules into BPF map '%s'", + "bpf-socket-bind: Failed to put socket bind deny rules into BPF map '%s'", sym_bpf_map__name(obj->maps.sd_bind_deny)); *ret_obj = TAKE_PTR(obj); @@ -116,25 +117,17 @@ int bpf_socket_bind_supported(void) { _cleanup_(socket_bind_bpf_freep) struct socket_bind_bpf *obj = NULL; int r; - r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); - if (r < 0) - return log_debug_errno(r, "Can't determine whether the unified hierarchy is used: %m"); - if (r == 0) { - log_debug("Not running with unified cgroup hierarchy, BPF is not supported"); - return false; - } - - if (dlopen_bpf() < 0) + if (!cgroup_bpf_supported()) return false; if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, /*ifindex=*/0)) { - log_debug("BPF program type cgroup_sock_addr is not supported"); + log_debug("bpf-socket-bind: BPF program type cgroup_sock_addr is not supported"); return false; } r = prepare_socket_bind_bpf(/*unit=*/NULL, /*allow_rules=*/NULL, /*deny_rules=*/NULL, &obj); if (r < 0) { - log_debug_errno(r, "BPF based socket_bind is not supported: %m"); + log_debug_errno(r, "bpf-socket-bind: socket bind filtering is not supported: %m"); return false; } @@ -154,7 +147,7 @@ int bpf_socket_bind_add_initial_link_fd(Unit *u, int fd) { r = fdset_put(u->initial_socket_bind_link_fds, fd); if (r < 0) - return log_unit_error_errno(u, r, "Failed to put socket-bind BPF link fd %d to initial fdset", fd); + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to put BPF fd %d to initial fdset", fd); return 0; } @@ -175,29 +168,29 @@ static int socket_bind_install_impl(Unit *u) { r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get cgroup path: %m"); + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to get cgroup path: %m"); if (!cc->socket_bind_allow && !cc->socket_bind_deny) return 0; r = prepare_socket_bind_bpf(u, cc->socket_bind_allow, cc->socket_bind_deny, &obj); if (r < 0) - return log_unit_error_errno(u, r, "Failed to load BPF object: %m"); + return log_unit_error_errno(u, r, "bpf-socket-bind: Failed to load BPF object: %m"); cgroup_fd = open(cgroup_path, O_RDONLY | O_CLOEXEC, 0); if (cgroup_fd < 0) - return log_unit_error_errno(u, errno, "Failed to open cgroup=%s for reading: %m", cgroup_path); + 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); if (r != 0) - return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program: %m", + 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); if (r != 0) - return log_unit_error_errno(u, r, "Failed to link '%s' cgroup-bpf program: %m", + 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)); u->ipv4_socket_bind_link = TAKE_PTR(ipv4); @@ -241,7 +234,8 @@ int bpf_socket_bind_add_initial_link_fd(Unit *u, int fd) { } int bpf_socket_bind_install(Unit *u) { - return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), "Failed to install socket bind: BPF framework is not supported"); + return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-socket-bind: Failed to install; BPF framework is not supported"); } int bpf_serialize_socket_bind(Unit *u, FILE *f, FDSet *fds) { diff --git a/src/core/bpf-util.c b/src/core/bpf-util.c new file mode 100644 index 0000000000..9130aa373f --- /dev/null +++ b/src/core/bpf-util.c @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "bpf-dlopen.h" +#include "bpf-util.h" +#include "cgroup-util.h" +#include "log.h" + +bool cgroup_bpf_supported(void) { + static int supported = -1; + int r; + + if (supported >= 0) + return supported; + + r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); + if (r < 0) { + log_warning_errno(r, "Can't determine whether the unified hierarchy is used: %m"); + return (supported = false); + } + + if (r == 0) { + log_info_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "Not running with unified cgroup hierarchy, disabling cgroup BPF features."); + return (supported = false); + } + + r = dlopen_bpf(); + if (r < 0) { + log_info_errno(r, "Failed to open libbpf, cgroup BPF features disabled: %m"); + return (supported = false); + } + + return (supported = true); +} diff --git a/src/core/bpf-util.h b/src/core/bpf-util.h new file mode 100644 index 0000000000..a6c55cd7e5 --- /dev/null +++ b/src/core/bpf-util.h @@ -0,0 +1,5 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +bool cgroup_bpf_supported(void); diff --git a/src/core/meson.build b/src/core/meson.build index 1e8b6dc310..d7ac4e59a8 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -1,139 +1,146 @@ # SPDX-License-Identifier: LGPL-2.1-or-later -libcore_sources = ''' - apparmor-setup.c - apparmor-setup.h - audit-fd.c - audit-fd.h - automount.c - automount.h - bpf-devices.c - bpf-devices.h - bpf-firewall.c - bpf-firewall.h - bpf-foreign.c - bpf-foreign.h - bpf-lsm.c - bpf-lsm.h - bpf-socket-bind.c - bpf-socket-bind.h - cgroup.c - cgroup.h - core-varlink.c - core-varlink.h - dbus-automount.c - dbus-automount.h - dbus-cgroup.c - dbus-cgroup.h - dbus-device.c - dbus-device.h - dbus-execute.c - dbus-execute.h - dbus-job.c - dbus-job.h - dbus-kill.c - dbus-kill.h - dbus-manager.c - dbus-manager.h - dbus-mount.c - dbus-mount.h - dbus-path.c - dbus-path.h - dbus-scope.c - dbus-scope.h - dbus-service.c - dbus-service.h - dbus-slice.c - dbus-slice.h - dbus-socket.c - dbus-socket.h - dbus-swap.c - dbus-swap.h - dbus-target.c - dbus-target.h - dbus-timer.c - dbus-timer.h - dbus-unit.c - dbus-unit.h - dbus-util.c - dbus-util.h - dbus.c - dbus.h - device.c - device.h - dynamic-user.c - dynamic-user.h - efi-random.c - efi-random.h - emergency-action.c - emergency-action.h - execute.c - execute.h - generator-setup.c - generator-setup.h - ima-setup.c - ima-setup.h - import-creds.c - import-creds.h - job.c - job.h - kill.c - kill.h - kmod-setup.c - kmod-setup.h - load-dropin.c - load-dropin.h - load-fragment.c - load-fragment.h - locale-setup.c - locale-setup.h - manager-dump.c - manager-dump.h - manager-serialize.c - manager-serialize.h - manager.c - manager.h - mount.c - mount.h - namespace.c - namespace.h - path.c - path.h - restrict-ifaces.c - restrict-ifaces.h - scope.c - scope.h - selinux-access.c - selinux-access.h - selinux-setup.c - selinux-setup.h - service.c - service.h - show-status.c - show-status.h - slice.c - slice.h - smack-setup.c - smack-setup.h - socket.c - socket.h - swap.c - swap.h - target.c - target.h - timer.c - timer.h - transaction.c - transaction.h - unit-dependency-atom.c - unit-dependency-atom.h - unit-printf.c - unit-printf.h - unit-serialize.c - unit-serialize.h - unit.c - unit.h -'''.split() +libcore_sources = files( + 'apparmor-setup.c', + 'apparmor-setup.h', + 'audit-fd.c', + 'audit-fd.h', + 'automount.c', + 'automount.h', + 'bpf-devices.c', + 'bpf-devices.h', + 'bpf-firewall.c', + 'bpf-firewall.h', + 'bpf-foreign.c', + 'bpf-foreign.h', + 'bpf-lsm.c', + 'bpf-lsm.h', + 'bpf-socket-bind.c', + 'bpf-socket-bind.h', + 'cgroup.c', + 'cgroup.h', + 'core-varlink.c', + 'core-varlink.h', + 'dbus-automount.c', + 'dbus-automount.h', + 'dbus-cgroup.c', + 'dbus-cgroup.h', + 'dbus-device.c', + 'dbus-device.h', + 'dbus-execute.c', + 'dbus-execute.h', + 'dbus-job.c', + 'dbus-job.h', + 'dbus-kill.c', + 'dbus-kill.h', + 'dbus-manager.c', + 'dbus-manager.h', + 'dbus-mount.c', + 'dbus-mount.h', + 'dbus-path.c', + 'dbus-path.h', + 'dbus-scope.c', + 'dbus-scope.h', + 'dbus-service.c', + 'dbus-service.h', + 'dbus-slice.c', + 'dbus-slice.h', + 'dbus-socket.c', + 'dbus-socket.h', + 'dbus-swap.c', + 'dbus-swap.h', + 'dbus-target.c', + 'dbus-target.h', + 'dbus-timer.c', + 'dbus-timer.h', + 'dbus-unit.c', + 'dbus-unit.h', + 'dbus-util.c', + 'dbus-util.h', + 'dbus.c', + 'dbus.h', + 'device.c', + 'device.h', + 'dynamic-user.c', + 'dynamic-user.h', + 'efi-random.c', + 'efi-random.h', + 'emergency-action.c', + 'emergency-action.h', + 'execute.c', + 'execute.h', + 'generator-setup.c', + 'generator-setup.h', + 'ima-setup.c', + 'ima-setup.h', + 'import-creds.c', + 'import-creds.h', + 'job.c', + 'job.h', + 'kill.c', + 'kill.h', + 'kmod-setup.c', + 'kmod-setup.h', + 'load-dropin.c', + 'load-dropin.h', + 'load-fragment.c', + 'load-fragment.h', + 'locale-setup.c', + 'locale-setup.h', + 'manager-dump.c', + 'manager-dump.h', + 'manager-serialize.c', + 'manager-serialize.h', + 'manager.c', + 'manager.h', + 'mount.c', + 'mount.h', + 'namespace.c', + 'namespace.h', + 'path.c', + 'path.h', + 'restrict-ifaces.c', + 'restrict-ifaces.h', + 'scope.c', + 'scope.h', + 'selinux-access.c', + 'selinux-access.h', + 'selinux-setup.c', + 'selinux-setup.h', + 'service.c', + 'service.h', + 'show-status.c', + 'show-status.h', + 'slice.c', + 'slice.h', + 'smack-setup.c', + 'smack-setup.h', + 'socket.c', + 'socket.h', + 'swap.c', + 'swap.h', + 'target.c', + 'target.h', + 'timer.c', + 'timer.h', + 'transaction.c', + 'transaction.h', + 'unit-dependency-atom.c', + 'unit-dependency-atom.h', + 'unit-printf.c', + 'unit-printf.h', + 'unit-serialize.c', + 'unit-serialize.h', + 'unit.c', + 'unit.h', +) + +if conf.get('BPF_FRAMEWORK') == 1 + libcore_sources += files( + 'bpf-util.c', + 'bpf-util.h', + ) +endif subdir('bpf') diff --git a/src/core/restrict-ifaces.c b/src/core/restrict-ifaces.c index efa5c8d85a..a0ecaff814 100644 --- a/src/core/restrict-ifaces.c +++ b/src/core/restrict-ifaces.c @@ -9,7 +9,7 @@ #include "bpf-dlopen.h" #include "bpf-link.h" - +#include "bpf-util.h" #include "bpf/restrict_ifaces/restrict-ifaces-skel.h" static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) { @@ -34,19 +34,19 @@ static int prepare_restrict_ifaces_bpf( obj = restrict_ifaces_bpf__open(); if (!obj) - return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "Failed to open BPF object: %m"); + return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, errno, "restrict-interfaces: Failed to open BPF object: %m"); r = sym_bpf_map__resize(obj->maps.sd_restrictif, MAX(set_size(restrict_network_interfaces), 1u)); if (r != 0) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, r, - "Failed to resize BPF map '%s': %m", + "restrict-interfaces: Failed to resize BPF map '%s': %m", sym_bpf_map__name(obj->maps.sd_restrictif)); obj->rodata->is_allow_list = is_allow_list; r = restrict_ifaces_bpf__load(obj); if (r != 0) - return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, r, "Failed to load BPF object: %m"); + return log_unit_full_errno(u, u ? LOG_ERR : LOG_DEBUG, r, "restrict-interfaces: Failed to load BPF object: %m"); map_fd = sym_bpf_map__fd(obj->maps.sd_restrictif); @@ -56,13 +56,15 @@ static int prepare_restrict_ifaces_bpf( ifindex = rtnl_resolve_interface(&rtnl, iface); if (ifindex < 0) { - log_unit_warning_errno(u, ifindex, "Couldn't find index of network interface '%s', ignoring: %m", iface); + log_unit_warning_errno(u, ifindex, + "restrict-interfaces: Couldn't find index of network interface '%s', ignoring: %m", + iface); continue; } if (sym_bpf_map_update_elem(map_fd, &ifindex, &dummy, BPF_ANY)) return log_unit_full_errno(u, u ? LOG_ERR : LOG_WARNING, errno, - "Failed to update BPF map '%s' fd: %m", + "restrict-interfaces: Failed to update BPF map '%s' fd: %m", sym_bpf_map__name(obj->maps.sd_restrictif)); } @@ -78,29 +80,21 @@ int restrict_network_interfaces_supported(void) { if (supported >= 0) return supported; - r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER); - if (r < 0) - return log_error_errno(r, "Can't determine whether the unified hierarchy is used: %m"); - if (r == 0) { - log_debug("Not running with unified cgroup hierarchy, BPF is not supported"); - return supported = 0; - } - - if (dlopen_bpf() < 0) - return false; + if (!cgroup_bpf_supported()) + return (supported = false); if (!sym_bpf_probe_prog_type(BPF_PROG_TYPE_CGROUP_SKB, /*ifindex=*/0)) { - log_debug("BPF program type cgroup_skb is not supported"); - return supported = 0; + log_debug("restrict-interfaces: BPF program type cgroup_skb is not supported"); + return (supported = false); } r = prepare_restrict_ifaces_bpf(NULL, true, NULL, &obj); if (r < 0) { - log_debug_errno(r, "Failed to load BPF object: %m"); - return supported = 0; + log_debug_errno(r, "restrict-interfaces: Failed to load BPF object: %m"); + return (supported = false); } - return supported = bpf_can_link_program(obj->progs.sd_restrictif_i); + return (supported = bpf_can_link_program(obj->progs.sd_restrictif_i)); } static int restrict_network_interfaces_install_impl(Unit *u) { @@ -117,7 +111,7 @@ static int restrict_network_interfaces_install_impl(Unit *u) { r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, NULL, &cgroup_path); if (r < 0) - return log_unit_error_errno(u, r, "Failed to get cgroup path: %m"); + return log_unit_error_errno(u, r, "restrict-interfaces: Failed to get cgroup path: %m"); if (!cc->restrict_network_interfaces) return 0; @@ -136,12 +130,12 @@ static int restrict_network_interfaces_install_impl(Unit *u) { ingress_link = sym_bpf_program__attach_cgroup(obj->progs.sd_restrictif_i, cgroup_fd); r = sym_libbpf_get_error(ingress_link); if (r != 0) - return log_unit_error_errno(u, r, "Failed to create ingress cgroup link: %m"); + 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); if (r != 0) - return log_unit_error_errno(u, r, "Failed to create egress cgroup link: %m"); + return log_unit_error_errno(u, r, "restrict-interfaces: Failed to create egress cgroup link: %m"); u->restrict_ifaces_ingress_bpf_link = TAKE_PTR(ingress_link); u->restrict_ifaces_egress_bpf_link = TAKE_PTR(egress_link); @@ -180,7 +174,8 @@ int restrict_network_interfaces_add_initial_link_fd(Unit *u, int fd) { r = fdset_put(u->initial_restric_ifaces_link_fds, fd); if (r < 0) - return log_unit_error_errno(u, r, "Failed to put restrict-ifaces-bpf-fd %d to restored fdset: %m", fd); + return log_unit_error_errno(u, r, + "restrict-interfaces: Failed to put restrict-ifaces-bpf-fd %d to restored fdset: %m", fd); return 0; } @@ -192,7 +187,7 @@ int restrict_network_interfaces_supported(void) { int restrict_network_interfaces_install(Unit *u) { return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP), - "Failed to install RestrictInterfaces: BPF programs built from source code are not supported: %m"); + "restrict-interfaces: Failed to install; BPF programs built from source code are not supported: %m"); } int serialize_restrict_network_interfaces(Unit *u, FILE *f, FDSet *fds) { diff --git a/src/shared/bpf-dlopen.c b/src/shared/bpf-dlopen.c index 6f82002ff8..d8e778794c 100644 --- a/src/shared/bpf-dlopen.c +++ b/src/shared/bpf-dlopen.c @@ -9,7 +9,6 @@ static void *bpf_dl = NULL; struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int); struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *); -long (*sym_libbpf_get_error)(const void *); int (*sym_bpf_link__fd)(const struct bpf_link *); int (*sym_bpf_link__destroy)(struct bpf_link *); int (*sym_bpf_map__fd)(const struct bpf_map *); @@ -26,9 +25,27 @@ void (*sym_bpf_object__detach_skeleton)(struct bpf_object_skeleton *); void (*sym_bpf_object__destroy_skeleton)(struct bpf_object_skeleton *); bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32); const char* (*sym_bpf_program__name)(const struct bpf_program *); +libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t); +long (*sym_libbpf_get_error)(const void *); + +_printf_(2,0) +static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_list ap) { +#if !LOG_TRACE + /* libbpf logs a lot of details at its debug level, which we don't need to see. */ + if (level == LIBBPF_DEBUG) + return 0; +#endif + /* All other levels are downgraded to LOG_DEBUG */ + + /* errno is used here, on the assumption that if the log message uses %m, errno will be set to + * something useful. Otherwise, it shouldn't matter, we may pass 0 or some bogus value. */ + return log_internalv(LOG_DEBUG, errno, NULL, 0, NULL, fmt, ap); +} int dlopen_bpf(void) { - return dlopen_many_sym_or_warn( + int r; + + r = dlopen_many_sym_or_warn( &bpf_dl, "libbpf.so.0", LOG_DEBUG, DLSYM_ARG(bpf_link__destroy), DLSYM_ARG(bpf_link__fd), @@ -48,7 +65,14 @@ int dlopen_bpf(void) { DLSYM_ARG(bpf_program__attach_cgroup), DLSYM_ARG(bpf_program__attach_lsm), DLSYM_ARG(bpf_program__name), + DLSYM_ARG(libbpf_set_print), DLSYM_ARG(libbpf_get_error)); + if (r < 0) + return r; + + /* We set the print helper unconditionally. Otherwise libbpf will emit not useful log messages. */ + (void) sym_libbpf_set_print(bpf_print_func); + return r; } #else diff --git a/src/shared/bpf-dlopen.h b/src/shared/bpf-dlopen.h index 713c41c3f4..f0d40325d9 100644 --- a/src/shared/bpf-dlopen.h +++ b/src/shared/bpf-dlopen.h @@ -8,7 +8,6 @@ extern struct bpf_link* (*sym_bpf_program__attach_cgroup)(struct bpf_program *, int); extern struct bpf_link* (*sym_bpf_program__attach_lsm)(struct bpf_program *); -extern long (*sym_libbpf_get_error)(const void *); extern int (*sym_bpf_link__fd)(const struct bpf_link *); extern int (*sym_bpf_link__destroy)(struct bpf_link *); extern int (*sym_bpf_map__fd)(const struct bpf_map *); @@ -27,6 +26,8 @@ extern void (*sym_bpf_object__detach_skeleton)(struct bpf_object_skeleton *); extern void (*sym_bpf_object__destroy_skeleton)(struct bpf_object_skeleton *); extern bool (*sym_bpf_probe_prog_type)(enum bpf_prog_type, __u32); extern const char* (*sym_bpf_program__name)(const struct bpf_program *); +extern libbpf_print_fn_t (*sym_libbpf_set_print)(libbpf_print_fn_t); +extern long (*sym_libbpf_get_error)(const void *); #endif diff --git a/src/test/test-bpf-firewall.c b/src/test/test-bpf-firewall.c index 8f4b485073..3b99c5aaec 100644 --- a/src/test/test-bpf-firewall.c +++ b/src/test/test-bpf-firewall.c @@ -61,9 +61,6 @@ int main(int argc, char *argv[]) { r = bpf_program_add_instructions(p, exit_insn, ELEMENTSOF(exit_insn)); assert_se(r == 0); - if (getuid() != 0) - return log_tests_skipped("not running as root"); - r = bpf_firewall_supported(); if (r == BPF_FIREWALL_UNSUPPORTED) return log_tests_skipped("BPF firewalling not supported"); diff --git a/src/test/test-bpf-lsm.c b/src/test/test-bpf-lsm.c index 630d60dbf5..9709053d0a 100644 --- a/src/test/test-bpf-lsm.c +++ b/src/test/test-bpf-lsm.c @@ -68,9 +68,6 @@ int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); - if (getuid() != 0) - return log_tests_skipped("not running as root"); - assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0); rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE); (void) setrlimit_closest(RLIMIT_MEMLOCK, &rl); diff --git a/src/test/test-socket-bind.c b/src/test/test-socket-bind.c index 59d8cc965b..dadd2c0dff 100644 --- a/src/test/test-socket-bind.c +++ b/src/test/test-socket-bind.c @@ -108,10 +108,7 @@ int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); if (detect_container() > 0) - return log_tests_skipped("test-bpf fails inside LXC and Docker containers: https://github.com/systemd/systemd/issues/9666"); - - if (getuid() != 0) - return log_tests_skipped("not running as root"); + return log_tests_skipped("test-socket-bind fails inside LXC and Docker containers: https://github.com/systemd/systemd/issues/9666"); assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0); rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE); @@ -125,7 +122,7 @@ int main(int argc, char *argv[]) { return log_tests_skipped("socket-bind is not supported"); if (find_netcat_executable(&netcat_path) != 0) - return log_tests_skipped("Can not find netcat executable"); + return log_tests_skipped("Cannot find netcat executable"); r = enter_cgroup_subroot(NULL); if (r == -ENOMEDIUM) diff --git a/src/userdb/userwork.c b/src/userdb/userwork.c index 18d58c308c..21a869df1b 100644 --- a/src/userdb/userwork.c +++ b/src/userdb/userwork.c @@ -553,10 +553,10 @@ static int run(int argc, char *argv[]) { parent = getppid(); if (parent <= 1) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Parent already died?"); + return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Parent already died?"); if (kill(parent, SIGUSR2) < 0) - return log_error_errno(errno, "Failed to kill our own parent."); + return log_error_errno(errno, "Failed to kill our own parent: %m"); } } diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index aa16582d9e..e29d4df692 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -127,7 +127,7 @@ static int run(int argc, char *argv[]) { r = query_volatile_mode(&m); if (r < 0) - return log_error_errno(r, "Failed to determine volatile mode from kernel command line."); + return log_error_errno(r, "Failed to determine volatile mode from kernel command line: %m"); if (r == 0 && argc >= 2) { /* The kernel command line always wins. However if nothing was set there, the argument passed here wins instead. */ m = volatile_mode_from_string(argv[1]);