Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

af_packet: lock imbalance

fanout_add() might return with fanout_mutex held.

Reduce indentation level while we are at it

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
afe62c68 68ac3191

+32 -32
+32 -32
net/packet/af_packet.c
··· 589 589 break; 590 590 } 591 591 } 592 + err = -EINVAL; 592 593 if (match && match->defrag != defrag) 593 - return -EINVAL; 594 + goto out; 594 595 if (!match) { 596 + err = -ENOMEM; 595 597 match = kzalloc(sizeof(*match), GFP_KERNEL); 596 - if (match) { 597 - write_pnet(&match->net, sock_net(sk)); 598 - match->id = id; 599 - match->type = type; 600 - match->defrag = defrag; 601 - atomic_set(&match->rr_cur, 0); 602 - INIT_LIST_HEAD(&match->list); 603 - spin_lock_init(&match->lock); 604 - atomic_set(&match->sk_ref, 0); 605 - match->prot_hook.type = po->prot_hook.type; 606 - match->prot_hook.dev = po->prot_hook.dev; 607 - match->prot_hook.func = packet_rcv_fanout; 608 - match->prot_hook.af_packet_priv = match; 609 - dev_add_pack(&match->prot_hook); 610 - list_add(&match->list, &fanout_list); 598 + if (!match) 599 + goto out; 600 + write_pnet(&match->net, sock_net(sk)); 601 + match->id = id; 602 + match->type = type; 603 + match->defrag = defrag; 604 + atomic_set(&match->rr_cur, 0); 605 + INIT_LIST_HEAD(&match->list); 606 + spin_lock_init(&match->lock); 607 + atomic_set(&match->sk_ref, 0); 608 + match->prot_hook.type = po->prot_hook.type; 609 + match->prot_hook.dev = po->prot_hook.dev; 610 + match->prot_hook.func = packet_rcv_fanout; 611 + match->prot_hook.af_packet_priv = match; 612 + dev_add_pack(&match->prot_hook); 613 + list_add(&match->list, &fanout_list); 614 + } 615 + err = -EINVAL; 616 + if (match->type == type && 617 + match->prot_hook.type == po->prot_hook.type && 618 + match->prot_hook.dev == po->prot_hook.dev) { 619 + err = -ENOSPC; 620 + if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) { 621 + __dev_remove_pack(&po->prot_hook); 622 + po->fanout = match; 623 + atomic_inc(&match->sk_ref); 624 + __fanout_link(sk, po); 625 + err = 0; 611 626 } 612 627 } 613 - err = -ENOMEM; 614 - if (match) { 615 - err = -EINVAL; 616 - if (match->type == type && 617 - match->prot_hook.type == po->prot_hook.type && 618 - match->prot_hook.dev == po->prot_hook.dev) { 619 - err = -ENOSPC; 620 - if (atomic_read(&match->sk_ref) < PACKET_FANOUT_MAX) { 621 - __dev_remove_pack(&po->prot_hook); 622 - po->fanout = match; 623 - atomic_inc(&match->sk_ref); 624 - __fanout_link(sk, po); 625 - err = 0; 626 - } 627 - } 628 - } 628 + out: 629 629 mutex_unlock(&fanout_mutex); 630 630 return err; 631 631 }