Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Dec 2020 19:39:44 +0000 (UTC)
From:      Gordon Tetlow <gordon@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org
Subject:   svn commit: r368256 - in releng: 11.4/usr.sbin/rtsold 12.1/usr.sbin/rtsold 12.2/usr.sbin/rtsold
Message-ID:  <202012011939.0B1JdiYr004472@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gordon
Date: Tue Dec  1 19:39:44 2020
New Revision: 368256
URL: https://svnweb.freebsd.org/changeset/base/368256

Log:
  Fix multiple vulnerabilities in rtsold.
  
  Approved by:	so
  Security:	FreeBSD-SA-20:32.rtsold
  Security:	CVE-2020-25577

Modified:
  releng/11.4/usr.sbin/rtsold/rtsol.c
  releng/12.1/usr.sbin/rtsold/rtsol.c
  releng/12.2/usr.sbin/rtsold/rtsol.c

Modified: releng/11.4/usr.sbin/rtsold/rtsol.c
==============================================================================
--- releng/11.4/usr.sbin/rtsold/rtsol.c	Tue Dec  1 19:38:52 2020	(r368255)
+++ releng/11.4/usr.sbin/rtsold/rtsol.c	Tue Dec  1 19:39:44 2020	(r368256)
@@ -390,8 +390,8 @@ rtsol_input(int s)
 		newent_rai = 1;
 	}
 
-#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)x + \
-				(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
+#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)(x) + \
+				(((struct nd_opt_hdr *)(x))->nd_opt_len * 8))
 	/* Process RA options. */
 	warnmsg(LOG_DEBUG, __func__, "Processing RA");
 	raoptp = (char *)icp + sizeof(struct nd_router_advert);
@@ -403,6 +403,15 @@ rtsol_input(int s)
 		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d",
 		    ndo->nd_opt_len);
 
+		if (ndo->nd_opt_len == 0) {
+			warnmsg(LOG_INFO, __func__, "invalid option length 0.");
+			break;
+		}
+		if ((char *)RA_OPT_NEXT_HDR(raoptp) > (char *)icp + msglen) {
+			warnmsg(LOG_INFO, __func__, "option length overflow.");
+			break;
+		}
+
 		switch (ndo->nd_opt_type) {
 		case ND_OPT_RDNSS:
 			rdnss = (struct nd_opt_rdnss *)raoptp;
@@ -932,15 +941,18 @@ dname_labeldec(char *dst, size_t dlen, const char *src
 	src_last = strchr(src, '\0');
 	dst_origin = dst;
 	memset(dst, '\0', dlen);
-	while (src && (len = (uint8_t)(*src++) & 0x3f) &&
-	    (src + len) <= src_last &&
-	    (dst - dst_origin < (ssize_t)dlen)) {
-		if (dst != dst_origin)
+	while ((len = (*src++) & 0x3f) &&
+	    src + len <= src_last &&
+	    len + 1 + (dst == dst_origin ? 0 : 1) <= dlen) {
+		if (dst != dst_origin) {
 			*dst++ = '.';
+			dlen--;
+		}
 		warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
 		memcpy(dst, src, len);
 		src += len;
 		dst += len;
+		dlen -= len;
 	}
 	*dst = '\0';
 

Modified: releng/12.1/usr.sbin/rtsold/rtsol.c
==============================================================================
--- releng/12.1/usr.sbin/rtsold/rtsol.c	Tue Dec  1 19:38:52 2020	(r368255)
+++ releng/12.1/usr.sbin/rtsold/rtsol.c	Tue Dec  1 19:39:44 2020	(r368256)
@@ -390,8 +390,8 @@ rtsol_input(int s)
 		newent_rai = 1;
 	}
 
-#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)x + \
-				(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
+#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)(x) + \
+				(((struct nd_opt_hdr *)(x))->nd_opt_len * 8))
 	/* Process RA options. */
 	warnmsg(LOG_DEBUG, __func__, "Processing RA");
 	raoptp = (char *)icp + sizeof(struct nd_router_advert);
@@ -403,6 +403,15 @@ rtsol_input(int s)
 		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d",
 		    ndo->nd_opt_len);
 
+		if (ndo->nd_opt_len == 0) {
+			warnmsg(LOG_INFO, __func__, "invalid option length 0.");
+			break;
+		}
+		if ((char *)RA_OPT_NEXT_HDR(raoptp) > (char *)icp + msglen) {
+			warnmsg(LOG_INFO, __func__, "option length overflow.");
+			break;
+		}
+
 		switch (ndo->nd_opt_type) {
 		case ND_OPT_RDNSS:
 			rdnss = (struct nd_opt_rdnss *)raoptp;
@@ -924,15 +933,18 @@ dname_labeldec(char *dst, size_t dlen, const char *src
 	src_last = strchr(src, '\0');
 	dst_origin = dst;
 	memset(dst, '\0', dlen);
-	while (src && (len = (uint8_t)(*src++) & 0x3f) &&
-	    (src + len) <= src_last &&
-	    (dst - dst_origin < (ssize_t)dlen)) {
-		if (dst != dst_origin)
+	while ((len = (*src++) & 0x3f) &&
+	    src + len <= src_last &&
+	    len + 1 + (dst == dst_origin ? 0 : 1) <= dlen) {
+		if (dst != dst_origin) {
 			*dst++ = '.';
+			dlen--;
+		}
 		warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
 		memcpy(dst, src, len);
 		src += len;
 		dst += len;
+		dlen -= len;
 	}
 	*dst = '\0';
 

Modified: releng/12.2/usr.sbin/rtsold/rtsol.c
==============================================================================
--- releng/12.2/usr.sbin/rtsold/rtsol.c	Tue Dec  1 19:38:52 2020	(r368255)
+++ releng/12.2/usr.sbin/rtsold/rtsol.c	Tue Dec  1 19:39:44 2020	(r368256)
@@ -337,8 +337,8 @@ rtsol_input(int sock)
 		newent_rai = 1;
 	}
 
-#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)x + \
-				(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
+#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)(x) + \
+				(((struct nd_opt_hdr *)(x))->nd_opt_len * 8))
 	/* Process RA options. */
 	warnmsg(LOG_DEBUG, __func__, "Processing RA");
 	raoptp = (char *)icp + sizeof(struct nd_router_advert);
@@ -350,6 +350,15 @@ rtsol_input(int sock)
 		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d",
 		    ndo->nd_opt_len);
 
+		if (ndo->nd_opt_len == 0) {
+			warnmsg(LOG_INFO, __func__, "invalid option length 0.");
+			break;
+		}
+		if ((char *)RA_OPT_NEXT_HDR(raoptp) > (char *)icp + msglen) {
+			warnmsg(LOG_INFO, __func__, "option length overflow.");
+			break;
+		}
+
 		switch (ndo->nd_opt_type) {
 		case ND_OPT_RDNSS:
 			rdnss = (struct nd_opt_rdnss *)raoptp;
@@ -760,15 +769,18 @@ dname_labeldec(char *dst, size_t dlen, const char *src
 	src_last = strchr(src, '\0');
 	dst_origin = dst;
 	memset(dst, '\0', dlen);
-	while (src && (len = (uint8_t)(*src++) & 0x3f) &&
-	    (src + len) <= src_last &&
-	    (dst - dst_origin < (ssize_t)dlen)) {
-		if (dst != dst_origin)
+	while ((len = (*src++) & 0x3f) &&
+	    src + len <= src_last &&
+	    len + 1 + (dst == dst_origin ? 0 : 1) <= dlen) {
+		if (dst != dst_origin) {
 			*dst++ = '.';
+			dlen--;
+		}
 		warnmsg(LOG_DEBUG, __func__, "labellen = %zd", len);
 		memcpy(dst, src, len);
 		src += len;
 		dst += len;
+		dlen -= len;
 	}
 	*dst = '\0';
 



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