Merge pull request #7481 from poettering/bpf-test-fix

bpf-firewall: actually invoke BPF_PROG_ATTACH to check whether cgroup/bpf is available
This commit is contained in:
Michael Biebl 2017-12-01 13:52:32 +01:00 committed by GitHub
commit 35ccaf9332
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 3 deletions

3
TODO
View File

@ -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

View File

@ -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;
}