--- usr.sbin/rtsold/rtsol.c.orig +++ usr.sbin/rtsold/rtsol.c @@ -337,8 +337,8 @@ 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 @@ 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 @@ 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';