git: aa71d6b4a2ec - main - netinet: Disallow unspecified addresses in ICMP-embedded packets

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 13 Mar 2023 14:51:09 UTC
The branch main has been updated by markj:

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

commit aa71d6b4a2ec3609303ca87ba75d0a2c539da9df
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-03-13 14:45:56 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-03-13 14:45:56 +0000

    netinet: Disallow unspecified addresses in ICMP-embedded packets
    
    Reported by:    glebius
    Reported by:    syzbot+981c528ccb5c5534dffc@syzkaller.appspotmail.com
    Reviewed by:    tuexen, glebius
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D38936
---
 sys/netinet/ip_icmp.c | 3 ++-
 sys/netinet6/icmp6.c  | 8 ++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index 98f290486ec5..9352289d62fe 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -561,7 +561,8 @@ icmp_input(struct mbuf **mp, int *offp, int proto)
 		if (IN_MULTICAST(ntohl(icp->icmp_ip.ip_dst.s_addr)))
 			goto badcode;
 		/* Filter out responses to INADDR_ANY, protocols ignore it. */
-		if (icp->icmp_ip.ip_dst.s_addr == INADDR_ANY)
+		if (icp->icmp_ip.ip_dst.s_addr == INADDR_ANY ||
+		    icp->icmp_ip.ip_src.s_addr == INADDR_ANY)
 			goto freeit;
 #ifdef ICMPPRINTFS
 		if (icmpprintfs)
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 5c94a0c56be1..4166cabdc5cb 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1070,6 +1070,14 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len)
 		 */
 		eip6 = (struct ip6_hdr *)(icmp6 + 1);
 
+		/*
+		 * Protocol layers can't do anything useful with unspecified
+		 * addresses.
+		 */
+		if (IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_src) ||
+		    IN6_IS_ADDR_UNSPECIFIED(&eip6->ip6_dst))
+			goto freeit;
+
 		icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
 		icmp6dst.sin6_family = AF_INET6;
 		if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))