Commit 171526f6 authored by Jakub Sitnicki's avatar Jakub Sitnicki Committed by Alexei Starovoitov
Browse files

flow_dissector: Pull locking up from prog attach callback



Split out the part of attach callback that happens with attach/detach lock
acquired. This structures the prog attach callback in a way that opens up
doors for moving the locking out of flow_dissector and into generic
callbacks for attaching/detaching progs to netns in subsequent patches.

Signed-off-by: default avatarJakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Reviewed-by: default avatarStanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/bpf/20200531082846.2117903-2-jakub@cloudflare.com
parent febeb6df
Loading
Loading
Loading
Loading
+20 −20
Original line number Diff line number Diff line
@@ -109,15 +109,10 @@ int skb_flow_dissector_prog_query(const union bpf_attr *attr,
	return 0;
}

int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
static int flow_dissector_bpf_prog_attach(struct net *net,
					  struct bpf_prog *prog)
{
	struct bpf_prog *attached;
	struct net *net;
	int ret = 0;

	net = current->nsproxy->net_ns;
	mutex_lock(&flow_dissector_mutex);

	if (net == &init_net) {
		/* BPF flow dissector in the root namespace overrides
@@ -130,33 +125,38 @@ int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
		for_each_net(ns) {
			if (ns == &init_net)
				continue;
			if (rcu_access_pointer(ns->flow_dissector_prog)) {
				ret = -EEXIST;
				goto out;
			}
			if (rcu_access_pointer(ns->flow_dissector_prog))
				return -EEXIST;
		}
	} else {
		/* Make sure root flow dissector is not attached
		 * when attaching to the non-root namespace.
		 */
		if (rcu_access_pointer(init_net.flow_dissector_prog)) {
			ret = -EEXIST;
			goto out;
		}
		if (rcu_access_pointer(init_net.flow_dissector_prog))
			return -EEXIST;
	}

	attached = rcu_dereference_protected(net->flow_dissector_prog,
					     lockdep_is_held(&flow_dissector_mutex));
	if (attached == prog) {
	if (attached == prog)
		/* The same program cannot be attached twice */
		ret = -EINVAL;
		goto out;
	}
		return -EINVAL;

	rcu_assign_pointer(net->flow_dissector_prog, prog);
	if (attached)
		bpf_prog_put(attached);
out:
	return 0;
}

int skb_flow_dissector_bpf_prog_attach(const union bpf_attr *attr,
				       struct bpf_prog *prog)
{
	int ret;

	mutex_lock(&flow_dissector_mutex);
	ret = flow_dissector_bpf_prog_attach(current->nsproxy->net_ns, prog);
	mutex_unlock(&flow_dissector_mutex);

	return ret;
}