@@ -1497,6 +1497,8 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po)
1497
1497
f -> arr [f -> num_members ] = sk ;
1498
1498
smp_wmb ();
1499
1499
f -> num_members ++ ;
1500
+ if (f -> num_members == 1 )
1501
+ dev_add_pack (& f -> prot_hook );
1500
1502
spin_unlock (& f -> lock );
1501
1503
}
1502
1504
@@ -1513,6 +1515,8 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
1513
1515
BUG_ON (i >= f -> num_members );
1514
1516
f -> arr [i ] = f -> arr [f -> num_members - 1 ];
1515
1517
f -> num_members -- ;
1518
+ if (f -> num_members == 0 )
1519
+ __dev_remove_pack (& f -> prot_hook );
1516
1520
spin_unlock (& f -> lock );
1517
1521
}
1518
1522
@@ -1693,7 +1697,6 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1693
1697
match -> prot_hook .func = packet_rcv_fanout ;
1694
1698
match -> prot_hook .af_packet_priv = match ;
1695
1699
match -> prot_hook .id_match = match_fanout_group ;
1696
- dev_add_pack (& match -> prot_hook );
1697
1700
list_add (& match -> list , & fanout_list );
1698
1701
}
1699
1702
err = - EINVAL ;
@@ -1718,7 +1721,12 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
1718
1721
return err ;
1719
1722
}
1720
1723
1721
- static void fanout_release (struct sock * sk )
1724
+ /* If pkt_sk(sk)->fanout->sk_ref is zero, this function removes
1725
+ * pkt_sk(sk)->fanout from fanout_list and returns pkt_sk(sk)->fanout.
1726
+ * It is the responsibility of the caller to call fanout_release_data() and
1727
+ * free the returned packet_fanout (after synchronize_net())
1728
+ */
1729
+ static struct packet_fanout * fanout_release (struct sock * sk )
1722
1730
{
1723
1731
struct packet_sock * po = pkt_sk (sk );
1724
1732
struct packet_fanout * f ;
@@ -1728,17 +1736,17 @@ static void fanout_release(struct sock *sk)
1728
1736
if (f ) {
1729
1737
po -> fanout = NULL ;
1730
1738
1731
- if (atomic_dec_and_test (& f -> sk_ref )) {
1739
+ if (atomic_dec_and_test (& f -> sk_ref ))
1732
1740
list_del (& f -> list );
1733
- dev_remove_pack (& f -> prot_hook );
1734
- fanout_release_data (f );
1735
- kfree (f );
1736
- }
1741
+ else
1742
+ f = NULL ;
1737
1743
1738
1744
if (po -> rollover )
1739
1745
kfree_rcu (po -> rollover , rcu );
1740
1746
}
1741
1747
mutex_unlock (& fanout_mutex );
1748
+
1749
+ return f ;
1742
1750
}
1743
1751
1744
1752
static bool packet_extra_vlan_len_allowed (const struct net_device * dev ,
@@ -2912,6 +2920,7 @@ static int packet_release(struct socket *sock)
2912
2920
{
2913
2921
struct sock * sk = sock -> sk ;
2914
2922
struct packet_sock * po ;
2923
+ struct packet_fanout * f ;
2915
2924
struct net * net ;
2916
2925
union tpacket_req_u req_u ;
2917
2926
@@ -2951,9 +2960,14 @@ static int packet_release(struct socket *sock)
2951
2960
packet_set_ring (sk , & req_u , 1 , 1 );
2952
2961
}
2953
2962
2954
- fanout_release (sk );
2963
+ f = fanout_release (sk );
2955
2964
2956
2965
synchronize_net ();
2966
+
2967
+ if (f ) {
2968
+ fanout_release_data (f );
2969
+ kfree (f );
2970
+ }
2957
2971
/*
2958
2972
* Now the socket is dead. No more input will appear.
2959
2973
*/
@@ -3905,7 +3919,6 @@ static int packet_notifier(struct notifier_block *this,
3905
3919
}
3906
3920
if (msg == NETDEV_UNREGISTER ) {
3907
3921
packet_cached_dev_reset (po );
3908
- fanout_release (sk );
3909
3922
po -> ifindex = -1 ;
3910
3923
if (po -> prot_hook .dev )
3911
3924
dev_put (po -> prot_hook .dev );
0 commit comments