lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 20 May 2019 10:58:04 -0600
From:   David Ahern <dsahern@...il.com>
To:     Mike Manning <mmanning@...tta.att-mail.com>, netdev@...r.kernel.org
Subject: Re: [PATCH net] net/ipv6: Reinstate ping/traceroute use with source
 address in VRF

On 5/20/19 2:40 AM, Mike Manning wrote:
> Since the commit 1893ff20275b ("net/ipv6: Add l3mdev check to
> ipv6_chk_addr_and_flags"), traceroute using TCP SYN or ICMP ECHO option
> and ping fail when specifying a source address typically on a loopback
> /dummy interface in the same VRF, e.g.:
> 
>     # ip vrf exec vrfgreen ping 3000::1 -I 2222::2
>     ping: bind icmp socket: Cannot assign requested address
>     # ip vrf exec vrfgreen traceroute 3000::1 -s 2222::2 -T
>     bind: Cannot assign requested address
> 
> IPv6 traceroute using default UDP and IPv4 ping & traceroute continue
> to work inside a VRF using a source address.
> 
> The reason is that the source address is provided via bind without a
> device given by these applications in this case. The call to
> ipv6_check_addr() in rawv6_bind() returns false as the default VRF is
> assumed if no dev was given, but the src addr is in a non-default VRF.
> 
> The solution is to check that the address exists in the L3 domain that
> the dev is part of only if the dev has been specified.
> 
> Signed-off-by: Mike Manning <mmanning@...tta.att-mail.com>
> ---
>  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 f96d1de79509..3963306ec27f 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -1908,6 +1908,7 @@ int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
>  			    int strict, u32 banned_flags)
>  {
>  	unsigned int hash = inet6_addr_hash(net, addr);
> +	const struct net_device *orig_dev = dev;
>  	const struct net_device *l3mdev;
>  	struct inet6_ifaddr *ifp;
>  	u32 ifp_flags;
> @@ -1922,7 +1923,7 @@ int ipv6_chk_addr_and_flags(struct net *net, const struct in6_addr *addr,
>  		if (!net_eq(dev_net(ifp->idev->dev), net))
>  			continue;
>  
> -		if (l3mdev_master_dev_rcu(ifp->idev->dev) != l3mdev)
> +		if (orig_dev && l3mdev_master_dev_rcu(ifp->idev->dev) != l3mdev)
>  			continue;
>  
>  		/* Decouple optimistic from tentative for evaluation here.
> 

Wrong fix. When looking up the address you have to give the L3 domain of
interest.

This change:

diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 84dbe21b71e5..96a3559f2a09 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -287,7 +287,9 @@ static int rawv6_bind(struct sock *sk, struct
sockaddr *uaddr, int addr_len)
                        /* Binding to link-local address requires an
interface */
                        if (!sk->sk_bound_dev_if)
                                goto out_unlock;
+               }

+               if (sk->sk_bound_dev_if) {
                        err = -ENODEV;
                        dev = dev_get_by_index_rcu(sock_net(sk),
                                                   sk->sk_bound_dev_if);

make raw binds similar to tcp. See:

c5ee066333ebc ("ipv6: Consider sk_bound_dev_if when binding a socket to
an address")
ec90ad334986f ("ipv6: Consider sk_bound_dev_if when binding a socket to
a v4 mapped address")

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ