Module Name:    src
Committed By:   christos
Date:           Sun Apr 24 17:56:31 UTC 2016

Modified Files:
        src/sys/net: if_spppsubr.c

Log Message:
CID 1210544: Tainted scalar


To generate a diff of this commit:
cvs rdiff -u -r1.139 -r1.140 src/sys/net/if_spppsubr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/if_spppsubr.c
diff -u src/sys/net/if_spppsubr.c:1.139 src/sys/net/if_spppsubr.c:1.140
--- src/sys/net/if_spppsubr.c:1.139	Sun Apr 24 13:32:06 2016
+++ src/sys/net/if_spppsubr.c	Sun Apr 24 13:56:31 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_spppsubr.c,v 1.139 2016/04/24 17:32:06 christos Exp $	 */
+/*	$NetBSD: if_spppsubr.c,v 1.140 2016/04/24 17:56:31 christos Exp $	 */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.139 2016/04/24 17:32:06 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.140 2016/04/24 17:56:31 christos Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -1259,7 +1259,7 @@ sppp_cp_send(struct sppp *sp, u_short pr
 	lh->ident = ident;
 	lh->len = htons(LCP_HEADER_LEN + len);
 	if (len)
-		bcopy (data, lh + 1, len);
+		memcpy(lh + 1, data, len);
 
 	if (debug) {
 		log(LOG_DEBUG, "%s: %s output <%s id=0x%x len=%d",
@@ -2067,14 +2067,14 @@ static int
 sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
 {
 	STDDCL;
-	u_char *buf, *r, *p;
+	u_char *buf, *r, *p, l, blen;
 	int origlen, rlen;
 	uint32_t nmagic;
 	u_short authproto;
 
 	len -= 4;
 	origlen = len;
-	buf = r = malloc (len, M_TEMP, M_NOWAIT);
+	buf = r = malloc (blen = len, M_TEMP, M_NOWAIT);
 	if (! buf)
 		return (0);
 
@@ -2084,16 +2084,16 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
 
 	/* pass 1: check for things that need to be rejected */
 	p = (void *)(h + 1);
-	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+	for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/*
 			 * Malicious option - drop immediately.
 			 * XXX Maybe we should just RXJ it?
 			 */
 			addlog("%s: received malicious LCP option 0x%02x, "
 			    "length 0x%02x, (len: 0x%02x) dropping.\n", ifp->if_xname,
-			    p[0], p[1], len);
+			    p[0], l, len);
 			goto drop;
 		}
 		if (debug)
@@ -2104,14 +2104,14 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
 			/* fall through, both are same length */
 		case LCP_OPT_ASYNC_MAP:
 			/* Async control character map. */
-			if (len >= 6 || p[1] == 6)
+			if (len >= 6 || l == 6)
 				continue;
 			if (debug)
 				addlog(" [invalid]");
 			break;
 		case LCP_OPT_MRU:
 			/* Maximum receive unit. */
-			if (len >= 4 && p[1] == 4)
+			if (len >= 4 && l == 4)
 				continue;
 			if (debug)
 				addlog(" [invalid]");
@@ -2123,7 +2123,7 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
 				break;
 			}
 			authproto = (p[2] << 8) + p[3];
-			if (authproto == PPP_CHAP && p[1] != 5) {
+			if (authproto == PPP_CHAP && l != 5) {
 				if (debug)
 					addlog(" [invalid chap len]");
 				break;
@@ -2147,10 +2147,15 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
 				addlog(" [rej]");
 			break;
 		}
+		if (rlen + l > blen) {
+			if (debug)
+				addlog(" [overflow]");
+			continue;
+		}
 		/* Add the option to rejected list. */
-		bcopy (p, r, p[1]);
-		r += p[1];
-		rlen += p[1];
+		memcpy(r, p, l);
+		r += l;
+		rlen += l;
 	}
 	if (rlen) {
 		if (debug)
@@ -2170,7 +2175,7 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
 
 	p = (void *)(h + 1);
 	len = origlen;
-	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+	for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		if (debug)
 			addlog(" %s", sppp_lcp_opt_name(*p));
 		switch (*p) {
@@ -2260,10 +2265,15 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp
 			}
 			continue;
 		}
+		if (rlen + l > blen) {
+			if (debug)
+				addlog(" [overflow]");
+			continue;
+		}
 		/* Add the option to nak'ed list. */
-		bcopy (p, r, p[1]);
-		r += p[1];
-		rlen += p[1];
+		memcpy(r, p, l);
+		r += l;
+		rlen += l;
 	}
 	if (rlen) {
 		if (++sp->fail_counter[IDX_LCP] >= sp->lcp.max_failure) {
@@ -2303,7 +2313,7 @@ static void
 sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
 {
 	STDDCL;
-	u_char *buf, *p;
+	u_char *buf, *p, l;
 
 	len -= 4;
 	buf = malloc (len, M_TEMP, M_NOWAIT);
@@ -2315,9 +2325,9 @@ sppp_lcp_RCN_rej(struct sppp *sp, struct
 		    ifp->if_xname);
 
 	p = (void *)(h + 1);
-	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
+	for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/*
 			 * Malicious option - drop immediately.
 			 * XXX Maybe we should just RXJ it?
@@ -2384,11 +2394,11 @@ static void
 sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
 {
 	STDDCL;
-	u_char *buf, *p;
+	u_char *buf, *p, l, blen;
 	uint32_t magic;
 
 	len -= 4;
-	buf = malloc (len, M_TEMP, M_NOWAIT);
+	buf = malloc (blen = len, M_TEMP, M_NOWAIT);
 	if (!buf)
 		return;
 
@@ -2397,9 +2407,9 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
 		    ifp->if_xname);
 
 	p = (void *)(h + 1);
-	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
+	for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/*
 			 * Malicious option - drop immediately.
 			 * XXX Maybe we should just RXJ it?
@@ -2414,7 +2424,7 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
 		case LCP_OPT_MAGIC:
 			/* Magic number -- renegotiate */
 			if ((sp->lcp.opts & (1 << LCP_OPT_MAGIC)) &&
-			    len >= 6 && p[1] == 6) {
+			    len >= 6 && l == 6) {
 				magic = (uint32_t)p[2] << 24 |
 					(uint32_t)p[3] << 16 | p[4] << 8 | p[5];
 				/*
@@ -2439,7 +2449,7 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct
 			 * Agree on it if it's reasonable, or use
 			 * default otherwise.
 			 */
-			if (len >= 4 && p[1] == 4) {
+			if (len >= 4 && l == 4) {
 				u_int mru = p[2] * 256 + p[3];
 				if (debug)
 					addlog(" %d", mru);
@@ -2791,7 +2801,7 @@ sppp_ipcp_TO(void *cookie)
 static int
 sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len)
 {
-	u_char *buf, *r, *p;
+	u_char *buf, *r, *p, l, blen;
 	struct ifnet *ifp = &sp->pp_if;
 	int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
 	uint32_t hisaddr, desiredaddr;
@@ -2802,7 +2812,8 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 	 * Make sure to allocate a buf that can at least hold a
 	 * conf-nak with an `address' option.  We might need it below.
 	 */
-	buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT);
+	blen = len < 6 ? 6 : len;
+	buf = r = malloc (blen, M_TEMP, M_NOWAIT);
 	if (! buf)
 		return (0);
 
@@ -2811,9 +2822,9 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 		log(LOG_DEBUG, "%s: ipcp parse opts:",
 		    ifp->if_xname);
 	p = (void *)(h + 1);
-	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+	for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/* XXX should we just RXJ? */
 			addlog("%s: malicious IPCP option received, dropping\n",
 			    ifp->if_xname);
@@ -2824,7 +2835,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 		switch (*p) {
 #ifdef notyet
 		case IPCP_OPT_COMPRESSION:
-			if (len >= 6 && p[1] >= 6) {
+			if (len >= 6 && l >= 6) {
 				/* correctly formed compress option */
 				continue;
 			}
@@ -2833,7 +2844,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 			break;
 #endif
 		case IPCP_OPT_ADDRESS:
-			if (len >= 6 && p[1] == 6) {
+			if (len >= 6 && l == 6) {
 				/* correctly formed address option */
 				continue;
 			}
@@ -2847,9 +2858,14 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 			break;
 		}
 		/* Add the option to rejected list. */
-		bcopy (p, r, p[1]);
-		r += p[1];
-		rlen += p[1];
+		if (rlen + l > blen) {
+			if (debug)
+				addlog(" [overflow]");
+			continue;
+		}
+		memcpy(r, p, l);
+		r += l;
+		rlen += l;
 	}
 	if (rlen) {
 		if (debug)
@@ -2873,7 +2889,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 		       ifp->if_xname);
 	p = (void *)(h + 1);
 	len = origlen;
-	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+	for (rlen=0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		if (debug)
 			addlog(" %s", sppp_ipcp_opt_name(*p));
 		switch (*p) {
@@ -2921,10 +2937,15 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 			p[5] = hisaddr;
 			break;
 		}
+		if (rlen + l > blen) {
+			if (debug)
+				addlog(" [overflow]");
+			continue;
+		}
 		/* Add the option to nak'ed list. */
-		bcopy (p, r, p[1]);
-		r += p[1];
-		rlen += p[1];
+		memcpy(r, p, l);
+		r += l;
+		rlen += l;
 	}
 
 	/*
@@ -2975,12 +2996,12 @@ sppp_ipcp_RCR(struct sppp *sp, struct lc
 static void
 sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
 {
-	u_char *buf, *p;
+	u_char *buf, *p, l, blen;
 	struct ifnet *ifp = &sp->pp_if;
 	int debug = ifp->if_flags & IFF_DEBUG;
 
 	len -= 4;
-	buf = malloc (len, M_TEMP, M_NOWAIT);
+	buf = malloc (blen = len, M_TEMP, M_NOWAIT);
 	if (!buf)
 		return;
 
@@ -2989,9 +3010,9 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struc
 		    ifp->if_xname);
 
 	p = (void *)(h + 1);
-	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
+	for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/* XXX should we just RXJ? */
 			addlog("%s: malicious IPCP option received, dropping\n",
 			    ifp->if_xname);
@@ -3028,7 +3049,7 @@ drop:
 static void
 sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
 {
-	u_char *p;
+	u_char *p, l;
 	struct ifnet *ifp = &sp->pp_if;
 	int debug = ifp->if_flags & IFF_DEBUG;
 	uint32_t wantaddr;
@@ -3040,9 +3061,9 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struc
 		    ifp->if_xname);
 
 	p = (void *)(h + 1);
-	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
+	for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/* XXX should we just RXJ? */
 			addlog("%s: malicious IPCP option received, dropping\n",
 			    ifp->if_xname);
@@ -3057,7 +3078,7 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struc
 			 * if we can do something for him.  We'll drop
 			 * him our address then.
 			 */
-			if (len >= 6 && p[1] == 6) {
+			if (len >= 6 && l == 6) {
 				wantaddr = p[2] << 24 | p[3] << 16 |
 					p[4] << 8 | p[5];
 				sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS);
@@ -3080,14 +3101,14 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struc
 			break;
 
 		case IPCP_OPT_PRIMDNS:
-			if (len >= 6 && p[1] == 6) {
+			if (len >= 6 && l == 6) {
 				sp->dns_addrs[0] = p[2] << 24 | p[3] << 16 |
 					p[4] << 8 | p[5];
 			}
 			break;
 
 		case IPCP_OPT_SECDNS:
-			if (len >= 6 && p[1] == 6) {
+			if (len >= 6 && l == 6) {
 				sp->dns_addrs[1] = p[2] << 24 | p[3] << 16 |
 					p[4] << 8 | p[5];
 			}
@@ -3296,7 +3317,7 @@ sppp_ipv6cp_TO(void *cookie)
 static int
 sppp_ipv6cp_RCR(struct sppp *sp, struct lcp_header *h, int len)
 {
-	u_char *buf, *r, *p;
+	u_char *buf, *r, *p, l, blen;
 	struct ifnet *ifp = &sp->pp_if;
 	int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG;
 	struct in6_addr myaddr, desiredaddr, suggestaddr;
@@ -3310,7 +3331,8 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 	 * Make sure to allocate a buf that can at least hold a
 	 * conf-nak with an `address' option.  We might need it below.
 	 */
-	buf = r = malloc ((len < 6? 6: len), M_TEMP, M_NOWAIT);
+	blen = len < 6 ? 6 : len;
+	buf = r = malloc (blen, M_TEMP, M_NOWAIT);
 	if (! buf)
 		return (0);
 
@@ -3320,9 +3342,9 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 		    ifp->if_xname);
 	p = (void *)(h + 1);
 	ifidcount = 0;
-	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+	for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		/* Sanity check option length */
-		if (p[1] > len) {
+		if (l > len) {
 			/* XXX just RXJ? */
 			addlog("%s: received malicious IPCPv6 option, "
 			    "dropping\n", ifp->if_xname);
@@ -3332,7 +3354,7 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 			addlog(" %s", sppp_ipv6cp_opt_name(*p));
 		switch (*p) {
 		case IPV6CP_OPT_IFID:
-			if (len >= 10 && p[1] == 10 && ifidcount == 0) {
+			if (len >= 10 && l == 10 && ifidcount == 0) {
 				/* correctly formed address option */
 				ifidcount++;
 				continue;
@@ -3342,7 +3364,7 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 			break;
 #ifdef notyet
 		case IPV6CP_OPT_COMPRESSION:
-			if (len >= 4 && p[1] >= 4) {
+			if (len >= 4 && l >= 4) {
 				/* correctly formed compress option */
 				continue;
 			}
@@ -3356,10 +3378,15 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 				addlog(" [rej]");
 			break;
 		}
+		if (rlen + l > blen) {
+			if (debug)
+				addlog(" [overflow]");
+			continue;
+		}
 		/* Add the option to rejected list. */
-		bcopy (p, r, p[1]);
-		r += p[1];
-		rlen += p[1];
+		memcpy(r, p, l);
+		r += l;
+		rlen += l;
 	}
 	if (rlen) {
 		if (debug)
@@ -3377,7 +3404,7 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 	p = (void *)(h + 1);
 	len = origlen;
 	type = CONF_ACK;
-	for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
+	for (rlen = 0; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
 		if (debug)
 			addlog(" %s", sppp_ipv6cp_opt_name(*p));
 		switch (*p) {
@@ -3427,10 +3454,15 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 				    sppp_cp_type_name(type));
 			break;
 		}
+		if (rlen + l > blen) {
+			if (debug)
+				addlog(" [overflow]");
+			continue;
+		}
 		/* Add the option to nak'ed list. */
-		bcopy (p, r, p[1]);
-		r += p[1];
-		rlen += p[1];
+		memcpy(r, p, l);
+		r += l;
+		rlen += l;
 	}
 
 	if (rlen == 0 && type == CONF_ACK) {
@@ -3466,12 +3498,12 @@ sppp_ipv6cp_RCR(struct sppp *sp, struct 
 static void
 sppp_ipv6cp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len)
 {
-	u_char *buf, *p;
+	u_char *buf, *p, l, blen;
 	struct ifnet *ifp = &sp->pp_if;
 	int debug = ifp->if_flags & IFF_DEBUG;
 
 	len -= 4;
-	buf = malloc (len, M_TEMP, M_NOWAIT);
+	buf = malloc (blen = len, M_TEMP, M_NOWAIT);
 	if (!buf)
 		return;
 
@@ -3480,8 +3512,8 @@ sppp_ipv6cp_RCN_rej(struct sppp *sp, str
 		    ifp->if_xname);
 
 	p = (void *)(h + 1);
-	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
-		if (p[1] > len) {
+	for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+		if (l > len) {
 			/* XXX just RXJ? */
 			addlog("%s: received malicious IPCPv6 option, "
 			    "dropping\n", ifp->if_xname);
@@ -3518,13 +3550,13 @@ drop:
 static void
 sppp_ipv6cp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len)
 {
-	u_char *buf, *p;
+	u_char *buf, *p, l, blen;
 	struct ifnet *ifp = &sp->pp_if;
 	int debug = ifp->if_flags & IFF_DEBUG;
 	struct in6_addr suggestaddr;
 
 	len -= 4;
-	buf = malloc (len, M_TEMP, M_NOWAIT);
+	buf = malloc (blen = len, M_TEMP, M_NOWAIT);
 	if (!buf)
 		return;
 
@@ -3533,8 +3565,8 @@ sppp_ipv6cp_RCN_nak(struct sppp *sp, str
 		    ifp->if_xname);
 
 	p = (void *)(h + 1);
-	for (; len > 1 && p[1]; len -= p[1], p += p[1]) {
-		if (p[1] > len) {
+	for (; len > 1 && (l = p[1]) != 0; len -= l, p += l) {
+		if (l > len) {
 			/* XXX just RXJ? */
 			addlog("%s: received malicious IPCPv6 option, "
 			    "dropping\n", ifp->if_xname);
@@ -3549,7 +3581,7 @@ sppp_ipv6cp_RCN_nak(struct sppp *sp, str
 			 * if we can do something for him.  We'll drop
 			 * him our address then.
 			 */
-			if (len < 10 || p[1] != 10)
+			if (len < 10 || l != 10)
 				break;
 			memset(&suggestaddr, 0, sizeof(suggestaddr));
 			suggestaddr.s6_addr16[0] = htons(0xfe80);

Reply via email to