summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-05-31 12:27:09 -0400
committerDavid S. Miller <davem@davemloft.net>2019-06-02 21:08:36 -0400
commit2638eb8b50cfc16240e0bb080b9afbf541a9b39d (patch)
tree84264a6f50aaedfac6854bef3d5972926d321c10
parentcb8f1478cea68bc9c9bca8bded9617d9b0b7beb6 (diff)
net: ipv4: provide __rcu annotation for ifa_list
ifa_list is protected by rcu, yet code doesn't reflect this. Add the __rcu annotations and fix up all places that are now reported by sparse. I've done this in the same commit to not add intermediate patches that result in new warnings. Reported-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/infiniband/hw/i40iw/i40iw_utils.c12
-rw-r--r--drivers/infiniband/hw/nes/nes.c8
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_main.c15
-rw-r--r--drivers/net/ethernet/via/via-velocity.h2
-rw-r--r--drivers/net/plip/plip.c4
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c19
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c2
-rw-r--r--drivers/staging/isdn/hysdn/hysdn_net.c6
-rw-r--r--include/linux/inetdevice.h21
-rw-r--r--net/core/netpoll.c10
-rw-r--r--net/core/pktgen.c8
-rw-r--r--net/ipv4/devinet.c88
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/netfilter/nf_nat_redirect.c12
15 files changed, 134 insertions, 81 deletions
diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c
index 337410f40860..016524683e17 100644
--- a/drivers/infiniband/hw/i40iw/i40iw_utils.c
+++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c
@@ -174,10 +174,14 @@ int i40iw_inetaddr_event(struct notifier_block *notifier,
174 rcu_read_lock(); 174 rcu_read_lock();
175 in = __in_dev_get_rcu(upper_dev); 175 in = __in_dev_get_rcu(upper_dev);
176 176
177 if (!in->ifa_list) 177 local_ipaddr = 0;
178 local_ipaddr = 0; 178 if (in) {
179 else 179 struct in_ifaddr *ifa;
180 local_ipaddr = ntohl(in->ifa_list->ifa_address); 180
181 ifa = rcu_dereference(in->ifa_list);
182 if (ifa)
183 local_ipaddr = ntohl(ifa->ifa_address);
184 }
181 185
182 rcu_read_unlock(); 186 rcu_read_unlock();
183 } else { 187 } else {
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index e00add6d78ec..29b324726ea6 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -183,7 +183,13 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
183 183
184 rcu_read_lock(); 184 rcu_read_lock();
185 in = __in_dev_get_rcu(upper_dev); 185 in = __in_dev_get_rcu(upper_dev);
186 nesvnic->local_ipaddr = in->ifa_list->ifa_address; 186 if (in) {
187 struct in_ifaddr *ifa;
188
189 ifa = rcu_dereference(in->ifa_list);
190 if (ifa)
191 nesvnic->local_ipaddr = ifa->ifa_address;
192 }
187 rcu_read_unlock(); 193 rcu_read_unlock();
188 } else { 194 } else {
189 nesvnic->local_ipaddr = ifa->ifa_address; 195 nesvnic->local_ipaddr = ifa->ifa_address;
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_main.c b/drivers/infiniband/hw/usnic/usnic_ib_main.c
index d88d9f8a7f9a..34c1f9d6c915 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_main.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_main.c
@@ -427,11 +427,16 @@ static void *usnic_ib_device_add(struct pci_dev *dev)
427 if (netif_carrier_ok(us_ibdev->netdev)) 427 if (netif_carrier_ok(us_ibdev->netdev))
428 usnic_fwd_carrier_up(us_ibdev->ufdev); 428 usnic_fwd_carrier_up(us_ibdev->ufdev);
429 429
430 ind = in_dev_get(netdev); 430 rcu_read_lock();
431 if (ind->ifa_list) 431 ind = __in_dev_get_rcu(netdev);
432 usnic_fwd_add_ipaddr(us_ibdev->ufdev, 432 if (ind) {
433 ind->ifa_list->ifa_address); 433 const struct in_ifaddr *ifa;
434 in_dev_put(ind); 434
435 ifa = rcu_dereference(ind->ifa_list);
436 if (ifa)
437 usnic_fwd_add_ipaddr(us_ibdev->ufdev, ifa->ifa_address);
438 }
439 rcu_read_unlock();
435 440
436 usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr, 441 usnic_mac_ip_to_gid(us_ibdev->netdev->perm_addr,
437 us_ibdev->ufdev->inaddr, &gid.raw[0]); 442 us_ibdev->ufdev->inaddr, &gid.raw[0]);
diff --git a/drivers/net/ethernet/via/via-velocity.h b/drivers/net/ethernet/via/via-velocity.h
index c0ecc6c7b5e0..cdfe7809e3c1 100644
--- a/drivers/net/ethernet/via/via-velocity.h
+++ b/drivers/net/ethernet/via/via-velocity.h
@@ -1509,7 +1509,7 @@ static inline int velocity_get_ip(struct velocity_info *vptr)
1509 rcu_read_lock(); 1509 rcu_read_lock();
1510 in_dev = __in_dev_get_rcu(vptr->netdev); 1510 in_dev = __in_dev_get_rcu(vptr->netdev);
1511 if (in_dev != NULL) { 1511 if (in_dev != NULL) {
1512 ifa = (struct in_ifaddr *) in_dev->ifa_list; 1512 ifa = rcu_dereference(in_dev->ifa_list);
1513 if (ifa != NULL) { 1513 if (ifa != NULL) {
1514 memcpy(vptr->ip_addr, &ifa->ifa_address, 4); 1514 memcpy(vptr->ip_addr, &ifa->ifa_address, 4);
1515 res = 0; 1515 res = 0;
diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c
index feb92ecd1880..3e3ac2e496a1 100644
--- a/drivers/net/plip/plip.c
+++ b/drivers/net/plip/plip.c
@@ -1012,7 +1012,7 @@ plip_rewrite_address(const struct net_device *dev, struct ethhdr *eth)
1012 in_dev = __in_dev_get_rcu(dev); 1012 in_dev = __in_dev_get_rcu(dev);
1013 if (in_dev) { 1013 if (in_dev) {
1014 /* Any address will do - we take the first */ 1014 /* Any address will do - we take the first */
1015 const struct in_ifaddr *ifa = in_dev->ifa_list; 1015 const struct in_ifaddr *ifa = rcu_dereference(in_dev->ifa_list);
1016 if (ifa) { 1016 if (ifa) {
1017 memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); 1017 memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
1018 memset(eth->h_dest, 0xfc, 2); 1018 memset(eth->h_dest, 0xfc, 2);
@@ -1107,7 +1107,7 @@ plip_open(struct net_device *dev)
1107 /* Any address will do - we take the first. We already 1107 /* Any address will do - we take the first. We already
1108 have the first two bytes filled with 0xfc, from 1108 have the first two bytes filled with 0xfc, from
1109 plip_init_dev(). */ 1109 plip_init_dev(). */
1110 struct in_ifaddr *ifa=in_dev->ifa_list; 1110 const struct in_ifaddr *ifa = rcu_dereference(in_dev->ifa_list);
1111 if (ifa != NULL) { 1111 if (ifa != NULL) {
1112 memcpy(dev->dev_addr+2, &ifa->ifa_local, 4); 1112 memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
1113 } 1113 }
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 89984fcab01e..1b2a18ea855c 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -3651,13 +3651,19 @@ vmxnet3_suspend(struct device *device)
3651 } 3651 }
3652 3652
3653 if (adapter->wol & WAKE_ARP) { 3653 if (adapter->wol & WAKE_ARP) {
3654 in_dev = in_dev_get(netdev); 3654 rcu_read_lock();
3655 if (!in_dev) 3655
3656 in_dev = __in_dev_get_rcu(netdev);
3657 if (!in_dev) {
3658 rcu_read_unlock();
3656 goto skip_arp; 3659 goto skip_arp;
3660 }
3657 3661
3658 ifa = (struct in_ifaddr *)in_dev->ifa_list; 3662 ifa = rcu_dereference(in_dev->ifa_list);
3659 if (!ifa) 3663 if (!ifa) {
3664 rcu_read_unlock();
3660 goto skip_arp; 3665 goto skip_arp;
3666 }
3661 3667
3662 pmConf->filters[i].patternSize = ETH_HLEN + /* Ethernet header*/ 3668 pmConf->filters[i].patternSize = ETH_HLEN + /* Ethernet header*/
3663 sizeof(struct arphdr) + /* ARP header */ 3669 sizeof(struct arphdr) + /* ARP header */
@@ -3677,7 +3683,9 @@ vmxnet3_suspend(struct device *device)
3677 3683
3678 /* The Unicast IPv4 address in 'tip' field. */ 3684 /* The Unicast IPv4 address in 'tip' field. */
3679 arpreq += 2 * ETH_ALEN + sizeof(u32); 3685 arpreq += 2 * ETH_ALEN + sizeof(u32);
3680 *(u32 *)arpreq = ifa->ifa_address; 3686 *(__be32 *)arpreq = ifa->ifa_address;
3687
3688 rcu_read_unlock();
3681 3689
3682 /* The mask for the relevant bits. */ 3690 /* The mask for the relevant bits. */
3683 pmConf->filters[i].mask[0] = 0x00; 3691 pmConf->filters[i].mask[0] = 0x00;
@@ -3686,7 +3694,6 @@ vmxnet3_suspend(struct device *device)
3686 pmConf->filters[i].mask[3] = 0x00; 3694 pmConf->filters[i].mask[3] = 0x00;
3687 pmConf->filters[i].mask[4] = 0xC0; /* IPv4 TIP */ 3695 pmConf->filters[i].mask[4] = 0xC0; /* IPv4 TIP */
3688 pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */ 3696 pmConf->filters[i].mask[5] = 0x03; /* IPv4 TIP */
3689 in_dev_put(in_dev);
3690 3697
3691 pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER; 3698 pmConf->wakeUpEvents |= VMXNET3_PM_WAKEUP_FILTER;
3692 i++; 3699 i++;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 5477a014e1fb..37cf602d8adf 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2194,13 +2194,13 @@ static int ath6kl_wow_suspend_vif(struct ath6kl_vif *vif,
2194 if (!in_dev) 2194 if (!in_dev)
2195 return 0; 2195 return 0;
2196 2196
2197 ifa = in_dev->ifa_list; 2197 ifa = rtnl_dereference(in_dev->ifa_list);
2198 memset(&ips, 0, sizeof(ips)); 2198 memset(&ips, 0, sizeof(ips));
2199 2199
2200 /* Configure IP addr only if IP address count < MAX_IP_ADDRS */ 2200 /* Configure IP addr only if IP address count < MAX_IP_ADDRS */
2201 while (index < MAX_IP_ADDRS && ifa) { 2201 while (index < MAX_IP_ADDRS && ifa) {
2202 ips[index] = ifa->ifa_local; 2202 ips[index] = ifa->ifa_local;
2203 ifa = ifa->ifa_next; 2203 ifa = rtnl_dereference(ifa->ifa_next);
2204 index++; 2204 index++;
2205 } 2205 }
2206 2206
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index e11a4bb67172..5a7cdb981789 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -3268,7 +3268,7 @@ static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,
3268 in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev); 3268 in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);
3269 if (!in_dev) 3269 if (!in_dev)
3270 continue; 3270 continue;
3271 ifa = in_dev->ifa_list; 3271 ifa = rtnl_dereference(in_dev->ifa_list);
3272 if (!ifa || !ifa->ifa_local) 3272 if (!ifa || !ifa->ifa_local)
3273 continue; 3273 continue;
3274 ips[i] = ifa->ifa_local; 3274 ips[i] = ifa->ifa_local;
diff --git a/drivers/staging/isdn/hysdn/hysdn_net.c b/drivers/staging/isdn/hysdn/hysdn_net.c
index 8e9c34f33d86..bea37ae30ebb 100644
--- a/drivers/staging/isdn/hysdn/hysdn_net.c
+++ b/drivers/staging/isdn/hysdn/hysdn_net.c
@@ -70,9 +70,13 @@ net_open(struct net_device *dev)
70 for (i = 0; i < ETH_ALEN; i++) 70 for (i = 0; i < ETH_ALEN; i++)
71 dev->dev_addr[i] = 0xfc; 71 dev->dev_addr[i] = 0xfc;
72 if ((in_dev = dev->ip_ptr) != NULL) { 72 if ((in_dev = dev->ip_ptr) != NULL) {
73 struct in_ifaddr *ifa = in_dev->ifa_list; 73 const struct in_ifaddr *ifa;
74
75 rcu_read_lock();
76 ifa = rcu_dereference(in_dev->ifa_list);
74 if (ifa != NULL) 77 if (ifa != NULL)
75 memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ifa->ifa_local)), &ifa->ifa_local, sizeof(ifa->ifa_local)); 78 memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ifa->ifa_local)), &ifa->ifa_local, sizeof(ifa->ifa_local));
79 rcu_read_unlock();
76 } 80 }
77 } else 81 } else
78 memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); 82 memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN);
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index d5d05503a04b..3515ca64e638 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -26,7 +26,7 @@ struct in_device {
26 struct net_device *dev; 26 struct net_device *dev;
27 refcount_t refcnt; 27 refcount_t refcnt;
28 int dead; 28 int dead;
29 struct in_ifaddr *ifa_list; /* IP ifaddr chain */ 29 struct in_ifaddr __rcu *ifa_list;/* IP ifaddr chain */
30 30
31 struct ip_mc_list __rcu *mc_list; /* IP multicast filter chain */ 31 struct ip_mc_list __rcu *mc_list; /* IP multicast filter chain */
32 struct ip_mc_list __rcu * __rcu *mc_hash; 32 struct ip_mc_list __rcu * __rcu *mc_hash;
@@ -136,7 +136,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
136 136
137struct in_ifaddr { 137struct in_ifaddr {
138 struct hlist_node hash; 138 struct hlist_node hash;
139 struct in_ifaddr *ifa_next; 139 struct in_ifaddr __rcu *ifa_next;
140 struct in_device *ifa_dev; 140 struct in_device *ifa_dev;
141 struct rcu_head rcu_head; 141 struct rcu_head rcu_head;
142 __be32 ifa_local; 142 __be32 ifa_local;
@@ -206,22 +206,13 @@ static __inline__ bool bad_mask(__be32 mask, __be32 addr)
206 return false; 206 return false;
207} 207}
208 208
209#define for_primary_ifa(in_dev) { struct in_ifaddr *ifa; \
210 for (ifa = (in_dev)->ifa_list; ifa && !(ifa->ifa_flags&IFA_F_SECONDARY); ifa = ifa->ifa_next)
211
212#define for_ifa(in_dev) { struct in_ifaddr *ifa; \
213 for (ifa = (in_dev)->ifa_list; ifa; ifa = ifa->ifa_next)
214
215
216#define endfor_ifa(in_dev) }
217
218#define in_dev_for_each_ifa_rtnl(ifa, in_dev) \ 209#define in_dev_for_each_ifa_rtnl(ifa, in_dev) \
219 for (ifa = (in_dev)->ifa_list; ifa; \ 210 for (ifa = rtnl_dereference((in_dev)->ifa_list); ifa; \
220 ifa = ifa->ifa_next) 211 ifa = rtnl_dereference(ifa->ifa_next))
221 212
222#define in_dev_for_each_ifa_rcu(ifa, in_dev) \ 213#define in_dev_for_each_ifa_rcu(ifa, in_dev) \
223 for (ifa = (in_dev)->ifa_list; ifa; \ 214 for (ifa = rcu_dereference((in_dev)->ifa_list); ifa; \
224 ifa = ifa->ifa_next) 215 ifa = rcu_dereference(ifa->ifa_next))
225 216
226static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev) 217static inline struct in_device *__in_dev_get_rcu(const struct net_device *dev)
227{ 218{
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index dd8b1a460d64..2cf27da1baeb 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -696,16 +696,22 @@ int netpoll_setup(struct netpoll *np)
696 696
697 if (!np->local_ip.ip) { 697 if (!np->local_ip.ip) {
698 if (!np->ipv6) { 698 if (!np->ipv6) {
699 const struct in_ifaddr *ifa;
700
699 in_dev = __in_dev_get_rtnl(ndev); 701 in_dev = __in_dev_get_rtnl(ndev);
702 if (!in_dev)
703 goto put_noaddr;
700 704
701 if (!in_dev || !in_dev->ifa_list) { 705 ifa = rtnl_dereference(in_dev->ifa_list);
706 if (!ifa) {
707put_noaddr:
702 np_err(np, "no IP address for %s, aborting\n", 708 np_err(np, "no IP address for %s, aborting\n",
703 np->dev_name); 709 np->dev_name);
704 err = -EDESTADDRREQ; 710 err = -EDESTADDRREQ;
705 goto put; 711 goto put;
706 } 712 }
707 713
708 np->local_ip.ip = in_dev->ifa_list->ifa_local; 714 np->local_ip.ip = ifa->ifa_local;
709 np_info(np, "local IP %pI4\n", &np->local_ip.ip); 715 np_info(np, "local IP %pI4\n", &np->local_ip.ip);
710 } else { 716 } else {
711#if IS_ENABLED(CONFIG_IPV6) 717#if IS_ENABLED(CONFIG_IPV6)
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 319ad5490fb3..4cd120dc30ad 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2125,9 +2125,11 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev)
2125 rcu_read_lock(); 2125 rcu_read_lock();
2126 in_dev = __in_dev_get_rcu(pkt_dev->odev); 2126 in_dev = __in_dev_get_rcu(pkt_dev->odev);
2127 if (in_dev) { 2127 if (in_dev) {
2128 if (in_dev->ifa_list) { 2128 const struct in_ifaddr *ifa;
2129 pkt_dev->saddr_min = 2129
2130 in_dev->ifa_list->ifa_address; 2130 ifa = rcu_dereference(in_dev->ifa_list);
2131 if (ifa) {
2132 pkt_dev->saddr_min = ifa->ifa_address;
2131 pkt_dev->saddr_max = pkt_dev->saddr_min; 2133 pkt_dev->saddr_max = pkt_dev->saddr_min;
2132 } 2134 }
2133 } 2135 }
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index b45421b2b734..ebaea05b4033 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -194,7 +194,8 @@ static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
194 194
195static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); 195static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
196static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain); 196static BLOCKING_NOTIFIER_HEAD(inetaddr_validator_chain);
197static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 197static void inet_del_ifa(struct in_device *in_dev,
198 struct in_ifaddr __rcu **ifap,
198 int destroy); 199 int destroy);
199#ifdef CONFIG_SYSCTL 200#ifdef CONFIG_SYSCTL
200static int devinet_sysctl_register(struct in_device *idev); 201static int devinet_sysctl_register(struct in_device *idev);
@@ -300,8 +301,8 @@ static void in_dev_rcu_put(struct rcu_head *head)
300 301
301static void inetdev_destroy(struct in_device *in_dev) 302static void inetdev_destroy(struct in_device *in_dev)
302{ 303{
303 struct in_ifaddr *ifa;
304 struct net_device *dev; 304 struct net_device *dev;
305 struct in_ifaddr *ifa;
305 306
306 ASSERT_RTNL(); 307 ASSERT_RTNL();
307 308
@@ -311,7 +312,7 @@ static void inetdev_destroy(struct in_device *in_dev)
311 312
312 ip_mc_destroy_dev(in_dev); 313 ip_mc_destroy_dev(in_dev);
313 314
314 while ((ifa = in_dev->ifa_list) != NULL) { 315 while ((ifa = rtnl_dereference(in_dev->ifa_list)) != NULL) {
315 inet_del_ifa(in_dev, &in_dev->ifa_list, 0); 316 inet_del_ifa(in_dev, &in_dev->ifa_list, 0);
316 inet_free_ifa(ifa); 317 inet_free_ifa(ifa);
317 } 318 }
@@ -342,17 +343,20 @@ int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b)
342 return 0; 343 return 0;
343} 344}
344 345
345static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 346static void __inet_del_ifa(struct in_device *in_dev,
346 int destroy, struct nlmsghdr *nlh, u32 portid) 347 struct in_ifaddr __rcu **ifap,
348 int destroy, struct nlmsghdr *nlh, u32 portid)
347{ 349{
348 struct in_ifaddr *promote = NULL; 350 struct in_ifaddr *promote = NULL;
349 struct in_ifaddr *ifa, *ifa1 = *ifap; 351 struct in_ifaddr *ifa, *ifa1;
350 struct in_ifaddr *last_prim = in_dev->ifa_list; 352 struct in_ifaddr *last_prim;
351 struct in_ifaddr *prev_prom = NULL; 353 struct in_ifaddr *prev_prom = NULL;
352 int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev); 354 int do_promote = IN_DEV_PROMOTE_SECONDARIES(in_dev);
353 355
354 ASSERT_RTNL(); 356 ASSERT_RTNL();
355 357
358 ifa1 = rtnl_dereference(*ifap);
359 last_prim = rtnl_dereference(in_dev->ifa_list);
356 if (in_dev->dead) 360 if (in_dev->dead)
357 goto no_promotions; 361 goto no_promotions;
358 362
@@ -361,9 +365,9 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
361 **/ 365 **/
362 366
363 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) { 367 if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
364 struct in_ifaddr **ifap1 = &ifa1->ifa_next; 368 struct in_ifaddr __rcu **ifap1 = &ifa1->ifa_next;
365 369
366 while ((ifa = *ifap1) != NULL) { 370 while ((ifa = rtnl_dereference(*ifap1)) != NULL) {
367 if (!(ifa->ifa_flags & IFA_F_SECONDARY) && 371 if (!(ifa->ifa_flags & IFA_F_SECONDARY) &&
368 ifa1->ifa_scope <= ifa->ifa_scope) 372 ifa1->ifa_scope <= ifa->ifa_scope)
369 last_prim = ifa; 373 last_prim = ifa;
@@ -396,7 +400,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
396 * and later to add them back with new prefsrc. Do this 400 * and later to add them back with new prefsrc. Do this
397 * while all addresses are on the device list. 401 * while all addresses are on the device list.
398 */ 402 */
399 for (ifa = promote; ifa; ifa = ifa->ifa_next) { 403 for (ifa = promote; ifa; ifa = rtnl_dereference(ifa->ifa_next)) {
400 if (ifa1->ifa_mask == ifa->ifa_mask && 404 if (ifa1->ifa_mask == ifa->ifa_mask &&
401 inet_ifa_match(ifa1->ifa_address, ifa)) 405 inet_ifa_match(ifa1->ifa_address, ifa))
402 fib_del_ifaddr(ifa, ifa1); 406 fib_del_ifaddr(ifa, ifa1);
@@ -422,19 +426,24 @@ no_promotions:
422 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); 426 blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1);
423 427
424 if (promote) { 428 if (promote) {
425 struct in_ifaddr *next_sec = promote->ifa_next; 429 struct in_ifaddr *next_sec;
426 430
431 next_sec = rtnl_dereference(promote->ifa_next);
427 if (prev_prom) { 432 if (prev_prom) {
428 prev_prom->ifa_next = promote->ifa_next; 433 struct in_ifaddr *last_sec;
429 promote->ifa_next = last_prim->ifa_next; 434
430 last_prim->ifa_next = promote; 435 last_sec = rtnl_dereference(last_prim->ifa_next);
436 rcu_assign_pointer(prev_prom->ifa_next, next_sec);
437 rcu_assign_pointer(promote->ifa_next, last_sec);
438 rcu_assign_pointer(last_prim->ifa_next, promote);
431 } 439 }
432 440
433 promote->ifa_flags &= ~IFA_F_SECONDARY; 441 promote->ifa_flags &= ~IFA_F_SECONDARY;
434 rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid); 442 rtmsg_ifa(RTM_NEWADDR, promote, nlh, portid);
435 blocking_notifier_call_chain(&inetaddr_chain, 443 blocking_notifier_call_chain(&inetaddr_chain,
436 NETDEV_UP, promote); 444 NETDEV_UP, promote);
437 for (ifa = next_sec; ifa; ifa = ifa->ifa_next) { 445 for (ifa = next_sec; ifa;
446 ifa = rtnl_dereference(ifa->ifa_next)) {
438 if (ifa1->ifa_mask != ifa->ifa_mask || 447 if (ifa1->ifa_mask != ifa->ifa_mask ||
439 !inet_ifa_match(ifa1->ifa_address, ifa)) 448 !inet_ifa_match(ifa1->ifa_address, ifa))
440 continue; 449 continue;
@@ -446,7 +455,8 @@ no_promotions:
446 inet_free_ifa(ifa1); 455 inet_free_ifa(ifa1);
447} 456}
448 457
449static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, 458static void inet_del_ifa(struct in_device *in_dev,
459 struct in_ifaddr __rcu **ifap,
450 int destroy) 460 int destroy)
451{ 461{
452 __inet_del_ifa(in_dev, ifap, destroy, NULL, 0); 462 __inet_del_ifa(in_dev, ifap, destroy, NULL, 0);
@@ -459,9 +469,10 @@ static DECLARE_DELAYED_WORK(check_lifetime_work, check_lifetime);
459static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, 469static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
460 u32 portid, struct netlink_ext_ack *extack) 470 u32 portid, struct netlink_ext_ack *extack)
461{ 471{
472 struct in_ifaddr __rcu **last_primary, **ifap;
462 struct in_device *in_dev = ifa->ifa_dev; 473 struct in_device *in_dev = ifa->ifa_dev;
463 struct in_ifaddr *ifa1, **ifap, **last_primary;
464 struct in_validator_info ivi; 474 struct in_validator_info ivi;
475 struct in_ifaddr *ifa1;
465 int ret; 476 int ret;
466 477
467 ASSERT_RTNL(); 478 ASSERT_RTNL();
@@ -474,8 +485,10 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
474 ifa->ifa_flags &= ~IFA_F_SECONDARY; 485 ifa->ifa_flags &= ~IFA_F_SECONDARY;
475 last_primary = &in_dev->ifa_list; 486 last_primary = &in_dev->ifa_list;
476 487
477 for (ifap = &in_dev->ifa_list; (ifa1 = *ifap) != NULL; 488 ifap = &in_dev->ifa_list;
478 ifap = &ifa1->ifa_next) { 489 ifa1 = rtnl_dereference(*ifap);
490
491 while (ifa1) {
479 if (!(ifa1->ifa_flags & IFA_F_SECONDARY) && 492 if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&
480 ifa->ifa_scope <= ifa1->ifa_scope) 493 ifa->ifa_scope <= ifa1->ifa_scope)
481 last_primary = &ifa1->ifa_next; 494 last_primary = &ifa1->ifa_next;
@@ -491,6 +504,9 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
491 } 504 }
492 ifa->ifa_flags |= IFA_F_SECONDARY; 505 ifa->ifa_flags |= IFA_F_SECONDARY;
493 } 506 }
507
508 ifap = &ifa1->ifa_next;
509 ifa1 = rtnl_dereference(*ifap);
494 } 510 }
495 511
496 /* Allow any devices that wish to register ifaddr validtors to weigh 512 /* Allow any devices that wish to register ifaddr validtors to weigh
@@ -516,8 +532,8 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
516 ifap = last_primary; 532 ifap = last_primary;
517 } 533 }
518 534
519 ifa->ifa_next = *ifap; 535 rcu_assign_pointer(ifa->ifa_next, *ifap);
520 *ifap = ifa; 536 rcu_assign_pointer(*ifap, ifa);
521 537
522 inet_hash_insert(dev_net(in_dev->dev), ifa); 538 inet_hash_insert(dev_net(in_dev->dev), ifa);
523 539
@@ -617,10 +633,12 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
617 struct netlink_ext_ack *extack) 633 struct netlink_ext_ack *extack)
618{ 634{
619 struct net *net = sock_net(skb->sk); 635 struct net *net = sock_net(skb->sk);
636 struct in_ifaddr __rcu **ifap;
620 struct nlattr *tb[IFA_MAX+1]; 637 struct nlattr *tb[IFA_MAX+1];
621 struct in_device *in_dev; 638 struct in_device *in_dev;
622 struct ifaddrmsg *ifm; 639 struct ifaddrmsg *ifm;
623 struct in_ifaddr *ifa, **ifap; 640 struct in_ifaddr *ifa;
641
624 int err = -EINVAL; 642 int err = -EINVAL;
625 643
626 ASSERT_RTNL(); 644 ASSERT_RTNL();
@@ -637,7 +655,7 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
637 goto errout; 655 goto errout;
638 } 656 }
639 657
640 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; 658 for (ifap = &in_dev->ifa_list; (ifa = rtnl_dereference(*ifap)) != NULL;
641 ifap = &ifa->ifa_next) { 659 ifap = &ifa->ifa_next) {
642 if (tb[IFA_LOCAL] && 660 if (tb[IFA_LOCAL] &&
643 ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL])) 661 ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL]))
@@ -725,15 +743,20 @@ static void check_lifetime(struct work_struct *work)
725 743
726 if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME && 744 if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
727 age >= ifa->ifa_valid_lft) { 745 age >= ifa->ifa_valid_lft) {
728 struct in_ifaddr **ifap; 746 struct in_ifaddr __rcu **ifap;
729 747 struct in_ifaddr *tmp;
730 for (ifap = &ifa->ifa_dev->ifa_list; 748
731 *ifap != NULL; ifap = &(*ifap)->ifa_next) { 749 ifap = &ifa->ifa_dev->ifa_list;
732 if (*ifap == ifa) { 750 tmp = rtnl_dereference(*ifap);
751 while (tmp) {
752 tmp = rtnl_dereference(tmp->ifa_next);
753 if (rtnl_dereference(*ifap) == ifa) {
733 inet_del_ifa(ifa->ifa_dev, 754 inet_del_ifa(ifa->ifa_dev,
734 ifap, 1); 755 ifap, 1);
735 break; 756 break;
736 } 757 }
758 ifap = &tmp->ifa_next;
759 tmp = rtnl_dereference(*ifap);
737 } 760 }
738 } else if (ifa->ifa_preferred_lft != 761 } else if (ifa->ifa_preferred_lft !=
739 INFINITY_LIFE_TIME && 762 INFINITY_LIFE_TIME &&
@@ -977,8 +1000,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
977{ 1000{
978 struct sockaddr_in sin_orig; 1001 struct sockaddr_in sin_orig;
979 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr; 1002 struct sockaddr_in *sin = (struct sockaddr_in *)&ifr->ifr_addr;
1003 struct in_ifaddr __rcu **ifap = NULL;
980 struct in_device *in_dev; 1004 struct in_device *in_dev;
981 struct in_ifaddr **ifap = NULL;
982 struct in_ifaddr *ifa = NULL; 1005 struct in_ifaddr *ifa = NULL;
983 struct net_device *dev; 1006 struct net_device *dev;
984 char *colon; 1007 char *colon;
@@ -1049,7 +1072,9 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
1049 /* note: we only do this for a limited set of ioctls 1072 /* note: we only do this for a limited set of ioctls
1050 and only if the original address family was AF_INET. 1073 and only if the original address family was AF_INET.
1051 This is checked above. */ 1074 This is checked above. */
1052 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; 1075
1076 for (ifap = &in_dev->ifa_list;
1077 (ifa = rtnl_dereference(*ifap)) != NULL;
1053 ifap = &ifa->ifa_next) { 1078 ifap = &ifa->ifa_next) {
1054 if (!strcmp(ifr->ifr_name, ifa->ifa_label) && 1079 if (!strcmp(ifr->ifr_name, ifa->ifa_label) &&
1055 sin_orig.sin_addr.s_addr == 1080 sin_orig.sin_addr.s_addr ==
@@ -1062,7 +1087,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
1062 4.3BSD-style and passed in junk so we fall back to 1087 4.3BSD-style and passed in junk so we fall back to
1063 comparing just the label */ 1088 comparing just the label */
1064 if (!ifa) { 1089 if (!ifa) {
1065 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; 1090 for (ifap = &in_dev->ifa_list;
1091 (ifa = rtnl_dereference(*ifap)) != NULL;
1066 ifap = &ifa->ifa_next) 1092 ifap = &ifa->ifa_next)
1067 if (!strcmp(ifr->ifr_name, ifa->ifa_label)) 1093 if (!strcmp(ifr->ifr_name, ifa->ifa_label))
1068 break; 1094 break;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 2b608044ae23..1f11907dc528 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -354,11 +354,11 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
354 sdata_lock(sdata); 354 sdata_lock(sdata);
355 355
356 /* Copy the addresses to the bss_conf list */ 356 /* Copy the addresses to the bss_conf list */
357 ifa = idev->ifa_list; 357 ifa = rtnl_dereference(idev->ifa_list);
358 while (ifa) { 358 while (ifa) {
359 if (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN) 359 if (c < IEEE80211_BSS_ARP_ADDR_LIST_LEN)
360 bss_conf->arp_addr_list[c] = ifa->ifa_address; 360 bss_conf->arp_addr_list[c] = ifa->ifa_address;
361 ifa = ifa->ifa_next; 361 ifa = rtnl_dereference(ifa->ifa_next);
362 c++; 362 c++;
363 } 363 }
364 364
diff --git a/net/netfilter/nf_nat_redirect.c b/net/netfilter/nf_nat_redirect.c
index 78a9e6454ff3..8598e80968e0 100644
--- a/net/netfilter/nf_nat_redirect.c
+++ b/net/netfilter/nf_nat_redirect.c
@@ -47,15 +47,17 @@ nf_nat_redirect_ipv4(struct sk_buff *skb,
47 if (hooknum == NF_INET_LOCAL_OUT) { 47 if (hooknum == NF_INET_LOCAL_OUT) {
48 newdst = htonl(0x7F000001); 48 newdst = htonl(0x7F000001);
49 } else { 49 } else {
50 struct in_device *indev; 50 const struct in_device *indev;
51 struct in_ifaddr *ifa;
52 51
53 newdst = 0; 52 newdst = 0;
54 53
55 indev = __in_dev_get_rcu(skb->dev); 54 indev = __in_dev_get_rcu(skb->dev);
56 if (indev && indev->ifa_list) { 55 if (indev) {
57 ifa = indev->ifa_list; 56 const struct in_ifaddr *ifa;
58 newdst = ifa->ifa_local; 57
58 ifa = rcu_dereference(indev->ifa_list);
59 if (ifa)
60 newdst = ifa->ifa_local;
59 } 61 }
60 62
61 if (!newdst) 63 if (!newdst)