summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)