⬢ DragonFlyBSD Kernel Audit
DF-3538 / fix.diff
← back to finding ↓ download raw
--- a/sys/net/ppp_layer/slcompress.c
+++ b/sys/net/ppp_layer/slcompress.c
@@ -113,7 +113,9 @@
 }
 
 #define DECODEL(f) { \
+	if (cp + 1 > buf + buflen) goto bad; \
 	if (*cp == 0) {\
+		if (cp + 3 > buf + buflen) goto bad; \
 		(f) = htonl(ntohl(f) + ((cp[1] << 8) | cp[2])); \
 		cp += 3; \
 	} else { \
@@ -122,7 +124,9 @@
 }
 
 #define DECODES(f) { \
+	if (cp + 1 > buf + buflen) goto bad; \
 	if (*cp == 0) {\
+		if (cp + 3 > buf + buflen) goto bad; \
 		(f) = htons(ntohs(f) + ((cp[1] << 8) | cp[2])); \
 		cp += 3; \
 	} else { \
@@ -131,7 +135,9 @@
 }
 
 #define DECODEU(f) { \
+	if (cp + 1 > buf + buflen) goto bad; \
 	if (*cp == 0) {\
+		if (cp + 3 > buf + buflen) goto bad; \
 		(f) = htons((cp[1] << 8) | cp[2]); \
 		cp += 3; \
 	} else { \
@@ -465,10 +471,14 @@
 	u_int16_t *bp;
 	u_int vjlen;
 
+	if (buflen < 1)			/* need the type/dispatch byte */
+		goto bad;
 	switch (type) {
 
 	case TYPE_UNCOMPRESSED_TCP:
 		ip = (struct ip *) buf;
+		if (buflen < (int)sizeof(struct ip))
+			goto bad;
 		if (ip->ip_p >= MAX_STATES)
 			goto bad;
 		cs = &comp->rstate[comp->last_recv = ip->ip_p];
@@ -500,8 +510,12 @@
 	/* We've got a compressed packet. */
 	INCR(sls_compressedin)
 	cp = buf;
+	if (cp + 1 > buf + buflen)		/* changes byte */
+		goto bad;
 	changes = *cp++;
 	if (changes & NEW_C) {
+		if (cp + 1 > buf + buflen)	/* connection id byte */
+			goto bad;
 		/* Make sure the state index is in range, then grab the state.
 		 * If we have a good state index, clear the 'discard' flag. */
 		if (*cp >= MAX_STATES)
@@ -518,6 +532,8 @@
 			return (-1);
 		}
 	}
+	if (cp + 2 > buf + buflen)		/* tcp checksum (2 bytes) */
+		goto bad;
 	cs = &comp->rstate[comp->last_recv];
 	hlen = cs->cs_ip.ip_hl << 2;
 	th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen];