From 0634585890b389e3e2b4d3c6d80d4f49d7497061 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 Nov 2017 12:42:35 +0100 Subject: [PATCH 1/2] update TODO --- TODO | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TODO b/TODO index f7ed2627ba..9aeb66bbaf 100644 --- a/TODO +++ b/TODO @@ -24,6 +24,9 @@ Janitorial Clean-ups: Features: +* make use of ethtool veth peer info in machined, for automatically finding out + host-side interface pointing to the container. + * add some special mode to LogsDirectory=/StateDirectory=… that allows declaring these directories without necessarily pulling in deps for them, or creating them when starting up. That way, we could declare that From e583759bd1a6f9906e6eda6d3835b514bd720b5c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 27 Nov 2017 12:42:40 +0100 Subject: [PATCH 2/2] bpf-firewall: actually invoke BPF_PROG_ATTACH to check whether cgroup/bpf is available Apparently that's the only way to really know whether the kernel has CONFIG_CGROUP_BPF turned on. Fixes: #7054 --- src/core/bpf-firewall.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c index 148f1a5dcb..f3f40fb0e8 100644 --- a/src/core/bpf-firewall.c +++ b/src/core/bpf-firewall.c @@ -649,13 +649,16 @@ int bpf_firewall_supported(void) { _cleanup_(bpf_program_unrefp) BPFProgram *program = NULL; static int supported = -1; + union bpf_attr attr; int fd, r; - /* Checks whether BPF firewalling is supported. For this, we check three things: + /* Checks whether BPF firewalling is supported. For this, we check five things: * * a) whether we are privileged * b) whether the unified hierarchy is being used * c) the BPF implementation in the kernel supports BPF LPM TRIE maps, which we require + * d) the BPF implementation in the kernel supports BPF_PROG_TYPE_CGROUP_SKB programs, which we require + * e) the BPF implementation in the kernel supports the BPF_PROG_ATTACH call, which we require * */ @@ -670,8 +673,10 @@ 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"); - if (r == 0) + if (r == 0) { + log_debug("Not running with unified cgroups, BPF firewalling is not supported."); return supported = false; + } fd = bpf_map_new(BPF_MAP_TYPE_LPM_TRIE, offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint64_t), @@ -702,5 +707,28 @@ int bpf_firewall_supported(void) { return supported = false; } - return supported = true; + /* Unfortunately the kernel allows us to create BPF_PROG_TYPE_CGROUP_SKB programs even when CONFIG_CGROUP_BPF + * is turned off at kernel compilation time. This sucks of course: why does it allow us to create a cgroup BPF + * program if we can't do a thing with it later? + * + * We detect this case by issuing the BPF_PROG_ATTACH bpf() call with invalid file descriptors: if + * CONFIG_CGROUP_BPF is turned off, then the call will fail early with EINVAL. If it is turned on the + * parameters are validated however, and that'll fail with EBADF then. */ + + attr = (union bpf_attr) { + .attach_type = BPF_CGROUP_INET_EGRESS, + .target_fd = -1, + .attach_bpf_fd = -1, + }; + + r = bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)); + if (r < 0) { + if (errno == EBADF) /* YAY! */ + return supported = true; + + log_debug_errno(errno, "Didn't get EBADF from BPF_PROG_ATTACH, BPF firewalling is not supported: %m"); + } else + log_debug("Wut? kernel accepted our invalid BPF_PROG_ATTACH call? Something is weird, assuming BPF firewalling is broken and hence not supported."); + + return supported = false; }