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: Jakub Sitnicki <jakub@cloudflare.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Reviewed-by: Stanislav Fomichev <sdf@google.com> Link: https://lore.kernel.org/bpf/20200531082846.2117903-2-jakub@cloudflare.com
This commit is contained in:

committed by
Alexei Starovoitov

parent
febeb6dff7
commit
171526f6fe
@@ -109,15 +109,10 @@ int skb_flow_dissector_prog_query(const union bpf_attr *attr,
|
|||||||
return 0;
|
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 *prog)
|
||||||
{
|
{
|
||||||
struct bpf_prog *attached;
|
struct bpf_prog *attached;
|
||||||
struct net *net;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
net = current->nsproxy->net_ns;
|
|
||||||
mutex_lock(&flow_dissector_mutex);
|
|
||||||
|
|
||||||
if (net == &init_net) {
|
if (net == &init_net) {
|
||||||
/* BPF flow dissector in the root namespace overrides
|
/* 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) {
|
for_each_net(ns) {
|
||||||
if (ns == &init_net)
|
if (ns == &init_net)
|
||||||
continue;
|
continue;
|
||||||
if (rcu_access_pointer(ns->flow_dissector_prog)) {
|
if (rcu_access_pointer(ns->flow_dissector_prog))
|
||||||
ret = -EEXIST;
|
return -EEXIST;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Make sure root flow dissector is not attached
|
/* Make sure root flow dissector is not attached
|
||||||
* when attaching to the non-root namespace.
|
* when attaching to the non-root namespace.
|
||||||
*/
|
*/
|
||||||
if (rcu_access_pointer(init_net.flow_dissector_prog)) {
|
if (rcu_access_pointer(init_net.flow_dissector_prog))
|
||||||
ret = -EEXIST;
|
return -EEXIST;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attached = rcu_dereference_protected(net->flow_dissector_prog,
|
attached = rcu_dereference_protected(net->flow_dissector_prog,
|
||||||
lockdep_is_held(&flow_dissector_mutex));
|
lockdep_is_held(&flow_dissector_mutex));
|
||||||
if (attached == prog) {
|
if (attached == prog)
|
||||||
/* The same program cannot be attached twice */
|
/* The same program cannot be attached twice */
|
||||||
ret = -EINVAL;
|
return -EINVAL;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
rcu_assign_pointer(net->flow_dissector_prog, prog);
|
rcu_assign_pointer(net->flow_dissector_prog, prog);
|
||||||
if (attached)
|
if (attached)
|
||||||
bpf_prog_put(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);
|
mutex_unlock(&flow_dissector_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user