@@ -713,34 +713,37 @@ static void check_lifetime(struct work_struct *work)
713713
714714 rcu_read_lock ();
715715 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 ;
717720
718- if (ifa -> ifa_flags & IFA_F_PERMANENT )
721+ flags = READ_ONCE (ifa -> ifa_flags );
722+ if (flags & IFA_F_PERMANENT )
719723 continue ;
720724
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 );
721728 /* We try to batch several events at once. */
722- age = (now - ifa -> ifa_tstamp +
729+ age = (now - tstamp +
723730 ADDRCONF_TIMER_FUZZ_MINUS ) / HZ ;
724731
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 ) {
727734 change_needed = true;
728- } else if (ifa -> ifa_preferred_lft ==
735+ } else if (preferred_lft ==
729736 INFINITY_LIFE_TIME ) {
730737 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 ;
736741
737- if (!(ifa -> ifa_flags & IFA_F_DEPRECATED ))
742+ if (!(flags & IFA_F_DEPRECATED ))
738743 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 ,
741745 next )) {
742- next = ifa -> ifa_tstamp +
743- ifa -> ifa_preferred_lft * HZ ;
746+ next = tstamp + preferred_lft * HZ ;
744747 }
745748 }
746749 rcu_read_unlock ();
@@ -804,24 +807,26 @@ static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
804807 __u32 prefered_lft )
805808{
806809 unsigned long timeout ;
810+ u32 flags ;
807811
808- ifa -> ifa_flags &= ~(IFA_F_PERMANENT | IFA_F_DEPRECATED );
812+ flags = ifa -> ifa_flags & ~(IFA_F_PERMANENT | IFA_F_DEPRECATED );
809813
810814 timeout = addrconf_timeout_fixup (valid_lft , HZ );
811815 if (addrconf_finite_timeout (timeout ))
812- ifa -> ifa_valid_lft = timeout ;
816+ WRITE_ONCE ( ifa -> ifa_valid_lft , timeout ) ;
813817 else
814- ifa -> ifa_flags |= IFA_F_PERMANENT ;
818+ flags |= IFA_F_PERMANENT ;
815819
816820 timeout = addrconf_timeout_fixup (prefered_lft , HZ );
817821 if (addrconf_finite_timeout (timeout )) {
818822 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 ) ;
821825 }
822- ifa -> ifa_tstamp = jiffies ;
826+ WRITE_ONCE (ifa -> ifa_flags , flags );
827+ WRITE_ONCE (ifa -> ifa_tstamp , jiffies );
823828 if (!ifa -> ifa_cstamp )
824- ifa -> ifa_cstamp = ifa -> ifa_tstamp ;
829+ WRITE_ONCE ( ifa -> ifa_cstamp , ifa -> ifa_tstamp ) ;
825830}
826831
827832static 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,
13121317 const struct in_ifaddr * ifa ;
13131318
13141319 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 )
13161321 continue ;
13171322 if (ifa -> ifa_scope != RT_SCOPE_LINK &&
13181323 ifa -> ifa_scope <= scope )
@@ -1340,7 +1345,7 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope)
13401345 localnet_scope = RT_SCOPE_LINK ;
13411346
13421347 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 )
13441349 continue ;
13451350 if (min (ifa -> ifa_scope , localnet_scope ) > scope )
13461351 continue ;
@@ -1671,11 +1676,12 @@ static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp,
16711676 return nla_put (skb , IFA_CACHEINFO , sizeof (ci ), & ci );
16721677}
16731678
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 ,
16751680 struct inet_fill_args * args )
16761681{
16771682 struct ifaddrmsg * ifm ;
16781683 struct nlmsghdr * nlh ;
1684+ unsigned long tstamp ;
16791685 u32 preferred , valid ;
16801686
16811687 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,
16861692 ifm = nlmsg_data (nlh );
16871693 ifm -> ifa_family = AF_INET ;
16881694 ifm -> ifa_prefixlen = ifa -> ifa_prefixlen ;
1689- ifm -> ifa_flags = ifa -> ifa_flags ;
1695+ ifm -> ifa_flags = READ_ONCE ( ifa -> ifa_flags ) ;
16901696 ifm -> ifa_scope = ifa -> ifa_scope ;
16911697 ifm -> ifa_index = ifa -> ifa_dev -> dev -> ifindex ;
16921698
16931699 if (args -> netnsid >= 0 &&
16941700 nla_put_s32 (skb , IFA_TARGET_NETNSID , args -> netnsid ))
16951701 goto nla_put_failure ;
16961702
1703+ tstamp = READ_ONCE (ifa -> ifa_tstamp );
16971704 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 ) ;
17001707 if (preferred != INFINITY_LIFE_TIME ) {
1701- long tval = (jiffies - ifa -> ifa_tstamp ) / HZ ;
1708+ long tval = (jiffies - tstamp ) / HZ ;
17021709
17031710 if (preferred > tval )
17041711 preferred -= tval ;
@@ -1725,10 +1732,10 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
17251732 nla_put_string (skb , IFA_LABEL , ifa -> ifa_label )) ||
17261733 (ifa -> ifa_proto &&
17271734 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 ) ||
17291736 (ifa -> ifa_rt_priority &&
17301737 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 ,
17321739 preferred , valid ))
17331740 goto nla_put_failure ;
17341741
@@ -1798,15 +1805,15 @@ static int inet_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
17981805}
17991806
18001807static 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 ,
18021809 struct inet_fill_args * fillargs )
18031810{
18041811 struct in_ifaddr * ifa ;
18051812 int ip_idx = 0 ;
18061813 int err ;
18071814
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 ) {
18101817 ip_idx ++ ;
18111818 continue ;
18121819 }
@@ -1818,9 +1825,9 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
18181825 ip_idx ++ ;
18191826 }
18201827 err = 0 ;
1821-
1828+ ip_idx = 0 ;
18221829done :
1823- cb -> args [ 2 ] = ip_idx ;
1830+ * s_ip_idx = ip_idx ;
18241831
18251832 return err ;
18261833}
@@ -1830,7 +1837,7 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
18301837static u32 inet_base_seq (const struct net * net )
18311838{
18321839 u32 res = atomic_read (& net -> ipv4 .dev_addr_genid ) +
1833- net -> dev_base_seq ;
1840+ READ_ONCE ( net -> dev_base_seq ) ;
18341841
18351842 /* Must not return 0 (see nl_dump_check_consistent()).
18361843 * Chose a value far away from 0.
@@ -1852,75 +1859,53 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
18521859 };
18531860 struct net * net = sock_net (skb -> sk );
18541861 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 ;
18591866 struct in_device * in_dev ;
1860- struct hlist_head * head ;
1867+ struct net_device * dev ;
18611868 int err = 0 ;
18621869
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 ();
18671871 if (cb -> strict_check ) {
18681872 err = inet_valid_dump_ifaddr_req (nlh , & fillargs , & tgt_net ,
18691873 skb -> sk , cb );
18701874 if (err < 0 )
1871- goto put_tgt_net ;
1875+ goto done ;
18721876
1873- err = 0 ;
18741877 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 ;
19001882 in_dev = __in_dev_get_rcu (dev );
19011883 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 ();
19081884 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 ;
19121888 }
1913- rcu_read_unlock ();
19141889 }
19151890
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+ }
19161902done :
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 ;
19201905 if (fillargs .netnsid >= 0 )
19211906 put_net (tgt_net );
1922-
1923- return skb -> len ? : err ;
1907+ rcu_read_unlock ();
1908+ return err ;
19241909}
19251910
19261911static void rtmsg_ifa (int event , struct in_ifaddr * ifa , struct nlmsghdr * nlh ,
@@ -2811,7 +2796,8 @@ void __init devinet_init(void)
28112796
28122797 rtnl_register (PF_INET , RTM_NEWADDR , inet_rtm_newaddr , NULL , 0 );
28132798 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 );
28152801 rtnl_register (PF_INET , RTM_GETNETCONF , inet_netconf_get_devconf ,
28162802 inet_netconf_dump_devconf ,
28172803 RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED );
0 commit comments