@@ -787,7 +787,8 @@ static void tun_detach_all(struct net_device *dev)
787
787
}
788
788
789
789
static int tun_attach (struct tun_struct * tun , struct file * file ,
790
- bool skip_filter , bool napi , bool napi_frags )
790
+ bool skip_filter , bool napi , bool napi_frags ,
791
+ bool publish_tun )
791
792
{
792
793
struct tun_file * tfile = file -> private_data ;
793
794
struct net_device * dev = tun -> dev ;
@@ -870,7 +871,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
870
871
* initialized tfile; otherwise we risk using half-initialized
871
872
* object.
872
873
*/
873
- rcu_assign_pointer (tfile -> tun , tun );
874
+ if (publish_tun )
875
+ rcu_assign_pointer (tfile -> tun , tun );
874
876
rcu_assign_pointer (tun -> tfiles [tun -> numqueues ], tfile );
875
877
tun -> numqueues ++ ;
876
878
tun_set_real_num_queues (tun );
@@ -2730,7 +2732,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
2730
2732
2731
2733
err = tun_attach (tun , file , ifr -> ifr_flags & IFF_NOFILTER ,
2732
2734
ifr -> ifr_flags & IFF_NAPI ,
2733
- ifr -> ifr_flags & IFF_NAPI_FRAGS );
2735
+ ifr -> ifr_flags & IFF_NAPI_FRAGS , true );
2734
2736
if (err < 0 )
2735
2737
return err ;
2736
2738
@@ -2829,13 +2831,17 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
2829
2831
2830
2832
INIT_LIST_HEAD (& tun -> disabled );
2831
2833
err = tun_attach (tun , file , false, ifr -> ifr_flags & IFF_NAPI ,
2832
- ifr -> ifr_flags & IFF_NAPI_FRAGS );
2834
+ ifr -> ifr_flags & IFF_NAPI_FRAGS , false );
2833
2835
if (err < 0 )
2834
2836
goto err_free_flow ;
2835
2837
2836
2838
err = register_netdevice (tun -> dev );
2837
2839
if (err < 0 )
2838
2840
goto err_detach ;
2841
+ /* free_netdev() won't check refcnt, to aovid race
2842
+ * with dev_put() we need publish tun after registration.
2843
+ */
2844
+ rcu_assign_pointer (tfile -> tun , tun );
2839
2845
}
2840
2846
2841
2847
netif_carrier_on (tun -> dev );
@@ -2978,7 +2984,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
2978
2984
if (ret < 0 )
2979
2985
goto unlock ;
2980
2986
ret = tun_attach (tun , file , false, tun -> flags & IFF_NAPI ,
2981
- tun -> flags & IFF_NAPI_FRAGS );
2987
+ tun -> flags & IFF_NAPI_FRAGS , true );
2982
2988
} else if (ifr -> ifr_flags & IFF_DETACH_QUEUE ) {
2983
2989
tun = rtnl_dereference (tfile -> tun );
2984
2990
if (!tun || !(tun -> flags & IFF_MULTI_QUEUE ) || tfile -> detached )
0 commit comments