diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 3126911f5042..58f2a5294453 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -113,6 +113,7 @@ nf_hook_entries_grow(const struct nf_hook_entries *old, alloc_entries = 1; old_entries = old ? old->num_hook_entries : 0; + mutex_lock(&nf_hook_mutex); if (old) { orig_ops = nf_hook_entries_get_hook_ops(old); @@ -129,17 +130,23 @@ nf_hook_entries_grow(const struct nf_hook_entries *old, * prevent defrag, conntrack, iptables etc from attaching). */ if (reg->priority == orig_ops[i]->priority && - reg->hook_ops_type == NF_HOOK_OP_BPF) - return ERR_PTR(-EBUSY); + reg->hook_ops_type == NF_HOOK_OP_BPF) { + new = ERR_PTR(-EBUSY); + goto unlock; + } } } - if (alloc_entries > MAX_HOOK_COUNT) - return ERR_PTR(-E2BIG); + if (alloc_entries > MAX_HOOK_COUNT) { + new = ERR_PTR(-E2BIG); + goto unlock; + } new = allocate_hook_entries_size(alloc_entries); - if (!new) - return ERR_PTR(-ENOMEM); + if (!new) { + new = ERR_PTR(-ENOMEM); + goto unlock; + } new_ops = nf_hook_entries_get_hook_ops(new); @@ -170,6 +177,8 @@ nf_hook_entries_grow(const struct nf_hook_entries *old, new->hooks[nhooks].priv = reg->priv; } +unlock: + mutex_unlock(&nf_hook_mutex); return new; } @@ -546,11 +555,13 @@ void nf_hook_entries_delete_raw(struct nf_hook_entries __rcu **pp, { struct nf_hook_entries *p; + mutex_lock(&nf_hook_mutex); p = rcu_dereference_raw(*pp); if (nf_remove_net_hook(p, reg)) { p = __nf_hook_entries_try_shrink(p, pp); nf_hook_entries_free(p); } + mutex_unlock(&nf_hook_mutex); } EXPORT_SYMBOL_GPL(nf_hook_entries_delete_raw);