1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

Merge pull request #12741 from keszybz/bpf-firewall-warning

Silence BPF firewall warning when not useful
This commit is contained in:
Yu Watanabe 2019-06-05 04:01:44 +09:00 committed by GitHub
commit 277cb7631e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 45 deletions

View File

@ -23,6 +23,7 @@
#include "memory-util.h"
#include "missing_syscall.h"
#include "unit.h"
#include "virt.h"
enum {
MAP_KEY_PACKETS,
@ -484,19 +485,17 @@ int bpf_firewall_compile(Unit *u) {
supported = bpf_firewall_supported();
if (supported < 0)
return supported;
if (supported == BPF_FIREWALL_UNSUPPORTED) {
log_unit_debug(u, "BPF firewalling not supported on this manager, proceeding without.");
return -EOPNOTSUPP;
}
if (supported != BPF_FIREWALL_SUPPORTED_WITH_MULTI && u->type == UNIT_SLICE) {
if (supported == BPF_FIREWALL_UNSUPPORTED)
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EOPNOTSUPP),
"BPF firewalling not supported on this manager, 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
* that BPF is more interesting on leaf nodes we hence avoid it on inner nodes in that case. This is
* consistent with old systemd behaviour from before v238, where BPF wasn't supported in inner nodes at
* all, either. */
log_unit_debug(u, "BPF_F_ALLOW_MULTI is not supported on this manager, not doing BPF firewall on slice units.");
return -EOPNOTSUPP;
}
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.");
/* Note that when we compile a new firewall we first flush out the access maps and the BPF programs themselves,
* but we reuse the the accounting maps. That way the firewall in effect always maps to the actual
@ -645,6 +644,8 @@ int bpf_firewall_reset_accounting(int map_fd) {
return bpf_map_update_element(map_fd, &key, &value);
}
static int bpf_firewall_unsupported_reason = 0;
int bpf_firewall_supported(void) {
struct bpf_insn trivial[] = {
BPF_MOV64_IMM(BPF_REG_0, 1),
@ -669,7 +670,9 @@ int bpf_firewall_supported(void) {
return supported;
if (geteuid() != 0) {
log_debug("Not enough privileges, BPF firewalling is not supported.");
bpf_firewall_unsupported_reason =
log_debug_errno(SYNTHETIC_ERRNO(EACCES),
"Not enough privileges, BPF firewalling is not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@ -677,7 +680,9 @@ int bpf_firewall_supported(void) {
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 cgroups, BPF firewalling is not supported.");
bpf_firewall_unsupported_reason =
log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Not running with unified cgroups, BPF firewalling is not supported.");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@ -687,7 +692,8 @@ int bpf_firewall_supported(void) {
1,
BPF_F_NO_PREALLOC);
if (fd < 0) {
log_debug_errno(fd, "Can't allocate BPF LPM TRIE map, BPF firewalling is not supported: %m");
bpf_firewall_unsupported_reason =
log_debug_errno(fd, "Can't allocate BPF LPM TRIE map, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@ -695,19 +701,22 @@ int bpf_firewall_supported(void) {
r = bpf_program_new(BPF_PROG_TYPE_CGROUP_SKB, &program);
if (r < 0) {
log_debug_errno(r, "Can't allocate CGROUP SKB BPF program, BPF firewalling is not supported: %m");
bpf_firewall_unsupported_reason =
log_debug_errno(r, "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) {
log_debug_errno(r, "Can't add trivial instructions to CGROUP SKB BPF program, BPF firewalling is not supported: %m");
bpf_firewall_unsupported_reason =
log_debug_errno(r, "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) {
log_debug_errno(r, "Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m");
bpf_firewall_unsupported_reason =
log_debug_errno(r, "Can't load kernel CGROUP SKB BPF program, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@ -727,7 +736,8 @@ int bpf_firewall_supported(void) {
if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) {
if (errno != EBADF) {
log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m");
bpf_firewall_unsupported_reason =
log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_DETACH, BPF firewalling is not supported: %m");
return supported = BPF_FIREWALL_UNSUPPORTED;
}
@ -766,3 +776,18 @@ int bpf_firewall_supported(void) {
return supported = BPF_FIREWALL_UNSUPPORTED;
}
}
void emit_bpf_firewall_warning(Unit *u) {
static bool warned = false;
if (!warned) {
bool quiet = bpf_firewall_unsupported_reason == -EPERM && detect_container();
log_unit_full(u, quiet ? LOG_DEBUG : LOG_WARNING, bpf_firewall_unsupported_reason,
"unit configures an IP firewall, but %s.\n"
"(This warning is only shown for the first unit using IP firewalling.)",
getuid() != 0 ? "not running as root" :
"the local system does not support BPF/cgroup firewalling");
warned = true;
}
}

View File

@ -18,3 +18,5 @@ int bpf_firewall_install(Unit *u);
int bpf_firewall_read_accounting(int map_fd, uint64_t *ret_bytes, uint64_t *ret_packets);
int bpf_firewall_reset_accounting(int map_fd);
void emit_bpf_firewall_warning(Unit *u);

View File

@ -1540,6 +1540,10 @@ CGroupMask unit_get_target_mask(Unit *u) {
* hierarchy that shall be enabled for it. */
mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
if (mask & CGROUP_MASK_BPF_FIREWALL & ~u->manager->cgroup_supported)
emit_bpf_firewall_warning(u);
mask &= u->manager->cgroup_supported;
mask &= ~unit_get_ancestor_disable_mask(u);

View File

@ -1426,21 +1426,6 @@ int bus_cgroup_set_property(
return r;
unit_write_setting(u, flags, name, buf);
if (*list) {
r = bpf_firewall_supported();
if (r < 0)
return r;
if (r == BPF_FIREWALL_UNSUPPORTED) {
static bool warned = false;
log_full(warned ? LOG_DEBUG : LOG_WARNING,
"Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
"Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
warned = true;
}
}
}
return 1;

View File

@ -134,21 +134,6 @@ int config_parse_ip_address_access(
*list = ip_address_access_reduce(*list);
if (*list) {
r = bpf_firewall_supported();
if (r < 0)
return r;
if (r == BPF_FIREWALL_UNSUPPORTED) {
static bool warned = false;
log_full(warned ? LOG_DEBUG : LOG_WARNING,
"File %s:%u configures an IP firewall (%s=%s), but the local system does not support BPF/cgroup based firewalling.\n"
"Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)", filename, line, lvalue, rvalue);
warned = true;
}
}
return 0;
}