@@ -943,28 +943,33 @@ static bool vxlan_snoop(struct net_device *dev,
943943static bool vxlan_group_used (struct vxlan_net * vn , struct vxlan_dev * dev )
944944{
945945 struct vxlan_dev * vxlan ;
946+ struct vxlan_sock * sock4 ;
947+ struct vxlan_sock * sock6 = NULL ;
946948 unsigned short family = dev -> default_dst .remote_ip .sa .sa_family ;
947949
950+ sock4 = rtnl_dereference (dev -> vn4_sock );
951+
948952 /* The vxlan_sock is only used by dev, leaving group has
949953 * no effect on other vxlan devices.
950954 */
951- if (family == AF_INET && dev -> vn4_sock &&
952- atomic_read (& dev -> vn4_sock -> refcnt ) == 1 )
955+ if (family == AF_INET && sock4 && atomic_read (& sock4 -> refcnt ) == 1 )
953956 return false;
954957#if IS_ENABLED (CONFIG_IPV6 )
955- if ( family == AF_INET6 && dev -> vn6_sock &&
956- atomic_read (& dev -> vn6_sock -> refcnt ) == 1 )
958+ sock6 = rtnl_dereference ( dev -> vn6_sock );
959+ if ( family == AF_INET6 && sock6 && atomic_read (& sock6 -> refcnt ) == 1 )
957960 return false;
958961#endif
959962
960963 list_for_each_entry (vxlan , & vn -> vxlan_list , next ) {
961964 if (!netif_running (vxlan -> dev ) || vxlan == dev )
962965 continue ;
963966
964- if (family == AF_INET && vxlan -> vn4_sock != dev -> vn4_sock )
967+ if (family == AF_INET &&
968+ rtnl_dereference (vxlan -> vn4_sock ) != sock4 )
965969 continue ;
966970#if IS_ENABLED (CONFIG_IPV6 )
967- if (family == AF_INET6 && vxlan -> vn6_sock != dev -> vn6_sock )
971+ if (family == AF_INET6 &&
972+ rtnl_dereference (vxlan -> vn6_sock ) != sock6 )
968973 continue ;
969974#endif
970975
@@ -1005,22 +1010,25 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)
10051010
10061011static void vxlan_sock_release (struct vxlan_dev * vxlan )
10071012{
1008- bool ipv4 = __vxlan_sock_release_prep (vxlan -> vn4_sock );
1013+ struct vxlan_sock * sock4 = rtnl_dereference (vxlan -> vn4_sock );
10091014#if IS_ENABLED (CONFIG_IPV6 )
1010- bool ipv6 = __vxlan_sock_release_prep (vxlan -> vn6_sock );
1015+ struct vxlan_sock * sock6 = rtnl_dereference (vxlan -> vn6_sock );
1016+
1017+ rcu_assign_pointer (vxlan -> vn6_sock , NULL );
10111018#endif
10121019
1020+ rcu_assign_pointer (vxlan -> vn4_sock , NULL );
10131021 synchronize_net ();
10141022
1015- if (ipv4 ) {
1016- udp_tunnel_sock_release (vxlan -> vn4_sock -> sock );
1017- kfree (vxlan -> vn4_sock );
1023+ if (__vxlan_sock_release_prep ( sock4 ) ) {
1024+ udp_tunnel_sock_release (sock4 -> sock );
1025+ kfree (sock4 );
10181026 }
10191027
10201028#if IS_ENABLED (CONFIG_IPV6 )
1021- if (ipv6 ) {
1022- udp_tunnel_sock_release (vxlan -> vn6_sock -> sock );
1023- kfree (vxlan -> vn6_sock );
1029+ if (__vxlan_sock_release_prep ( sock6 ) ) {
1030+ udp_tunnel_sock_release (sock6 -> sock );
1031+ kfree (sock6 );
10241032 }
10251033#endif
10261034}
@@ -1036,18 +1044,21 @@ static int vxlan_igmp_join(struct vxlan_dev *vxlan)
10361044 int ret = - EINVAL ;
10371045
10381046 if (ip -> sa .sa_family == AF_INET ) {
1047+ struct vxlan_sock * sock4 = rtnl_dereference (vxlan -> vn4_sock );
10391048 struct ip_mreqn mreq = {
10401049 .imr_multiaddr .s_addr = ip -> sin .sin_addr .s_addr ,
10411050 .imr_ifindex = ifindex ,
10421051 };
10431052
1044- sk = vxlan -> vn4_sock -> sock -> sk ;
1053+ sk = sock4 -> sock -> sk ;
10451054 lock_sock (sk );
10461055 ret = ip_mc_join_group (sk , & mreq );
10471056 release_sock (sk );
10481057#if IS_ENABLED (CONFIG_IPV6 )
10491058 } else {
1050- sk = vxlan -> vn6_sock -> sock -> sk ;
1059+ struct vxlan_sock * sock6 = rtnl_dereference (vxlan -> vn6_sock );
1060+
1061+ sk = sock6 -> sock -> sk ;
10511062 lock_sock (sk );
10521063 ret = ipv6_stub -> ipv6_sock_mc_join (sk , ifindex ,
10531064 & ip -> sin6 .sin6_addr );
@@ -1067,18 +1078,21 @@ static int vxlan_igmp_leave(struct vxlan_dev *vxlan)
10671078 int ret = - EINVAL ;
10681079
10691080 if (ip -> sa .sa_family == AF_INET ) {
1081+ struct vxlan_sock * sock4 = rtnl_dereference (vxlan -> vn4_sock );
10701082 struct ip_mreqn mreq = {
10711083 .imr_multiaddr .s_addr = ip -> sin .sin_addr .s_addr ,
10721084 .imr_ifindex = ifindex ,
10731085 };
10741086
1075- sk = vxlan -> vn4_sock -> sock -> sk ;
1087+ sk = sock4 -> sock -> sk ;
10761088 lock_sock (sk );
10771089 ret = ip_mc_leave_group (sk , & mreq );
10781090 release_sock (sk );
10791091#if IS_ENABLED (CONFIG_IPV6 )
10801092 } else {
1081- sk = vxlan -> vn6_sock -> sock -> sk ;
1093+ struct vxlan_sock * sock6 = rtnl_dereference (vxlan -> vn6_sock );
1094+
1095+ sk = sock6 -> sock -> sk ;
10821096 lock_sock (sk );
10831097 ret = ipv6_stub -> ipv6_sock_mc_drop (sk , ifindex ,
10841098 & ip -> sin6 .sin6_addr );
@@ -1828,11 +1842,15 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
18281842 struct dst_cache * dst_cache ,
18291843 const struct ip_tunnel_info * info )
18301844{
1845+ struct vxlan_sock * sock6 = rcu_dereference (vxlan -> vn6_sock );
18311846 bool use_cache = ip_tunnel_dst_cache_usable (skb , info );
18321847 struct dst_entry * ndst ;
18331848 struct flowi6 fl6 ;
18341849 int err ;
18351850
1851+ if (!sock6 )
1852+ return ERR_PTR (- EIO );
1853+
18361854 if (tos && !info )
18371855 use_cache = false;
18381856 if (use_cache ) {
@@ -1850,7 +1868,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
18501868 fl6 .flowi6_proto = IPPROTO_UDP ;
18511869
18521870 err = ipv6_stub -> ipv6_dst_lookup (vxlan -> net ,
1853- vxlan -> vn6_sock -> sock -> sk ,
1871+ sock6 -> sock -> sk ,
18541872 & ndst , & fl6 );
18551873 if (err < 0 )
18561874 return ERR_PTR (err );
@@ -1995,9 +2013,11 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
19952013 }
19962014
19972015 if (dst -> sa .sa_family == AF_INET ) {
1998- if (!vxlan -> vn4_sock )
2016+ struct vxlan_sock * sock4 = rcu_dereference (vxlan -> vn4_sock );
2017+
2018+ if (!sock4 )
19992019 goto drop ;
2000- sk = vxlan -> vn4_sock -> sock -> sk ;
2020+ sk = sock4 -> sock -> sk ;
20012021
20022022 rt = vxlan_get_route (vxlan , skb ,
20032023 rdst ? rdst -> remote_ifindex : 0 , tos ,
@@ -2050,12 +2070,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
20502070 src_port , dst_port , xnet , !udp_sum );
20512071#if IS_ENABLED (CONFIG_IPV6 )
20522072 } else {
2073+ struct vxlan_sock * sock6 = rcu_dereference (vxlan -> vn6_sock );
20532074 struct dst_entry * ndst ;
20542075 u32 rt6i_flags ;
20552076
2056- if (!vxlan -> vn6_sock )
2077+ if (!sock6 )
20572078 goto drop ;
2058- sk = vxlan -> vn6_sock -> sock -> sk ;
2079+ sk = sock6 -> sock -> sk ;
20592080
20602081 ndst = vxlan6_get_route (vxlan , skb ,
20612082 rdst ? rdst -> remote_ifindex : 0 , tos ,
@@ -2415,9 +2436,10 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
24152436 dport = info -> key .tp_dst ? : vxlan -> cfg .dst_port ;
24162437
24172438 if (ip_tunnel_info_af (info ) == AF_INET ) {
2439+ struct vxlan_sock * sock4 = rcu_dereference (vxlan -> vn4_sock );
24182440 struct rtable * rt ;
24192441
2420- if (!vxlan -> vn4_sock )
2442+ if (!sock4 )
24212443 return - EINVAL ;
24222444 rt = vxlan_get_route (vxlan , skb , 0 , info -> key .tos ,
24232445 info -> key .u .ipv4 .dst ,
@@ -2429,8 +2451,6 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
24292451#if IS_ENABLED (CONFIG_IPV6 )
24302452 struct dst_entry * ndst ;
24312453
2432- if (!vxlan -> vn6_sock )
2433- return - EINVAL ;
24342454 ndst = vxlan6_get_route (vxlan , skb , 0 , info -> key .tos ,
24352455 info -> key .label , & info -> key .u .ipv6 .dst ,
24362456 & info -> key .u .ipv6 .src , NULL , info );
@@ -2740,10 +2760,10 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
27402760 return PTR_ERR (vs );
27412761#if IS_ENABLED (CONFIG_IPV6 )
27422762 if (ipv6 )
2743- vxlan -> vn6_sock = vs ;
2763+ rcu_assign_pointer ( vxlan -> vn6_sock , vs ) ;
27442764 else
27452765#endif
2746- vxlan -> vn4_sock = vs ;
2766+ rcu_assign_pointer ( vxlan -> vn4_sock , vs ) ;
27472767 vxlan_vs_add_dev (vs , vxlan );
27482768 return 0 ;
27492769}
@@ -2754,9 +2774,9 @@ static int vxlan_sock_add(struct vxlan_dev *vxlan)
27542774 bool metadata = vxlan -> flags & VXLAN_F_COLLECT_METADATA ;
27552775 int ret = 0 ;
27562776
2757- vxlan -> vn4_sock = NULL ;
2777+ RCU_INIT_POINTER ( vxlan -> vn4_sock , NULL ) ;
27582778#if IS_ENABLED (CONFIG_IPV6 )
2759- vxlan -> vn6_sock = NULL ;
2779+ RCU_INIT_POINTER ( vxlan -> vn6_sock , NULL ) ;
27602780 if (ipv6 || metadata )
27612781 ret = __vxlan_sock_add (vxlan , true);
27622782#endif
0 commit comments