]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-bpf: check if we can mlock() before trying bpf
authorLennart Poettering <lennart@poettering.net>
Thu, 24 Jan 2019 09:19:33 +0000 (10:19 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 24 Jan 2019 22:50:26 +0000 (23:50 +0100)
src/test/test-bpf.c

index 7341f7f1eadaf1d840971d18f35fd119e6391314..cd8d68f215b2074b702784da880e231dab5c9a8a 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <linux/libbpf.h>
 #include <string.h>
+#include <sys/mman.h>
 #include <unistd.h>
 
 #include "bpf-firewall.h"
 #include "tests.h"
 #include "unit.h"
 
+/* We use the same limit here that PID 1 bumps RLIMIT_MEMLOCK to if it can */
+#define CAN_MEMLOCK_SIZE (64U*1024U*1024U)
+
+static bool can_memlock(void) {
+        void *p;
+        bool b;
+
+        /* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against
+         * RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we
+         * cannot. Why not check RLIMIT_MEMLOCK explicitly? Because in container environments the
+         * RLIMIT_MEMLOCK value we see might not match the RLIMIT_MEMLOCK value actually in effect. */
+
+        p = mmap(NULL, CAN_MEMLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
+        if (p == MAP_FAILED)
+                return false;
+
+        b = mlock(p, CAN_MEMLOCK_SIZE) >= 0;
+        if (b)
+                assert_se(munlock(p, CAN_MEMLOCK_SIZE) >= 0);
+
+        assert_se(munmap(p, CAN_MEMLOCK_SIZE) >= 0);
+        return b;
+}
+
 int main(int argc, char *argv[]) {
         struct bpf_insn exit_insn[] = {
                 BPF_MOV64_IMM(BPF_REG_0, 1),
@@ -26,6 +51,7 @@ int main(int argc, char *argv[]) {
         _cleanup_(manager_freep) Manager *m = NULL;
         Unit *u;
         char log_buf[65535];
+        struct rlimit rl;
         int r;
 
         test_setup_logging(LOG_DEBUG);
@@ -33,6 +59,13 @@ int main(int argc, char *argv[]) {
         if (is_run_on_travis_ci())
                 return log_tests_skipped("test-bpf fails on Travis CI: https://github.com/systemd/systemd/issues/9666");
 
+        assert_se(getrlimit(RLIMIT_MEMLOCK, &rl) >= 0);
+        rl.rlim_cur = rl.rlim_max = MAX3(rl.rlim_cur, rl.rlim_max, CAN_MEMLOCK_SIZE);
+        (void) setrlimit(RLIMIT_MEMLOCK, &rl);
+
+        if (!can_memlock())
+                return log_tests_skipped("Can't use mlock(), skipping.");
+
         r = enter_cgroup_subroot();
         if (r == -ENOMEDIUM)
                 return log_tests_skipped("cgroupfs not available");