diff options
author | Florian Westphal <fw@strlen.de> | 2019-06-27 08:03:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-06-27 12:54:34 -0400 |
commit | 6a9e9cea4c51dd7137f381710bb42e2ad6e7e285 (patch) | |
tree | 57b256e5356e97686e4c57fad2236b0f947c187e /net/ipv4 | |
parent | 5b9469a285ebc85af29736a6d9fa995aea0dbf0b (diff) |
net: ipv4: fix infinite loop on secondary addr promotion
secondary address promotion causes infinite loop -- it arranges
for ifa->ifa_next to point back to itself.
Problem is that 'prev_prom' and 'last_prim' might point at the same entry,
so 'last_sec' pointer must be obtained after prev_prom->next update.
Fixes: 2638eb8b50cf ("net: ipv4: provide __rcu annotation for ifa_list")
Reported-by: Ran Rozenstein <ranro@mellanox.com>
Reported-by: Tariq Toukan <tariqt@mellanox.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/devinet.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 7874303220c5..137d1892395d 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -428,8 +428,9 @@ no_promotions: | |||
428 | if (prev_prom) { | 428 | if (prev_prom) { |
429 | struct in_ifaddr *last_sec; | 429 | struct in_ifaddr *last_sec; |
430 | 430 | ||
431 | last_sec = rtnl_dereference(last_prim->ifa_next); | ||
432 | rcu_assign_pointer(prev_prom->ifa_next, next_sec); | 431 | rcu_assign_pointer(prev_prom->ifa_next, next_sec); |
432 | |||
433 | last_sec = rtnl_dereference(last_prim->ifa_next); | ||
433 | rcu_assign_pointer(promote->ifa_next, last_sec); | 434 | rcu_assign_pointer(promote->ifa_next, last_sec); |
434 | rcu_assign_pointer(last_prim->ifa_next, promote); | 435 | rcu_assign_pointer(last_prim->ifa_next, promote); |
435 | } | 436 | } |