On Wed, 2 Oct 2019 09:38:55 -0700 Eric Dumazet wrote: > This began with a syzbot report. syzkaller was injecting > IPv6 TCP SYN packets having a v4mapped source address. > > After an unsuccessful 4-tuple lookup, TCP creates a request > socket (SYN_RECV) and calls reqsk_queue_hash_req() > > reqsk_queue_hash_req() calls sk_ehashfn(sk) > > At this point we have AF_INET6 sockets, and the heuristic > used by sk_ehashfn() to either hash the IPv4 or IPv6 addresses > is to use ipv6_addr_v4mapped(&sk->sk_v6_daddr) > > For the particular spoofed packet, we end up hashing V4 addresses > which were not initialized by the TCP IPv6 stack, so KMSAN fired > a warning. > > I first fixed sk_ehashfn() to test both source and destination addresses, > but then faced various problems, including user-space programs > like packetdrill that had similar assumptions. > > Instead of trying to fix the whole ecosystem, it is better > to admit that we have a dual stack behavior, and that we > can not build linux kernels without V4 stack anyway. > > The dual stack API automatically forces the traffic to be IPv4 > if v4mapped addresses are used at bind() or connect(), so it makes > no sense to allow IPv6 traffic to use the same v4mapped class. > > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Signed-off-by: Eric Dumazet <eduma...@google.com> > Cc: Florian Westphal <f...@strlen.de> > Cc: Hannes Frederic Sowa <han...@stressinduktion.org> > Reported-by: syzbot <syzkal...@googlegroups.com>
FTR this appears to break an UDP/sFlow application which used to work fine with mapped addresses. Given the IETF memo perhaps a sysctl would be appropriate, but even with that we're back to problems in TCP if the sysctl is flipped :S > diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c > index > d432d0011c160f41aec09640e95179dd7b364cfc..2bb0b66181a741c7fb73cacbdf34c5160f52d186 > 100644 > --- a/net/ipv6/ip6_input.c > +++ b/net/ipv6/ip6_input.c > @@ -223,6 +223,16 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, > struct net_device *dev, > if (ipv6_addr_is_multicast(&hdr->saddr)) > goto err; > > + /* While RFC4291 is not explicit about v4mapped addresses > + * in IPv6 headers, it seems clear linux dual-stack > + * model can not deal properly with these. > + * Security models could be fooled by ::ffff:127.0.0.1 for example. > + * > + * https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02 > + */ > + if (ipv6_addr_v4mapped(&hdr->saddr)) > + goto err; > + > skb->transport_header = skb->network_header + sizeof(*hdr); > IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); >