]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ipv6: weaken the v4mapped source check
authorJakub Kicinski <kuba@kernel.org>
Wed, 17 Mar 2021 16:55:15 +0000 (09:55 -0700)
committerDavid S. Miller <davem@davemloft.net>
Thu, 18 Mar 2021 18:19:23 +0000 (11:19 -0700)
This reverts commit 6af1799aaf3f1bc8defedddfa00df3192445bbf3.

Commit 6af1799aaf3f ("ipv6: drop incoming packets having a v4mapped
source address") introduced an input check against v4mapped addresses.
Use of such addresses on the wire is indeed questionable and not
allowed on public Internet. As the commit pointed out

  https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02

lists potential issues.

Unfortunately there are applications which use v4mapped addresses,
and breaking them is a clear regression. For example v4mapped
addresses (or any semi-valid addresses, really) may be used
for uni-direction event streams or packet export.

Since the issue which sparked the addition of the check was with
TCP and request_socks in particular push the check down to TCPv6
and DCCP. This restores the ability to receive UDPv6 packets with
v4mapped address as the source.

Keep using the IPSTATS_MIB_INHDRERRORS statistic to minimize the
user-visible changes.

Fixes: 6af1799aaf3f ("ipv6: drop incoming packets having a v4mapped source address")
Reported-by: Sunyi Shao <sunyishao@fb.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Acked-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/dccp/ipv6.c
net/ipv6/ip6_input.c
net/ipv6/tcp_ipv6.c
net/mptcp/subflow.c

index 1f73603913f5aeacdcb2554ed695e51262c0b2ba..2be5c69824f94423e2f90b97938dd623a4fea9c7 100644 (file)
@@ -319,6 +319,11 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (!ipv6_unicast_destination(skb))
                return 0;       /* discard, don't send a reset here */
 
+       if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) {
+               __IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS);
+               return 0;
+       }
+
        if (dccp_bad_service_code(sk, service)) {
                dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE;
                goto drop;
index e9d2a4a409aabef2d4b76cc6a8ae9d3ce8da0183..80256717868e69766acb3b590680f34a4ed1c0e9 100644 (file)
@@ -245,16 +245,6 @@ 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);
 
index bd44ded7e50c19d393433a9b7cd18384677f746f..d0f007741e8ed3638999823ca0637f870a3a7c2c 100644 (file)
@@ -1175,6 +1175,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (!ipv6_unicast_destination(skb))
                goto drop;
 
+       if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) {
+               __IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS);
+               return 0;
+       }
+
        return tcp_conn_request(&tcp6_request_sock_ops,
                                &tcp_request_sock_ipv6_ops, sk, skb);
 
index 3d47d670e66546f2f4cd4be7588cead55687be06..d17d39ccdf34bbd14d7f79b2c9b90173ce25f06f 100644 (file)
@@ -477,6 +477,11 @@ static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (!ipv6_unicast_destination(skb))
                goto drop;
 
+       if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) {
+               __IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS);
+               return 0;
+       }
+
        return tcp_conn_request(&mptcp_subflow_request_sock_ops,
                                &subflow_request_sock_ipv6_ops, sk, skb);