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);