Author: markj
Date: Tue Dec  1 19:34:44 2020
New Revision: 368248
URL: https://svnweb.freebsd.org/changeset/base/368248

Log:
  rtsold: Fix multiple buffer overflows
  
  Approved by:  so
  Security:     CVE-2020-25577
  MFC after:    now

Modified:
  head/usr.sbin/rtsold/rtsol.c

Modified: head/usr.sbin/rtsold/rtsol.c
==============================================================================
--- head/usr.sbin/rtsold/rtsol.c        Tue Dec  1 18:57:37 2020        
(r368247)
+++ head/usr.sbin/rtsold/rtsol.c        Tue Dec  1 19:34:44 2020        
(r368248)
@@ -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 + (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';
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to