]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add RestrictNetworkInterfaces= BPF program source code
authorMauricio Vásquez <mauricio@kinvolk.io>
Thu, 21 Jan 2021 15:45:38 +0000 (10:45 -0500)
committerMauricio Vásquez <mauricio@kinvolk.io>
Wed, 18 Aug 2021 20:55:53 +0000 (15:55 -0500)
The code is composed by two BPF_PROG_TYPE_CGROUP_SKB programs that
are loaded in the cgroup inet ingress and egress hooks
(BPF_CGROUP_INET_{INGRESS|EGRESS}).

The decision to let a packet pass or not is based on a map that contains
the indexes of the interfaces.

Signed-off-by: Mauricio Vásquez <mauricio@kinvolk.io>
src/core/bpf/restrict_ifaces/meson.build [new file with mode: 0644]
src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c [new file with mode: 0644]
src/core/meson.build

diff --git a/src/core/bpf/restrict_ifaces/meson.build b/src/core/bpf/restrict_ifaces/meson.build
new file mode 100644 (file)
index 0000000..5bf024d
--- /dev/null
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+if conf.get('BPF_FRAMEWORK') == 1
+        restrict_ifaces_skel_h = custom_target(
+                'restrict-ifaces.skel.h',
+                input : 'restrict-ifaces.bpf.c',
+                output : 'restrict-ifaces.skel.h',
+                command : [build_bpf_skel_py,
+                           '--clang_exec', clang.path(),
+                           '--llvm_strip_exec', llvm_strip.path(),
+                           '--bpftool_exec', bpftool.path(),
+                           '--arch', host_machine.cpu_family(),
+                           '@INPUT@', '@OUTPUT@'])
+endif
diff --git a/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c b/src/core/bpf/restrict_ifaces/restrict-ifaces.bpf.c
new file mode 100644 (file)
index 0000000..347a3a8
--- /dev/null
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* <linux/bpf.h> must precede <bpf/bpf_helpers.h> due to integer types
+ * in bpf helpers signatures.
+ */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+const volatile __u8 is_allow_list = 0;
+
+/* Map containing the network interfaces indexes.
+ * The interpretation of the map depends on the value of is_allow_list.
+ */
+struct {
+        __uint(type, BPF_MAP_TYPE_HASH);
+        __type(key, __u32);
+        __type(value, __u8);
+} sd_restrictif SEC(".maps");
+
+#define DROP 0
+#define PASS 1
+
+static inline int restrict_network_interfaces_impl(const struct __sk_buff *sk) {
+        __u32 zero = 0, ifindex;
+        __u8 *lookup_result;
+
+        ifindex = sk->ifindex;
+        lookup_result = bpf_map_lookup_elem(&sd_restrictif, &ifindex);
+        if (is_allow_list) {
+                /* allow-list: let the packet pass if iface in the list */
+                if (lookup_result)
+                        return PASS;
+        } else {
+            /* deny-list: let the packet pass if iface *not* in the list */
+                if (!lookup_result)
+                        return PASS;
+        }
+
+        return DROP;
+}
+
+SEC("cgroup_skb/egress")
+int sd_restrictif_e(const struct __sk_buff *sk) {
+        return restrict_network_interfaces_impl(sk);
+}
+
+SEC("cgroup_skb/ingress")
+int sd_restrictif_i(const struct __sk_buff *sk) {
+        return restrict_network_interfaces_impl(sk);
+}
+
+static const char _license[] SEC("license") = "LGPL-2.1-or-later";
index 1941081972bf5ed172688549f87688594ba79a9d..df773b6675f883f98b579fa2ac75297b46cfe8b3 100644 (file)
@@ -136,6 +136,11 @@ if conf.get('BPF_FRAMEWORK') == 1
         libcore_sources += [socket_bind_skel_h]
 endif
 
+subdir('bpf/restrict_ifaces')
+if conf.get('BPF_FRAMEWORK') == 1
+        libcore_sources += [restrict_ifaces_skel_h]
+endif
+
 load_fragment_gperf_gperf = custom_target(
         'load-fragment-gperf.gperf',
         input : 'load-fragment-gperf.gperf.in',