@@ -713,34 +713,37 @@ static void check_lifetime(struct work_struct *work)
713
713
714
714
rcu_read_lock ();
715
715
hlist_for_each_entry_rcu (ifa , & inet_addr_lst [i ], hash ) {
716
- unsigned long age ;
716
+ unsigned long age , tstamp ;
717
+ u32 preferred_lft ;
718
+ u32 valid_lft ;
719
+ u32 flags ;
717
720
718
- if (ifa -> ifa_flags & IFA_F_PERMANENT )
721
+ flags = READ_ONCE (ifa -> ifa_flags );
722
+ if (flags & IFA_F_PERMANENT )
719
723
continue ;
720
724
725
+ preferred_lft = READ_ONCE (ifa -> ifa_preferred_lft );
726
+ valid_lft = READ_ONCE (ifa -> ifa_valid_lft );
727
+ tstamp = READ_ONCE (ifa -> ifa_tstamp );
721
728
/* We try to batch several events at once. */
722
- age = (now - ifa -> ifa_tstamp +
729
+ age = (now - tstamp +
723
730
ADDRCONF_TIMER_FUZZ_MINUS ) / HZ ;
724
731
725
- if (ifa -> ifa_valid_lft != INFINITY_LIFE_TIME &&
726
- age >= ifa -> ifa_valid_lft ) {
732
+ if (valid_lft != INFINITY_LIFE_TIME &&
733
+ age >= valid_lft ) {
727
734
change_needed = true;
728
- } else if (ifa -> ifa_preferred_lft ==
735
+ } else if (preferred_lft ==
729
736
INFINITY_LIFE_TIME ) {
730
737
continue ;
731
- } else if (age >= ifa -> ifa_preferred_lft ) {
732
- if (time_before (ifa -> ifa_tstamp +
733
- ifa -> ifa_valid_lft * HZ , next ))
734
- next = ifa -> ifa_tstamp +
735
- ifa -> ifa_valid_lft * HZ ;
738
+ } else if (age >= preferred_lft ) {
739
+ if (time_before (tstamp + valid_lft * HZ , next ))
740
+ next = tstamp + valid_lft * HZ ;
736
741
737
- if (!(ifa -> ifa_flags & IFA_F_DEPRECATED ))
742
+ if (!(flags & IFA_F_DEPRECATED ))
738
743
change_needed = true;
739
- } else if (time_before (ifa -> ifa_tstamp +
740
- ifa -> ifa_preferred_lft * HZ ,
744
+ } else if (time_before (tstamp + preferred_lft * HZ ,
741
745
next )) {
742
- next = ifa -> ifa_tstamp +
743
- ifa -> ifa_preferred_lft * HZ ;
746
+ next = tstamp + preferred_lft * HZ ;
744
747
}
745
748
}
746
749
rcu_read_unlock ();
@@ -804,24 +807,26 @@ static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
804
807
__u32 prefered_lft )
805
808
{
806
809
unsigned long timeout ;
810
+ u32 flags ;
807
811
808
- ifa -> ifa_flags &= ~(IFA_F_PERMANENT | IFA_F_DEPRECATED );
812
+ flags = ifa -> ifa_flags & ~(IFA_F_PERMANENT | IFA_F_DEPRECATED );
809
813
810
814
timeout = addrconf_timeout_fixup (valid_lft , HZ );
811
815
if (addrconf_finite_timeout (timeout ))
812
- ifa -> ifa_valid_lft = timeout ;
816
+ WRITE_ONCE ( ifa -> ifa_valid_lft , timeout ) ;
813
817
else
814
- ifa -> ifa_flags |= IFA_F_PERMANENT ;
818
+ flags |= IFA_F_PERMANENT ;
815
819
816
820
timeout = addrconf_timeout_fixup (prefered_lft , HZ );
817
821
if (addrconf_finite_timeout (timeout )) {
818
822
if (timeout == 0 )
819
- ifa -> ifa_flags |= IFA_F_DEPRECATED ;
820
- ifa -> ifa_preferred_lft = timeout ;
823
+ flags |= IFA_F_DEPRECATED ;
824
+ WRITE_ONCE ( ifa -> ifa_preferred_lft , timeout ) ;
821
825
}
822
- ifa -> ifa_tstamp = jiffies ;
826
+ WRITE_ONCE (ifa -> ifa_flags , flags );
827
+ WRITE_ONCE (ifa -> ifa_tstamp , jiffies );
823
828
if (!ifa -> ifa_cstamp )
824
- ifa -> ifa_cstamp = ifa -> ifa_tstamp ;
829
+ WRITE_ONCE ( ifa -> ifa_cstamp , ifa -> ifa_tstamp ) ;
825
830
}
826
831
827
832
static struct in_ifaddr * rtm_to_ifaddr (struct net * net , struct nlmsghdr * nlh ,
@@ -1312,7 +1317,7 @@ static __be32 in_dev_select_addr(const struct in_device *in_dev,
1312
1317
const struct in_ifaddr * ifa ;
1313
1318
1314
1319
in_dev_for_each_ifa_rcu (ifa , in_dev ) {
1315
- if (ifa -> ifa_flags & IFA_F_SECONDARY )
1320
+ if (READ_ONCE ( ifa -> ifa_flags ) & IFA_F_SECONDARY )
1316
1321
continue ;
1317
1322
if (ifa -> ifa_scope != RT_SCOPE_LINK &&
1318
1323
ifa -> ifa_scope <= scope )
@@ -1340,7 +1345,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
1340
1345
localnet_scope = RT_SCOPE_LINK ;
1341
1346
1342
1347
in_dev_for_each_ifa_rcu (ifa , in_dev ) {
1343
- if (ifa -> ifa_flags & IFA_F_SECONDARY )
1348
+ if (READ_ONCE ( ifa -> ifa_flags ) & IFA_F_SECONDARY )
1344
1349
continue ;
1345
1350
if (min (ifa -> ifa_scope , localnet_scope ) > scope )
1346
1351
continue ;
@@ -1671,11 +1676,12 @@ static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
1671
1676
return nla_put (skb , IFA_CACHEINFO , sizeof (ci ), & ci );
1672
1677
}
1673
1678
1674
- static int inet_fill_ifaddr (struct sk_buff * skb , struct in_ifaddr * ifa ,
1679
+ static int inet_fill_ifaddr (struct sk_buff * skb , const struct in_ifaddr * ifa ,
1675
1680
struct inet_fill_args * args )
1676
1681
{
1677
1682
struct ifaddrmsg * ifm ;
1678
1683
struct nlmsghdr * nlh ;
1684
+ unsigned long tstamp ;
1679
1685
u32 preferred , valid ;
1680
1686
1681
1687
nlh = nlmsg_put (skb , args -> portid , args -> seq , args -> event , sizeof (* ifm ),
@@ -1686,19 +1692,20 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1686
1692
ifm = nlmsg_data (nlh );
1687
1693
ifm -> ifa_family = AF_INET ;
1688
1694
ifm -> ifa_prefixlen = ifa -> ifa_prefixlen ;
1689
- ifm -> ifa_flags = ifa -> ifa_flags ;
1695
+ ifm -> ifa_flags = READ_ONCE ( ifa -> ifa_flags ) ;
1690
1696
ifm -> ifa_scope = ifa -> ifa_scope ;
1691
1697
ifm -> ifa_index = ifa -> ifa_dev -> dev -> ifindex ;
1692
1698
1693
1699
if (args -> netnsid >= 0 &&
1694
1700
nla_put_s32 (skb , IFA_TARGET_NETNSID , args -> netnsid ))
1695
1701
goto nla_put_failure ;
1696
1702
1703
+ tstamp = READ_ONCE (ifa -> ifa_tstamp );
1697
1704
if (!(ifm -> ifa_flags & IFA_F_PERMANENT )) {
1698
- preferred = ifa -> ifa_preferred_lft ;
1699
- valid = ifa -> ifa_valid_lft ;
1705
+ preferred = READ_ONCE ( ifa -> ifa_preferred_lft ) ;
1706
+ valid = READ_ONCE ( ifa -> ifa_valid_lft ) ;
1700
1707
if (preferred != INFINITY_LIFE_TIME ) {
1701
- long tval = (jiffies - ifa -> ifa_tstamp ) / HZ ;
1708
+ long tval = (jiffies - tstamp ) / HZ ;
1702
1709
1703
1710
if (preferred > tval )
1704
1711
preferred -= tval ;
@@ -1725,10 +1732,10 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1725
1732
nla_put_string (skb , IFA_LABEL , ifa -> ifa_label )) ||
1726
1733
(ifa -> ifa_proto &&
1727
1734
nla_put_u8 (skb , IFA_PROTO , ifa -> ifa_proto )) ||
1728
- nla_put_u32 (skb , IFA_FLAGS , ifa -> ifa_flags ) ||
1735
+ nla_put_u32 (skb , IFA_FLAGS , ifm -> ifa_flags ) ||
1729
1736
(ifa -> ifa_rt_priority &&
1730
1737
nla_put_u32 (skb , IFA_RT_PRIORITY , ifa -> ifa_rt_priority )) ||
1731
- put_cacheinfo (skb , ifa -> ifa_cstamp , ifa -> ifa_tstamp ,
1738
+ put_cacheinfo (skb , READ_ONCE ( ifa -> ifa_cstamp ), tstamp ,
1732
1739
preferred , valid ))
1733
1740
goto nla_put_failure ;
1734
1741
@@ -1798,15 +1805,15 @@ static int inet_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
1798
1805
}
1799
1806
1800
1807
static int in_dev_dump_addr (struct in_device * in_dev , struct sk_buff * skb ,
1801
- struct netlink_callback * cb , int s_ip_idx ,
1808
+ struct netlink_callback * cb , int * s_ip_idx ,
1802
1809
struct inet_fill_args * fillargs )
1803
1810
{
1804
1811
struct in_ifaddr * ifa ;
1805
1812
int ip_idx = 0 ;
1806
1813
int err ;
1807
1814
1808
- in_dev_for_each_ifa_rtnl (ifa , in_dev ) {
1809
- if (ip_idx < s_ip_idx ) {
1815
+ in_dev_for_each_ifa_rcu (ifa , in_dev ) {
1816
+ if (ip_idx < * s_ip_idx ) {
1810
1817
ip_idx ++ ;
1811
1818
continue ;
1812
1819
}
@@ -1818,9 +1825,9 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
1818
1825
ip_idx ++ ;
1819
1826
}
1820
1827
err = 0 ;
1821
-
1828
+ ip_idx = 0 ;
1822
1829
done :
1823
- cb -> args [ 2 ] = ip_idx ;
1830
+ * s_ip_idx = ip_idx ;
1824
1831
1825
1832
return err ;
1826
1833
}
@@ -1830,7 +1837,7 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
1830
1837
static u32 inet_base_seq (const struct net * net )
1831
1838
{
1832
1839
u32 res = atomic_read (& net -> ipv4 .dev_addr_genid ) +
1833
- net -> dev_base_seq ;
1840
+ READ_ONCE ( net -> dev_base_seq ) ;
1834
1841
1835
1842
/* Must not return 0 (see nl_dump_check_consistent()).
1836
1843
* Chose a value far away from 0.
@@ -1852,75 +1859,53 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
1852
1859
};
1853
1860
struct net * net = sock_net (skb -> sk );
1854
1861
struct net * tgt_net = net ;
1855
- int h , s_h ;
1856
- int idx , s_idx ;
1857
- int s_ip_idx ;
1858
- struct net_device * dev ;
1862
+ struct {
1863
+ unsigned long ifindex ;
1864
+ int ip_idx ;
1865
+ } * ctx = ( void * ) cb -> ctx ;
1859
1866
struct in_device * in_dev ;
1860
- struct hlist_head * head ;
1867
+ struct net_device * dev ;
1861
1868
int err = 0 ;
1862
1869
1863
- s_h = cb -> args [0 ];
1864
- s_idx = idx = cb -> args [1 ];
1865
- s_ip_idx = cb -> args [2 ];
1866
-
1870
+ rcu_read_lock ();
1867
1871
if (cb -> strict_check ) {
1868
1872
err = inet_valid_dump_ifaddr_req (nlh , & fillargs , & tgt_net ,
1869
1873
skb -> sk , cb );
1870
1874
if (err < 0 )
1871
- goto put_tgt_net ;
1875
+ goto done ;
1872
1876
1873
- err = 0 ;
1874
1877
if (fillargs .ifindex ) {
1875
- dev = __dev_get_by_index (tgt_net , fillargs .ifindex );
1876
- if (!dev ) {
1877
- err = - ENODEV ;
1878
- goto put_tgt_net ;
1879
- }
1880
-
1881
- in_dev = __in_dev_get_rtnl (dev );
1882
- if (in_dev ) {
1883
- err = in_dev_dump_addr (in_dev , skb , cb , s_ip_idx ,
1884
- & fillargs );
1885
- }
1886
- goto put_tgt_net ;
1887
- }
1888
- }
1889
-
1890
- for (h = s_h ; h < NETDEV_HASHENTRIES ; h ++ , s_idx = 0 ) {
1891
- idx = 0 ;
1892
- head = & tgt_net -> dev_index_head [h ];
1893
- rcu_read_lock ();
1894
- cb -> seq = inet_base_seq (tgt_net );
1895
- hlist_for_each_entry_rcu (dev , head , index_hlist ) {
1896
- if (idx < s_idx )
1897
- goto cont ;
1898
- if (h > s_h || idx > s_idx )
1899
- s_ip_idx = 0 ;
1878
+ err = - ENODEV ;
1879
+ dev = dev_get_by_index_rcu (tgt_net , fillargs .ifindex );
1880
+ if (!dev )
1881
+ goto done ;
1900
1882
in_dev = __in_dev_get_rcu (dev );
1901
1883
if (!in_dev )
1902
- goto cont ;
1903
-
1904
- err = in_dev_dump_addr (in_dev , skb , cb , s_ip_idx ,
1905
- & fillargs );
1906
- if (err < 0 ) {
1907
- rcu_read_unlock ();
1908
1884
goto done ;
1909
- }
1910
- cont :
1911
- idx ++ ;
1885
+ err = in_dev_dump_addr ( in_dev , skb , cb , & ctx -> ip_idx ,
1886
+ & fillargs );
1887
+ goto done ;
1912
1888
}
1913
- rcu_read_unlock ();
1914
1889
}
1915
1890
1891
+ cb -> seq = inet_base_seq (tgt_net );
1892
+
1893
+ for_each_netdev_dump (net , dev , ctx -> ifindex ) {
1894
+ in_dev = __in_dev_get_rcu (dev );
1895
+ if (!in_dev )
1896
+ continue ;
1897
+ err = in_dev_dump_addr (in_dev , skb , cb , & ctx -> ip_idx ,
1898
+ & fillargs );
1899
+ if (err < 0 )
1900
+ goto done ;
1901
+ }
1916
1902
done :
1917
- cb -> args [0 ] = h ;
1918
- cb -> args [1 ] = idx ;
1919
- put_tgt_net :
1903
+ if (err < 0 && likely (skb -> len ))
1904
+ err = skb -> len ;
1920
1905
if (fillargs .netnsid >= 0 )
1921
1906
put_net (tgt_net );
1922
-
1923
- return skb -> len ? : err ;
1907
+ rcu_read_unlock ();
1908
+ return err ;
1924
1909
}
1925
1910
1926
1911
static void rtmsg_ifa (int event , struct in_ifaddr * ifa , struct nlmsghdr * nlh ,
@@ -2811,7 +2796,8 @@ void __init devinet_init(void)
2811
2796
2812
2797
rtnl_register (PF_INET , RTM_NEWADDR , inet_rtm_newaddr , NULL , 0 );
2813
2798
rtnl_register (PF_INET , RTM_DELADDR , inet_rtm_deladdr , NULL , 0 );
2814
- rtnl_register (PF_INET , RTM_GETADDR , NULL , inet_dump_ifaddr , 0 );
2799
+ rtnl_register (PF_INET , RTM_GETADDR , NULL , inet_dump_ifaddr ,
2800
+ RTNL_FLAG_DUMP_UNLOCKED );
2815
2801
rtnl_register (PF_INET , RTM_GETNETCONF , inet_netconf_get_devconf ,
2816
2802
inet_netconf_dump_devconf ,
2817
2803
RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED );
0 commit comments