git: 0c605af3f9d9 - main - netinet: Explicitly disallow connections to the unspecified address

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 29 Aug 2024 13:51:09 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=0c605af3f9d9e66be6af0a3bbc36dbedc5dfe516

commit 0c605af3f9d9e66be6af0a3bbc36dbedc5dfe516
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-08-29 13:11:15 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-08-29 13:11:15 +0000

    netinet: Explicitly disallow connections to the unspecified address
    
    If the V_connect_ifaddr_wild sysctl says that we shouldn't infer a
    destination address, return an error.  Otherwise it's possible for use
    of an unspecified foreign address to trigger a subsequent assertion
    failure, for example in in_pcblookup_hash_locked().
    
    Similarly, if no interface addresses are assigned, fail quickly upon an
    attempt to connect to the unspecified address.
    
    Reported by:    Shawn Webb <shawn.webb@hardenedbsd.org>
    MFC after:      2 weeks
    Reviewed by:    zlei, allanjude, emaste
    Differential Revision:  https://reviews.freebsd.org/D46454
---
 sys/netinet/in_pcb.c   | 2 ++
 sys/netinet6/in6_pcb.c | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 70ddd581895f..6ea197cf68d8 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1336,6 +1336,8 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr_in *sin,
 				faddr = satosin(&CK_STAILQ_FIRST(
 				    &V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
 		}
+	} else if (faddr.s_addr == INADDR_ANY) {
+		return (ENETUNREACH);
 	}
 	if (laddr.s_addr == INADDR_ANY) {
 		error = in_pcbladdr(inp, &faddr, &laddr, cred);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 098b4e50483c..501434f2fac6 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -368,7 +368,10 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr_in6 *sin6,
 		 */
 		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
 			sin6->sin6_addr = in6addr_loopback;
+	} else if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+		return (ENETUNREACH);
 	}
+
 	if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
 		return (error);