Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
Hi, Hajime Tazaki wrote: > > Yoshifuji-san, > > At Mon, 13 Jul 2015 17:38:48 +0900, > Erik Kline wrote: >> >> On 13 July 2015 at 15:32, YOSHIFUJI Hideaki >> wrote: >>> Hi, >>> >>> Erik Kline wrote: Hmm, when I run a UML linux with this patch (which, I'm ashamed to say, I failed to do before) I get these kinds of errors: unregister_netdevice: waiting for to become free. Usage count = 1 unregister_netdevice: waiting for to become free. Usage count = 1 Perhaps they're unrelated... I'm still investigating. >>> >>> Would you test attached patch please? >> >> That does look logically correct, so +1 to it regardless, but it does >> not seem to have fixed the issue I'm seeing. >> >> I still haven't produced the smallest possible demo test program. > > sorry to jump-in, but there is a side-effect with this > patch, which my tcp and dccp tests (ipv6) are failed. > > because newly added function (__ipv6_dev_get_saddr) won't > update a variable 'hiscore' (it swaps with 'score' in some > case), the caller (ipv6_dev_get_saddr) can't fill an > appropriate saddr in the end. > > I don't know if this is a good patch but the following diff > makes my test happy. We should update score as well... > > -- Hajime > > diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c > index 4ab74d5..c4e9416 100644 > --- a/net/ipv6/addrconf.c > +++ b/net/ipv6/addrconf.c > @@ -1363,7 +1363,8 @@ static void __ipv6_dev_get_saddr(struct net *net, >unsigned int prefs, >const struct in6_addr *saddr, >struct inet6_dev *idev, > - struct ipv6_saddr_score *scores) > + struct ipv6_saddr_score *scores, > + struct ipv6_saddr_score **in_hiscore) > { > struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1]; > > @@ -1424,6 +1425,7 @@ static void __ipv6_dev_get_saddr(struct net *net, > in6_ifa_hold(score->ifa); > > swap(hiscore, score); > + *in_hiscore = hiscore; > > /* restore our iterator */ > score->ifa = hiscore->ifa; > @@ -1480,13 +1482,15 @@ int ipv6_dev_get_saddr(struct net *net, const struct > net_device *dst_dev, > } > > if (use_oif_addr) { > - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores); > + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, > + scores, &hiscore); > } else { > for_each_netdev_rcu(net, dev) { > idev = __in6_dev_get(dev); > if (!idev) > continue; > - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, > scores); > + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, > + scores, &hiscore); > } > } > rcu_read_unlock(); > -- Hideaki Yoshifuji Technical Division, MIRACLE LINUX CORPORATION -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
Yoshifuji-san, At Mon, 13 Jul 2015 17:38:48 +0900, Erik Kline wrote: > > On 13 July 2015 at 15:32, YOSHIFUJI Hideaki > wrote: > > Hi, > > > > Erik Kline wrote: > >> Hmm, when I run a UML linux with this patch (which, I'm ashamed to > >> say, I failed to do before) I get these kinds of errors: > >> > >> unregister_netdevice: waiting for to become free. > >> Usage count = 1 > >> unregister_netdevice: waiting for to become free. > >> Usage count = 1 > >> > >> Perhaps they're unrelated... I'm still investigating. > > > > Would you test attached patch please? > > That does look logically correct, so +1 to it regardless, but it does > not seem to have fixed the issue I'm seeing. > > I still haven't produced the smallest possible demo test program. sorry to jump-in, but there is a side-effect with this patch, which my tcp and dccp tests (ipv6) are failed. because newly added function (__ipv6_dev_get_saddr) won't update a variable 'hiscore' (it swaps with 'score' in some case), the caller (ipv6_dev_get_saddr) can't fill an appropriate saddr in the end. I don't know if this is a good patch but the following diff makes my test happy. -- Hajime diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4ab74d5..c4e9416 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1363,7 +1363,8 @@ static void __ipv6_dev_get_saddr(struct net *net, unsigned int prefs, const struct in6_addr *saddr, struct inet6_dev *idev, -struct ipv6_saddr_score *scores) +struct ipv6_saddr_score *scores, +struct ipv6_saddr_score **in_hiscore) { struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1]; @@ -1424,6 +1425,7 @@ static void __ipv6_dev_get_saddr(struct net *net, in6_ifa_hold(score->ifa); swap(hiscore, score); + *in_hiscore = hiscore; /* restore our iterator */ score->ifa = hiscore->ifa; @@ -1480,13 +1482,15 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, } if (use_oif_addr) { - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores); + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, +scores, &hiscore); } else { for_each_netdev_rcu(net, dev) { idev = __in6_dev_get(dev); if (!idev) continue; - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores); + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, +scores, &hiscore); } } rcu_read_unlock(); -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
On 13 July 2015 at 15:32, YOSHIFUJI Hideaki wrote: > Hi, > > Erik Kline wrote: >> Hmm, when I run a UML linux with this patch (which, I'm ashamed to >> say, I failed to do before) I get these kinds of errors: >> >> unregister_netdevice: waiting for to become free. >> Usage count = 1 >> unregister_netdevice: waiting for to become free. >> Usage count = 1 >> >> Perhaps they're unrelated... I'm still investigating. > > Would you test attached patch please? That does look logically correct, so +1 to it regardless, but it does not seem to have fixed the issue I'm seeing. I still haven't produced the smallest possible demo test program. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
Hi, Erik Kline wrote: > Hmm, when I run a UML linux with this patch (which, I'm ashamed to > say, I failed to do before) I get these kinds of errors: > > unregister_netdevice: waiting for to become free. > Usage count = 1 > unregister_netdevice: waiting for to become free. > Usage count = 1 > > Perhaps they're unrelated... I'm still investigating. Would you test attached patch please? --yoshfuji > > On 11 July 2015 at 15:19, David Miller wrote: >> From: YOSHIFUJI Hideaki/吉藤英明 >> Date: Fri, 10 Jul 2015 16:58:31 +0900 >> >>> If outgoing interface is specified and the candidate address is >>> restricted to the outgoing interface, it is enough to iterate >>> over that given interface only. >>> >>> Signed-off-by: YOSHIFUJI Hideaki >>> Acked-by: Erik Kline >> >> Applied, thanks! -- Hideaki Yoshifuji Technical Division, MIRACLE LINUX CORPORATION >From 38c5a10a5876ea47766ffc05b5a131a210d6e1aa Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 13 Jul 2015 15:23:02 +0900 Subject: [PATCH] ipv6: Avoid NULL pointer dereference in __ipv6_dev_get_saddr(). Commit 9131f3de2 ("ipv6: Do not iterate over all interfaces when finding source address on specific interface.") introduced possible NULL pointer dereference if outgoing device is specified. Fixes: 9131f3de24db4dc12199aede7d931e6703e97f3b ("ipv6: Do not iterate over all interfaces when finding source address on specific interface.") Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/addrconf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4ab74d5..50ad476 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1480,7 +1480,8 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, } if (use_oif_addr) { - __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores); + if (idev) + __ipv6_dev_get_saddr(net, &dst, prefs, saddr, idev, scores); } else { for_each_netdev_rcu(net, dev) { idev = __in6_dev_get(dev); -- 1.9.1
Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
Hmm, when I run a UML linux with this patch (which, I'm ashamed to say, I failed to do before) I get these kinds of errors: unregister_netdevice: waiting for to become free. Usage count = 1 unregister_netdevice: waiting for to become free. Usage count = 1 Perhaps they're unrelated... I'm still investigating. On 11 July 2015 at 15:19, David Miller wrote: > From: YOSHIFUJI Hideaki/吉藤英明 > Date: Fri, 10 Jul 2015 16:58:31 +0900 > >> If outgoing interface is specified and the candidate address is >> restricted to the outgoing interface, it is enough to iterate >> over that given interface only. >> >> Signed-off-by: YOSHIFUJI Hideaki >> Acked-by: Erik Kline > > Applied, thanks! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
From: YOSHIFUJI Hideaki/吉藤英明 Date: Fri, 10 Jul 2015 16:58:31 +0900 > If outgoing interface is specified and the candidate address is > restricted to the outgoing interface, it is enough to iterate > over that given interface only. > > Signed-off-by: YOSHIFUJI Hideaki > Acked-by: Erik Kline Applied, thanks! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH net-next v2] ipv6: Do not iterate over all interfaces when finding source address on specific interface.
If outgoing interface is specified and the candidate address is restricted to the outgoing interface, it is enough to iterate over that given interface only. Signed-off-by: YOSHIFUJI Hideaki Acked-by: Erik Kline --- net/ipv6/addrconf.c | 197 1 file changed, 107 insertions(+), 90 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 21c2c81..4ab74d5 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1358,15 +1358,94 @@ out: return ret; } +static void __ipv6_dev_get_saddr(struct net *net, +struct ipv6_saddr_dst *dst, +unsigned int prefs, +const struct in6_addr *saddr, +struct inet6_dev *idev, +struct ipv6_saddr_score *scores) +{ + struct ipv6_saddr_score *score = &scores[0], *hiscore = &scores[1]; + + read_lock_bh(&idev->lock); + list_for_each_entry(score->ifa, &idev->addr_list, if_list) { + int i; + + /* +* - Tentative Address (RFC2462 section 5.4) +* - A tentative address is not considered +*"assigned to an interface" in the traditional +*sense, unless it is also flagged as optimistic. +* - Candidate Source Address (section 4) +* - In any case, anycast addresses, multicast +*addresses, and the unspecified address MUST +*NOT be included in a candidate set. +*/ + if ((score->ifa->flags & IFA_F_TENTATIVE) && + (!(score->ifa->flags & IFA_F_OPTIMISTIC))) + continue; + + score->addr_type = __ipv6_addr_type(&score->ifa->addr); + + if (unlikely(score->addr_type == IPV6_ADDR_ANY || +score->addr_type & IPV6_ADDR_MULTICAST)) { + net_dbg_ratelimited("ADDRCONF: unspecified / multicast address assigned as unicast address on %s", + idev->dev->name); + continue; + } + + score->rule = -1; + bitmap_zero(score->scorebits, IPV6_SADDR_RULE_MAX); + + for (i = 0; i < IPV6_SADDR_RULE_MAX; i++) { + int minihiscore, miniscore; + + minihiscore = ipv6_get_saddr_eval(net, hiscore, dst, i); + miniscore = ipv6_get_saddr_eval(net, score, dst, i); + + if (minihiscore > miniscore) { + if (i == IPV6_SADDR_RULE_SCOPE && + score->scopedist > 0) { + /* +* special case: +* each remaining entry +* has too small (not enough) +* scope, because ifa entries +* are sorted by their scope +* values. +*/ + goto out; + } + break; + } else if (minihiscore < miniscore) { + if (hiscore->ifa) + in6_ifa_put(hiscore->ifa); + + in6_ifa_hold(score->ifa); + + swap(hiscore, score); + + /* restore our iterator */ + score->ifa = hiscore->ifa; + + break; + } + } + } +out: + read_unlock_bh(&idev->lock); +} + int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, const struct in6_addr *daddr, unsigned int prefs, struct in6_addr *saddr) { - struct ipv6_saddr_score scores[2], - *score = &scores[0], *hiscore = &scores[1]; + struct ipv6_saddr_score scores[2], *hiscore = &scores[1]; struct ipv6_saddr_dst dst; + struct inet6_dev *idev; struct net_device *dev; int dst_type; + bool use_oif_addr = false; dst_type = __ipv6_addr_type(daddr); dst.addr = daddr; @@ -1380,97 +1459,35 @@ int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, rcu_read_lock(); - for_each_netdev_rcu(net, dev) { - struct inet6_dev *idev; - - /* Candidate Source Address (section 4) -* - multicast and link-local destination address, -*the set of candidate source address MUST only -*