svn commit: r324426 - stable/11/sys/netinet
Andrey V. Elsukov
ae at FreeBSD.org
Mon Oct 9 08:50:05 UTC 2017
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;
More information about the svn-src-stable-11
mailing list