Commit afe62c68 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

af_packet: lock imbalance

fanout_add() might return with fanout_mutex held.

Reduce indentation level while we are at it
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 68ac3191
...@@ -589,43 +589,43 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) ...@@ -589,43 +589,43 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
break; break;
} }
} }
err = -EINVAL;
if (match && match->defrag != defrag) if (match && match->defrag != defrag)
return -EINVAL; goto out;
if (!match) { if (!match) {
err = -ENOMEM;
match = kzalloc(sizeof(*match), GFP_KERNEL); match = kzalloc(sizeof(*match), GFP_KERNEL);
if (match) { if (!match)
write_pnet(&match->net, sock_net(sk)); goto out;
match->id = id; write_pnet(&match->net, sock_net(sk));
match->type = type; match->id = id;
match->defrag = defrag; match->type = type;
atomic_set(&match->rr_cur, 0); match->defrag = defrag;
INIT_LIST_HEAD(&match->list); atomic_set(&match->rr_cur, 0);
spin_lock_init(&match->lock); INIT_LIST_HEAD(&match->list);
atomic_set(&match->sk_ref, 0); spin_lock_init(&match->lock);
match->prot_hook.type = po->prot_hook.type; atomic_set(&match->sk_ref, 0);
match->prot_hook.dev = po->prot_hook.dev; match->prot_hook.type = po->prot_hook.type;
match->prot_hook.func = packet_rcv_fanout; match->prot_hook.dev = po->prot_hook.dev;
match->prot_hook.af_packet_priv = match; match->prot_hook.func = packet_rcv_fanout;
dev_add_pack(&match->prot_hook); match->prot_hook.af_packet_priv = match;
list_add(&match->list, &fanout_list); dev_add_pack(&match->prot_hook);
} list_add(&match->list, &fanout_list);
} }
err = -ENOMEM; err = -EINVAL;
if (match) { if (match->type == type &&
err = -EINVAL; match->prot_hook.type == po->prot_hook.type &&
if (match->type == type && match->prot_hook.dev == po->prot_hook.dev) {
match->prot_hook.type == po->prot_hook.type && err = -ENOSPC;
match->prot_hook.dev == po->prot_hook.dev) { if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) {
err = -ENOSPC; __dev_remove_pack(&po->prot_hook);
if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) { po->fanout = match;
__dev_remove_pack(&po->prot_hook); atomic_inc(&match->sk_ref);
po->fanout = match; __fanout_link(sk, po);
atomic_inc(&match->sk_ref); err = 0;
__fanout_link(sk, po);
err = 0;
}
} }
} }
out:
mutex_unlock(&fanout_mutex); mutex_unlock(&fanout_mutex);
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment