git: 7e88d8fec4e8 - stable/14 - route: error on IPv4 network routes with incorrect destination

From: Mike Karels <karels_at_FreeBSD.org>
Date: Mon, 22 Jan 2024 16:42:41 UTC
The branch stable/14 has been updated by karels:

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

commit 7e88d8fec4e8adc258378c7a68adf6cef1da8ad4
Author:     Mike Karels <karels@FreeBSD.org>
AuthorDate: 2024-01-15 21:14:54 +0000
Commit:     Mike Karels <karels@FreeBSD.org>
CommitDate: 2024-01-22 16:42:16 +0000

    route: error on IPv4 network routes with incorrect destination
    
    Route destinations like 10/8 are most likely intended as a shorthand
    for 10.0.0.0/8, but instead it means 0.0.0.10/8, which includes
    only bits in the host part of the mask, and hence adds a route to
    0.0.0.0/8.  In 12.x, there was code to "do what I mean", which was
    removed as part of a cleanup of old network class remnants.  Given
    that we have gone this long without that code, do not restore that
    behavior.  Instead, detect the issue and produce an error.
    Specifically, if there are no dots in a numeric IPv4 address, the
    mask is specified with CIDR notation (using a slash), and there are
    bits set in the host part, produce an error like this for 10/8:
    
        route: malformed address, bits set after mask; 10 means 0.0.0.10
    
    PR:             258874
    Reviewed by:    melifaro, emaste
    Differential Revision:  https://reviews.freebsd.org/D43384
    
    (cherry picked from commit b9e8ae1d8a424194b4e185359da4ded163f24f4e)
---
 sbin/route/route.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/sbin/route/route.c b/sbin/route/route.c
index 3913bdc9e6af..7cf2bf842559 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -1342,6 +1342,9 @@ getaddr(int idx, char *str, int nrflags)
 	q = strchr(str,'/');
 	if (q != NULL && idx == RTAX_DST) {
 		/* A.B.C.D/NUM */
+		struct sockaddr_in *mask;
+		uint32_t mask_bits;
+
 		*q = '\0';
 		if (inet_aton(str, &sin->sin_addr) == 0)
 			errx(EX_NOHOST, "bad address: %s", str);
@@ -1351,6 +1354,20 @@ getaddr(int idx, char *str, int nrflags)
 			errx(EX_NOHOST, "bad mask length: %s", q + 1);
 
 		inet_makemask((struct sockaddr_in *)&so[RTAX_NETMASK],masklen);
+
+		/*
+		 * Check for bogus destination such as "10/8"; heuristic is
+		 * that there are bits set in the host part, and no dot
+		 * is present.
+		 */
+		mask = ((struct sockaddr_in *) &so[RTAX_NETMASK]);
+		mask_bits = ntohl(mask->sin_addr.s_addr);
+		if ((ntohl(sin->sin_addr.s_addr) & ~mask_bits) != 0 &&
+		    strchr(str, '.') == NULL)
+			errx(EX_NOHOST,
+			    "malformed address, bits set after mask;"
+			    " %s means %s",
+			    str, inet_ntoa(sin->sin_addr));
 		return (0);
 	}
 	if (inet_aton(str, &sin->sin_addr) != 0)