From patchwork Thu Dec 13 13:59:06 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [181/241] ipv6: addrconf: fix /proc/net/if_inet6 X-Patchwork-Submitter: Herton Ronaldo Krzesinski X-Patchwork-Id: 206026 Message-Id: <1355407206-17100-182-git-send-email-herton.krzesinski@canonical.com> To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, kernel-team@lists.ubuntu.com Cc: Eric Dumazet , Mihai Maruseac , "David S. Miller" Date: Thu, 13 Dec 2012 11:59:06 -0200 From: Herton Ronaldo Krzesinski List-Id: Kernel team discussions 3.5.7.2 -stable review patch. If anyone has any objections, please let me know. ------------------ From: Eric Dumazet commit 9f0d3c2781baa1102108e16efbe640dd74564a7c upstream. Commit 1d5783030a1 (ipv6/addrconf: speedup /proc/net/if_inet6 filling) added bugs hiding some devices from if_inet6 and breaking applications. "ip -6 addr" could still display all IPv6 addresses, while "ifconfig -a" couldnt. One way to reproduce the bug is by starting in a shell : unshare -n /bin/bash ifconfig lo up And in original net namespace, lo device disappeared from if_inet6 Reported-by: Jan Hinnerk Stosch Tested-by: Jan Hinnerk Stosch Signed-off-by: Eric Dumazet Cc: Mihai Maruseac Signed-off-by: David S. Miller Signed-off-by: Herton Ronaldo Krzesinski --- net/ipv6/addrconf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0344f8e..0808ad5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3093,14 +3093,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) struct hlist_node *n; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; /* sync with offset */ if (p < state->offset) { p++; continue; } state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } /* prepare for next bucket */ @@ -3118,18 +3119,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct hlist_node *n = &ifa->addr_lst; hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } while (++state->bucket < IN6_ADDR_HSIZE) { state->offset = 0; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } }