Date: Sun, 8 Jun 2008 18:14:23 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 143124 for review Message-ID: <200806081814.m58IEN1S068010@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=143124 Change 143124 by sam@sam_ebb on 2008/06/08 18:14:11 handle max_linkhdr large enough to force overflow of an inline mbuf when forming the tcpip hdr Affected files ... .. //depot/projects/vap/sys/netinet/tcp_output.c#9 edit .. //depot/projects/vap/sys/netinet/tcp_subr.c#10 edit .. //depot/projects/vap/sys/netinet/tcp_syncache.c#10 edit .. //depot/projects/vap/sys/netinet/tcp_timewait.c#4 edit .. //depot/projects/vap/sys/sys/mbuf.h#14 edit Differences ... ==== //depot/projects/vap/sys/netinet/tcp_output.c#9 (text+ko) ==== @@ -735,14 +735,10 @@ } } -/*#ifdef DIAGNOSTIC*/ -#ifdef INET6 +#ifdef DIAGNOSTIC if (max_linkhdr + hdrlen > MCLBYTES) -#else - if (max_linkhdr + hdrlen > MHLEN) + panic("tcphdr too big"); #endif - panic("tcphdr too big"); -/*#endif*/ /* * Grab a header mbuf, attaching a copy of data to @@ -751,7 +747,7 @@ */ if (len) { struct mbuf *mb; - u_int moff; + u_int moff, trailingspace; if ((tp->t_flags & TF_FORCEDATA) && len == 1) tcpstat.tcps_sndprobe++; @@ -775,23 +771,18 @@ m->m_len += hdrlen; m->m_data -= hdrlen; #else - MGETHDR(m, M_DONTWAIT, MT_DATA); + if (hdrlen + max_linkhdr <= MHLEN) { + m = m_gethdr(M_DONTWAIT, MT_DATA); + trailingspace = MHLEN - (hdrlen + max_linkhdr); + } else { + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + trailingspace = MCLBYTES - (hdrlen + max_linkhdr); + } if (m == NULL) { SOCKBUF_UNLOCK(&so->so_snd); error = ENOBUFS; goto out; } -#ifdef INET6 - if (MHLEN < hdrlen + max_linkhdr) { - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - SOCKBUF_UNLOCK(&so->so_snd); - m_freem(m); - error = ENOBUFS; - goto out; - } - } -#endif m->m_data += max_linkhdr; m->m_len = hdrlen; @@ -801,7 +792,7 @@ */ mb = sbsndptr(&so->so_snd, off, len, &moff); - if (len <= MHLEN - hdrlen - max_linkhdr) { + if (len <= trailingspace) { m_copydata(mb, moff, (int)len, mtod(m, caddr_t) + hdrlen); m->m_len += len; @@ -834,7 +825,7 @@ tcpstat.tcps_sndurg++; else tcpstat.tcps_sndwinup++; - +#if 0 MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == NULL) { error = ENOBUFS; @@ -848,6 +839,21 @@ #endif m->m_data += max_linkhdr; m->m_len = hdrlen; +#else + if (hdrlen + max_linkhdr <= MHLEN) + m = m_gethdr(M_DONTWAIT, MT_DATA); + else + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + if (hdrlen + max_linkhdr <= MHLEN) + MH_ALIGN(m, hdrlen); + else + MCL_ALIGN(m, hdrlen); + m->m_len = hdrlen; +#endif } SOCKBUF_UNLOCK_ASSERT(&so->so_snd); m->m_pkthdr.rcvif = (struct ifnet *)0; ==== //depot/projects/vap/sys/netinet/tcp_subr.c#10 (text+ko) ==== @@ -291,7 +291,7 @@ #endif /* INET6 */ if (max_protohdr < TCP_MINPROTOHDR) max_protohdr = TCP_MINPROTOHDR; - if (max_linkhdr + TCP_MINPROTOHDR > MHLEN) + if (max_linkhdr + TCP_MINPROTOHDR > MCLBYTES) panic("tcp_init"); #undef TCP_MINPROTOHDR /* @@ -412,7 +412,7 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) { - int tlen; + int hdrlen, tlen; int win = 0; struct ip *ip; struct tcphdr *nth; @@ -446,11 +446,28 @@ } } if (m == NULL) { +#if 0 m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) return; tlen = 0; m->m_data += max_linkhdr; +#else +#ifdef INET6 + if (isipv6) + hdrlen = sizeof (struct ip6_hdr) + + sizeof (struct tcphdr); + else +#endif + hdrlen = sizeof (struct tcpiphdr); + if (hdrlen + max_linkhdr <= MHLEN) + m = m_gethdr(M_DONTWAIT, MT_DATA); + else + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) + return; + m->m_data += max_linkhdr; +#endif #ifdef INET6 if (isipv6) { bcopy((caddr_t)ip6, mtod(m, caddr_t), ==== //depot/projects/vap/sys/netinet/tcp_syncache.c#10 (text+ko) ==== @@ -1285,12 +1285,19 @@ if (sc->sc_peer_mss) mssopt = max( min(sc->sc_peer_mss, mssopt), tcp_minmss); +#if 0 /* XXX: Assume that the entire packet will fit in a header mbuf. */ KASSERT(max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN, ("syncache: mbuf too small")); /* Create the IP+TCP header from scratch. */ m = m_gethdr(M_DONTWAIT, MT_DATA); +#else + if (max_linkhdr + tlen + TCP_MAXOLEN <= MHLEN) + m = m_gethdr(M_DONTWAIT, MT_DATA); + else + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); +#endif if (m == NULL) return (ENOBUFS); #ifdef MAC ==== //depot/projects/vap/sys/netinet/tcp_timewait.c#4 (text+ko) ==== @@ -534,7 +534,20 @@ INP_WLOCK_ASSERT(inp); +#ifdef INET6 + if (isipv6) + hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); + else +#endif + hdrlen = sizeof(struct tcpiphdr); +#if 0 m = m_gethdr(M_DONTWAIT, MT_DATA); +#else + if (max_linkhdr + hdrlen + TCP_MAXOLEN <= MHLEN) + m = m_gethdr(M_DONTWAIT, MT_DATA); + else + m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); +#endif if (m == NULL) return (ENOBUFS); m->m_data += max_linkhdr; @@ -545,14 +558,12 @@ #ifdef INET6 if (isipv6) { - hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); ip6 = mtod(m, struct ip6_hdr *); th = (struct tcphdr *)(ip6 + 1); tcpip_fillheaders(inp, ip6, th); } else #endif { - hdrlen = sizeof(struct tcpiphdr); ip = mtod(m, struct ip *); th = (struct tcphdr *)(ip + 1); tcpip_fillheaders(inp, ip, th); @@ -572,9 +583,9 @@ m->m_len = hdrlen + optlen; m->m_pkthdr.len = m->m_len; - +#if 0 KASSERT(max_linkhdr + m->m_len <= MHLEN, ("tcptw: mbuf too small")); - +#endif th->th_seq = htonl(tw->snd_nxt); th->th_ack = htonl(tw->rcv_nxt); th->th_off = (sizeof(struct tcphdr) + optlen) >> 2; ==== //depot/projects/vap/sys/sys/mbuf.h#14 (text+ko) ==== @@ -677,6 +677,17 @@ } while (0) /* + * As above, for mbufs allocated with m_getcl. + */ +#define MCL_ALIGN(m, len) do { \ + KASSERT((m)->m_flags & M_PKTHDR && ((m)->m_flags & M_EXT), \ + ("%s: MCL_ALIGN not PKTHDR cluster", __func__)); \ + KASSERT((m)->m_data == (m)->m_ext.ext_buf, \ + ("%s: MCL_ALIGN not a virgin mbuf", __func__)); \ + (m)->m_data += (MCLBYTES - (len)) & ~(sizeof(long) - 1); \ +} while (0) + +/* * Compute the amount of space available before the current start of data in * an mbuf. *
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200806081814.m58IEN1S068010>