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:   Sat, 12 Nov 2016 16:40:29 +0100
From:   "Jason A. Donenfeld" <Jason@...c4.com>
To:     David Ahern <dsa@...ulusnetworks.com>
Cc:     Netdev <netdev@...r.kernel.org>,
        WireGuard mailing list <wireguard@...ts.zx2c4.com>,
        LKML <linux-kernel@...r.kernel.org>
Subject: Re: Source address fib invalidation on IPv6

Hi again,

I've done some pretty in depth debugging now to determine exactly what
the behavior of ipv6_stub->ipv6_dst_lookup is. First I'll start with
ip_route_output_flow, which I believe to be well behaved, and then
I'll show ipv6_stub->ipv6_dst_lookup, which seems ill-behaved:

Userspace:
    ip addr add 192.168.1.2/24 dev eth0
Kernelspace:
    struct flowi4 fl = {
       .saddr = 192.168.1.2,
       .daddr = 192.168.1.99,
    };
    rt = ip_route_output_flow(sock_net(sock), &fl, sock);
    // rt returns valid rt for routing to 192.168.1.99 from
192.168.1.2 using eth0
Userspace:
    ip addr add 192.168.1.3/24 dev eth0
    ip addr del 192.168.1.2/24 dev eth0
Kernelspace:
    struct flowi4 fl = {
       .saddr = 192.168.1.2,
       .daddr = 192.168.1.99,
    };
    rt = ip_route_output_flow(sock_net(sock), &fl, sock);
    // PTR_ERR(rt) == -EINVAL

This seems correct behavior to me, since no interface has 192.168.1.2
as a source address.

Now for the incorrect IPv6 behavior:

Userspace:
    ip -6 addr add abcd::2/96 dev eth0
Kernelspace:
    struct flowi6 fl = {
       .saddr = abcd::2,
       .daddr = abcd::99,
    };
    ret = ipv6_stub->ipv6_dst_lookup(sock_net(sock), sock, &dst, &fl);
    // ret is 0, and dst is a non-null dst routing to abcd::99 from
abcd::2 using eth0
Userspace:
    ip -6 addr add abcd::3/96 dev eth0
    ip -6 addr del abcd::2/96 dev eth0
Kernelspace:
    struct flowi6 fl = {
       .saddr = abcd::2,
       .daddr = abcd::99,
    };
    ret = ipv6_stub->ipv6_dst_lookup(sock_net(sock), sock, &dst, &fl);
    // ret is 0, and dst is a non-null dst routing to abcd::99 from
abcd::2 using eth0 **INCORRECT BEHAVIOR!**

This seems *INCORRECT* behavior to me, since no interface has abcd::2
as a source address.

So, to summarize, the problem is that ipv6_dst_lookup will happily
return a dst even though the source IP has been removed from the
interface.

I hope this clarifies things. I await your response.

Regards,
Jason

Powered by blists - more mailing lists