From owner-svn-src-stable-11@freebsd.org Mon Oct 9 08:50:05 2017 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B77FAE29BB2; Mon, 9 Oct 2017 08:50:05 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 0CB121A88; Mon, 9 Oct 2017 08:50:04 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v998o448070190; Mon, 9 Oct 2017 08:50:04 GMT (envelope-from ae@FreeBSD.org) Received: (from ae@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v998o4CP070189; Mon, 9 Oct 2017 08:50:04 GMT (envelope-from ae@FreeBSD.org) Message-Id: <201710090850.v998o4CP070189@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ae set sender to ae@FreeBSD.org using -f From: "Andrey V. Elsukov" Date: Mon, 9 Oct 2017 08:50:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r324426 - stable/11/sys/netinet X-SVN-Group: stable-11 X-SVN-Commit-Author: ae X-SVN-Commit-Paths: stable/11/sys/netinet X-SVN-Commit-Revision: 324426 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 09 Oct 2017 08:50:05 -0000 Author: ae Date: Mon Oct 9 08:50:03 2017 New Revision: 324426 URL: https://svnweb.freebsd.org/changeset/base/324426 Log: MFC r324098: Some mbuf related fixes in icmp_error() * check mbuf length before doing mtod() and accessing to IP header; * update oip pointer and all depending pointers after m_pullup(); * remove extra checks and extra parentheses, wrap long lines; PR: 222670 Modified: stable/11/sys/netinet/ip_icmp.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/netinet/ip_icmp.c ============================================================================== --- stable/11/sys/netinet/ip_icmp.c Mon Oct 9 07:44:09 2017 (r324425) +++ stable/11/sys/netinet/ip_icmp.c Mon Oct 9 08:50:03 2017 (r324426) @@ -185,17 +185,14 @@ kmod_icmpstat_inc(int statnum) void icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu) { - register struct ip *oip = mtod(n, struct ip *), *nip; - register unsigned oiphlen = oip->ip_hl << 2; - register struct icmp *icp; - register struct mbuf *m; - unsigned icmplen, icmpelen, nlen; + struct ip *oip, *nip; + struct icmp *icp; + struct mbuf *m; + unsigned icmplen, icmpelen, nlen, oiphlen; - KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", __func__)); -#ifdef ICMPPRINTFS - if (icmpprintfs) - printf("icmp_error(%p, %x, %d)\n", oip, type, code); -#endif + KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", + __func__)); + if (type != ICMP_REDIRECT) ICMPSTAT_INC(icps_error); /* @@ -207,19 +204,28 @@ icmp_error(struct mbuf *n, int type, int code, uint32_ */ if (n->m_flags & M_DECRYPTED) goto freeit; - if (oip->ip_off & htons(~(IP_MF|IP_DF))) - goto freeit; if (n->m_flags & (M_BCAST|M_MCAST)) goto freeit; + + /* Drop if IP header plus 8 bytes is not contiguous in first mbuf. */ + if (n->m_len < sizeof(struct ip) + ICMP_MINLEN) + goto freeit; + oip = mtod(n, struct ip *); + oiphlen = oip->ip_hl << 2; + if (n->m_len < oiphlen + ICMP_MINLEN) + goto freeit; +#ifdef ICMPPRINTFS + if (icmpprintfs) + printf("icmp_error(%p, %x, %d)\n", oip, type, code); +#endif + if (oip->ip_off & htons(~(IP_MF|IP_DF))) + goto freeit; if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT && - n->m_len >= oiphlen + ICMP_MINLEN && - !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) { + !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + + oiphlen))->icmp_type)) { ICMPSTAT_INC(icps_oldicmp); goto freeit; } - /* Drop if IP header plus 8 bytes is not contignous in first mbuf. */ - if (oiphlen + 8 > n->m_len) - goto freeit; /* * Calculate length to quote from original packet and * prevent the ICMP mbuf from overflowing. @@ -235,9 +241,10 @@ icmp_error(struct mbuf *n, int type, int code, uint32_ n->m_next == NULL) goto stdreply; if (n->m_len < oiphlen + sizeof(struct tcphdr) && - ((n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL)) + (n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL) goto freeit; - th = (struct tcphdr *)((caddr_t)oip + oiphlen); + oip = mtod(n, struct ip *); + th = mtodo(n, oiphlen); tcphlen = th->th_off << 2; if (tcphlen < sizeof(struct tcphdr)) goto freeit; @@ -245,8 +252,8 @@ icmp_error(struct mbuf *n, int type, int code, uint32_ goto freeit; if (oiphlen + tcphlen > n->m_len && n->m_next == NULL) goto stdreply; - if (n->m_len < oiphlen + tcphlen && - ((n = m_pullup(n, oiphlen + tcphlen)) == NULL)) + if (n->m_len < oiphlen + tcphlen && + (n = m_pullup(n, oiphlen + tcphlen)) == NULL) goto freeit; icmpelen = max(tcphlen, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen)); @@ -262,24 +269,31 @@ icmp_error(struct mbuf *n, int type, int code, uint32_ if (n->m_len < oiphlen + sizeof(struct sctphdr) && (n = m_pullup(n, oiphlen + sizeof(struct sctphdr))) == NULL) goto freeit; + oip = mtod(n, struct ip *); icmpelen = max(sizeof(struct sctphdr), min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen)); - sh = (struct sctphdr *)((caddr_t)oip + oiphlen); + sh = mtodo(n, oiphlen); if (ntohl(sh->v_tag) == 0 && - ntohs(oip->ip_len) >= oiphlen + sizeof(struct sctphdr) + 8 && + ntohs(oip->ip_len) >= oiphlen + + sizeof(struct sctphdr) + 8 && (n->m_len >= oiphlen + sizeof(struct sctphdr) + 8 || n->m_next != NULL)) { if (n->m_len < oiphlen + sizeof(struct sctphdr) + 8 && - (n = m_pullup(n, oiphlen + sizeof(struct sctphdr) + 8)) == NULL) + (n = m_pullup(n, oiphlen + + sizeof(struct sctphdr) + 8)) == NULL) goto freeit; + oip = mtod(n, struct ip *); + sh = mtodo(n, oiphlen); ch = (struct sctp_chunkhdr *)(sh + 1); if (ch->chunk_type == SCTP_INITIATION) { icmpelen = max(sizeof(struct sctphdr) + 8, - min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen)); + min(V_icmp_quotelen, ntohs(oip->ip_len) - + oiphlen)); } } } else -stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen)); +stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - + oiphlen)); icmplen = min(oiphlen + icmpelen, nlen); if (icmplen < sizeof(struct ip)) @@ -294,7 +308,8 @@ stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs #ifdef MAC mac_netinet_icmp_reply(n, m); #endif - icmplen = min(icmplen, M_TRAILINGSPACE(m) - sizeof(struct ip) - ICMP_MINLEN); + icmplen = min(icmplen, M_TRAILINGSPACE(m) - + sizeof(struct ip) - ICMP_MINLEN); m_align(m, ICMP_MINLEN + icmplen); m->m_len = ICMP_MINLEN + icmplen;