aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2019-10-02 12:38:55 -0400
committerDavid S. Miller <davem@davemloft.net>2019-10-03 11:40:21 -0400
commit6af1799aaf3f1bc8defedddfa00df3192445bbf3 (patch)
treee8838a12f9419244da2a0cf80f3f13843f50acdb
parent134cc4cefad34d8d24670d8a911b59c3b89c6731 (diff)
ipv6: drop incoming packets having a v4mapped source address
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 <edumazet@google.com> Cc: Florian Westphal <fw@strlen.de> Cc: Hannes Frederic Sowa <hannes@stressinduktion.org> Reported-by: syzbot <syzkaller@googlegroups.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/ip6_input.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 7e5df23cbe7b..3d71c7d6102c 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,
223 if (ipv6_addr_is_multicast(&hdr->saddr)) 223 if (ipv6_addr_is_multicast(&hdr->saddr))
224 goto err; 224 goto err;
225 225
226 /* While RFC4291 is not explicit about v4mapped addresses
227 * in IPv6 headers, it seems clear linux dual-stack
228 * model can not deal properly with these.
229 * Security models could be fooled by ::ffff:127.0.0.1 for example.
230 *
231 * https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02
232 */
233 if (ipv6_addr_v4mapped(&hdr->saddr))
234 goto err;
235
226 skb->transport_header = skb->network_header + sizeof(*hdr); 236 skb->transport_header = skb->network_header + sizeof(*hdr);
227 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); 237 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
228 238