flow_dissector: Move out netns_bpf prog callbacks
authorJakub Sitnicki <jakub@cloudflare.com>
Sun, 31 May 2020 08:28:37 +0000 (10:28 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 1 Jun 2020 22:21:02 +0000 (15:21 -0700)
Move functions to manage BPF programs attached to netns that are not
specific to flow dissector to a dedicated module named
bpf/net_namespace.c.

The set of functions will grow with the addition of bpf_link support for
netns attached programs. This patch prepares ground by creating a place
for it.

This is a code move with no functional changes intended.

Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200531082846.2117903-4-jakub@cloudflare.com
include/net/flow_dissector.h
kernel/bpf/Makefile
kernel/bpf/net_namespace.c [new file with mode: 0644]
net/core/flow_dissector.c

index 4fb1a69c6ecf8ab538f6693d9d49359d663bb967..a7eba43fe4e4cab9deb228bbbff0f9dd6064ab5f 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/string.h>
 #include <uapi/linux/if_ether.h>
 
+struct bpf_prog;
+struct net;
 struct sk_buff;
 
 /**
@@ -369,4 +371,8 @@ flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
        memset(key_basic, 0, sizeof(*key_basic));
 }
 
+#ifdef CONFIG_BPF_SYSCALL
+int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog);
+#endif /* CONFIG_BPF_SYSCALL */
+
 #endif
index 8fca02f64811ef67ce8029f2db866e94adaee7bf..1131a921e1a6a062b61f0646b7ca1c684b513b9f 100644 (file)
@@ -13,6 +13,7 @@ ifeq ($(CONFIG_NET),y)
 obj-$(CONFIG_BPF_SYSCALL) += devmap.o
 obj-$(CONFIG_BPF_SYSCALL) += cpumap.o
 obj-$(CONFIG_BPF_SYSCALL) += offload.o
+obj-$(CONFIG_BPF_SYSCALL) += net_namespace.o
 endif
 ifeq ($(CONFIG_PERF_EVENTS),y)
 obj-$(CONFIG_BPF_SYSCALL) += stackmap.o
diff --git a/kernel/bpf/net_namespace.c b/kernel/bpf/net_namespace.c
new file mode 100644 (file)
index 0000000..b37d814
--- /dev/null
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include <net/net_namespace.h>
+
+/*
+ * Functions to manage BPF programs attached to netns
+ */
+
+/* Protects updates to netns_bpf */
+DEFINE_MUTEX(netns_bpf_mutex);
+
+int netns_bpf_prog_query(const union bpf_attr *attr,
+                        union bpf_attr __user *uattr)
+{
+       __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
+       u32 prog_id, prog_cnt = 0, flags = 0;
+       enum netns_bpf_attach_type type;
+       struct bpf_prog *attached;
+       struct net *net;
+
+       if (attr->query.query_flags)
+               return -EINVAL;
+
+       type = to_netns_bpf_attach_type(attr->query.attach_type);
+       if (type < 0)
+               return -EINVAL;
+
+       net = get_net_ns_by_fd(attr->query.target_fd);
+       if (IS_ERR(net))
+               return PTR_ERR(net);
+
+       rcu_read_lock();
+       attached = rcu_dereference(net->bpf.progs[type]);
+       if (attached) {
+               prog_cnt = 1;
+               prog_id = attached->aux->id;
+       }
+       rcu_read_unlock();
+
+       put_net(net);
+
+       if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
+               return -EFAULT;
+       if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
+               return -EFAULT;
+
+       if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
+               return 0;
+
+       if (copy_to_user(prog_ids, &prog_id, sizeof(u32)))
+               return -EFAULT;
+
+       return 0;
+}
+
+int netns_bpf_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
+{
+       enum netns_bpf_attach_type type;
+       struct net *net;
+       int ret;
+
+       type = to_netns_bpf_attach_type(attr->attach_type);
+       if (type < 0)
+               return -EINVAL;
+
+       net = current->nsproxy->net_ns;
+       mutex_lock(&netns_bpf_mutex);
+       switch (type) {
+       case NETNS_BPF_FLOW_DISSECTOR:
+               ret = flow_dissector_bpf_prog_attach(net, prog);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       mutex_unlock(&netns_bpf_mutex);
+
+       return ret;
+}
+
+/* Must be called with netns_bpf_mutex held. */
+static int __netns_bpf_prog_detach(struct net *net,
+                                  enum netns_bpf_attach_type type)
+{
+       struct bpf_prog *attached;
+
+       attached = rcu_dereference_protected(net->bpf.progs[type],
+                                            lockdep_is_held(&netns_bpf_mutex));
+       if (!attached)
+               return -ENOENT;
+       RCU_INIT_POINTER(net->bpf.progs[type], NULL);
+       bpf_prog_put(attached);
+       return 0;
+}
+
+int netns_bpf_prog_detach(const union bpf_attr *attr)
+{
+       enum netns_bpf_attach_type type;
+       int ret;
+
+       type = to_netns_bpf_attach_type(attr->attach_type);
+       if (type < 0)
+               return -EINVAL;
+
+       mutex_lock(&netns_bpf_mutex);
+       ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type);
+       mutex_unlock(&netns_bpf_mutex);
+
+       return ret;
+}
+
+static void __net_exit netns_bpf_pernet_pre_exit(struct net *net)
+{
+       enum netns_bpf_attach_type type;
+
+       mutex_lock(&netns_bpf_mutex);
+       for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++)
+               __netns_bpf_prog_detach(net, type);
+       mutex_unlock(&netns_bpf_mutex);
+}
+
+static struct pernet_operations netns_bpf_pernet_ops __net_initdata = {
+       .pre_exit = netns_bpf_pernet_pre_exit,
+};
+
+static int __init netns_bpf_init(void)
+{
+       return register_pernet_subsys(&netns_bpf_pernet_ops);
+}
+
+subsys_initcall(netns_bpf_init);
index 6c1b8e43d611dc5ca19c45fb588189e72ea797ca..d02df0b6d0d99ae12783f15746fbdff49b603cc7 100644 (file)
@@ -33,9 +33,6 @@
 #endif
 #include <linux/bpf-netns.h>
 
-/* Protects updates to netns_bpf */
-DEFINE_MUTEX(netns_bpf_mutex);
-
 static void dissector_set_key(struct flow_dissector *flow_dissector,
                              enum flow_dissector_key_id key_id)
 {
@@ -72,52 +69,8 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
 }
 EXPORT_SYMBOL(skb_flow_dissector_init);
 
-int netns_bpf_prog_query(const union bpf_attr *attr,
-                        union bpf_attr __user *uattr)
-{
-       __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
-       u32 prog_id, prog_cnt = 0, flags = 0;
-       enum netns_bpf_attach_type type;
-       struct bpf_prog *attached;
-       struct net *net;
-
-       if (attr->query.query_flags)
-               return -EINVAL;
-
-       type = to_netns_bpf_attach_type(attr->query.attach_type);
-       if (type < 0)
-               return -EINVAL;
-
-       net = get_net_ns_by_fd(attr->query.target_fd);
-       if (IS_ERR(net))
-               return PTR_ERR(net);
-
-       rcu_read_lock();
-       attached = rcu_dereference(net->bpf.progs[type]);
-       if (attached) {
-               prog_cnt = 1;
-               prog_id = attached->aux->id;
-       }
-       rcu_read_unlock();
-
-       put_net(net);
-
-       if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
-               return -EFAULT;
-       if (copy_to_user(&uattr->query.prog_cnt, &prog_cnt, sizeof(prog_cnt)))
-               return -EFAULT;
-
-       if (!attr->query.prog_cnt || !prog_ids || !prog_cnt)
-               return 0;
-
-       if (copy_to_user(prog_ids, &prog_id, sizeof(u32)))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int flow_dissector_bpf_prog_attach(struct net *net,
-                                         struct bpf_prog *prog)
+#ifdef CONFIG_BPF_SYSCALL
+int flow_dissector_bpf_prog_attach(struct net *net, struct bpf_prog *prog)
 {
        enum netns_bpf_attach_type type = NETNS_BPF_FLOW_DISSECTOR;
        struct bpf_prog *attached;
@@ -155,76 +108,7 @@ static int flow_dissector_bpf_prog_attach(struct net *net,
                bpf_prog_put(attached);
        return 0;
 }
-
-int netns_bpf_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
-{
-       enum netns_bpf_attach_type type;
-       struct net *net;
-       int ret;
-
-       type = to_netns_bpf_attach_type(attr->attach_type);
-       if (type < 0)
-               return -EINVAL;
-
-       net = current->nsproxy->net_ns;
-       mutex_lock(&netns_bpf_mutex);
-       switch (type) {
-       case NETNS_BPF_FLOW_DISSECTOR:
-               ret = flow_dissector_bpf_prog_attach(net, prog);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-       mutex_unlock(&netns_bpf_mutex);
-
-       return ret;
-}
-
-/* Must be called with netns_bpf_mutex held. */
-static int __netns_bpf_prog_detach(struct net *net,
-                                  enum netns_bpf_attach_type type)
-{
-       struct bpf_prog *attached;
-
-       attached = rcu_dereference_protected(net->bpf.progs[type],
-                                            lockdep_is_held(&netns_bpf_mutex));
-       if (!attached)
-               return -ENOENT;
-       RCU_INIT_POINTER(net->bpf.progs[type], NULL);
-       bpf_prog_put(attached);
-       return 0;
-}
-
-int netns_bpf_prog_detach(const union bpf_attr *attr)
-{
-       enum netns_bpf_attach_type type;
-       int ret;
-
-       type = to_netns_bpf_attach_type(attr->attach_type);
-       if (type < 0)
-               return -EINVAL;
-
-       mutex_lock(&netns_bpf_mutex);
-       ret = __netns_bpf_prog_detach(current->nsproxy->net_ns, type);
-       mutex_unlock(&netns_bpf_mutex);
-
-       return ret;
-}
-
-static void __net_exit netns_bpf_pernet_pre_exit(struct net *net)
-{
-       enum netns_bpf_attach_type type;
-
-       mutex_lock(&netns_bpf_mutex);
-       for (type = 0; type < MAX_NETNS_BPF_ATTACH_TYPE; type++)
-               __netns_bpf_prog_detach(net, type);
-       mutex_unlock(&netns_bpf_mutex);
-}
-
-static struct pernet_operations netns_bpf_pernet_ops __net_initdata = {
-       .pre_exit = netns_bpf_pernet_pre_exit,
-};
+#endif /* CONFIG_BPF_SYSCALL */
 
 /**
  * __skb_flow_get_ports - extract the upper layer ports and return them
@@ -1902,7 +1786,6 @@ static int __init init_default_flow_dissectors(void)
        skb_flow_dissector_init(&flow_keys_basic_dissector,
                                flow_keys_basic_dissector_keys,
                                ARRAY_SIZE(flow_keys_basic_dissector_keys));
-
-       return register_pernet_subsys(&netns_bpf_pernet_ops);
+       return 0;
 }
 core_initcall(init_default_flow_dissectors);