Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Mar 2023 13:33:48 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 795fda214f11 - stable/13 - netinet: Tighten checks for unspecified source addresses
Message-ID:  <202303201333.32KDXmnB073696@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=795fda214f11ebb58b335fd064f736708df6b3ff

commit 795fda214f11ebb58b335fd064f736708df6b3ff
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-03-06 20:06:00 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-03-20 13:00:56 +0000

    netinet: Tighten checks for unspecified source addresses
    
    The assertions added in commit b0ccf53f2455 ("inpcb: Assert against
    wildcard addrs in in_pcblookup_hash_locked()") revealed that protocol
    layers may pass the unspecified address to in_pcblookup().
    
    Add some checks to filter out such packets before we attempt an inpcb
    lookup:
    - Disallow the use of an unspecified source address in in_pcbladdr() and
      in6_pcbladdr().
    - Disallow IP packets with an unspecified destination address.
    - Disallow TCP packets with an unspecified source address, and add an
      assertion to verify the comment claiming that the case of an
      unspecified destination address is handled by the IP layer.
    
    Reported by:    syzbot+9ca890fb84e984e82df2@syzkaller.appspotmail.com
    Reported by:    syzbot+ae873c71d3c71d5f41cb@syzkaller.appspotmail.com
    Reported by:    syzbot+e3e689aba1d442905067@syzkaller.appspotmail.com
    Reviewed by:    glebius, melifaro
    MFC after:      2 weeks
    Sponsored by:   Klara, Inc.
    Sponsored by:   Modirum MDPay
    Differential Revision:  https://reviews.freebsd.org/D38570
    
    (cherry picked from commit 713264f6b8bc5f927dd52cf8ffcccfa397034fec)
---
 sys/netinet/in_pcb.c    | 2 ++
 sys/netinet/ip_input.c  | 5 +++++
 sys/netinet/tcp_input.c | 8 ++++++++
 sys/netinet6/in6_pcb.c  | 2 ++
 4 files changed, 17 insertions(+)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 55fa795457cb..d10bd9b32e89 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1338,6 +1338,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
 	}
 
 done:
+	if (error == 0 && laddr->s_addr == INADDR_ANY)
+		return (EHOSTUNREACH);
 	return (error);
 }
 
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 750ddfc3a46f..2cfd3c544c72 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -515,6 +515,11 @@ ip_input(struct mbuf *m)
 			goto bad;
 		}
 	}
+	/* The unspecified address can appear only as a src address - RFC1122 */
+	if (__predict_false(ntohl(ip->ip_dst.s_addr) == INADDR_ANY)) {
+		IPSTAT_INC(ips_badaddr);
+		goto bad;
+	}
 
 	if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
 		sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 1c2fe014c7f3..9bc9923530e0 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -715,6 +715,8 @@ tcp_input_with_port(struct mbuf **mp, int *offp, int proto, uint16_t port)
 		 * Note that packets with unspecified IPv6 destination is
 		 * already dropped in ip6_input.
 		 */
+		KASSERT(!IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst),
+		    ("%s: unspecified destination v6 address", __func__));
 		if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
 			/* XXX stat */
 			goto drop;
@@ -783,6 +785,12 @@ tcp_input_with_port(struct mbuf **mp, int *offp, int proto, uint16_t port)
 			TCPSTAT_INC(tcps_rcvbadsum);
 			goto drop;
 		}
+		KASSERT(ip->ip_dst.s_addr != INADDR_ANY,
+		    ("%s: unspecified destination v4 address", __func__));
+		if (__predict_false(ip->ip_src.s_addr == INADDR_ANY)) {
+			/* XXX stat */
+			goto drop;
+		}
 	}
 #endif /* INET */
 
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 02fd3dff2ad7..ab04d402cf96 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -376,6 +376,8 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr_in6 *sin6,
 	NET_EPOCH_EXIT(et);
 	if (error)
 		return (error);
+	if (IN6_IS_ADDR_UNSPECIFIED(&in6a))
+		return (EHOSTUNREACH);
 
 	/*
 	 * Do not update this earlier, in case we return with an error.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202303201333.32KDXmnB073696>