Date: Thu, 7 Feb 2008 09:29:24 GMT From: Andre Oppermann <andre@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 134972 for review Message-ID: <200802070929.m179TOXi043375@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=134972 Change 134972 by andre@andre_flirtbox on 2008/02/07 09:28:38 Copy TCP header information into local variables as the mbuf portion where it resides is technically gone. When using m_collapse() will be truely gone and accessing it will give a page fault. Affected files ... .. //depot/projects/tcp_reass/netinet/tcp_reass.c#17 edit Differences ... ==== //depot/projects/tcp_reass/netinet/tcp_reass.c#17 (text+ko) ==== @@ -175,6 +175,7 @@ struct socket *so = tp->t_inpcb->inp_socket; struct mbuf *n; int i, thflags = 0, mcnt; + tcp_seq th_seq; struct trq tqes; INP_LOCK_ASSERT(tp->t_inpcb); @@ -192,7 +193,14 @@ return (0); goto present; } + + /* + * Store TCP header information in local variables as + * we may lose access to it after mbuf compacting. + */ thflags = (th->th_flags & TH_FIN); + th_seq = th->th_seq; + th = NULL; /* Prevent further use. */ /* Check if it is really neccessary to do all the work. */ if (!tcp_reass_enabled && TAILQ_EMPTY(&tp->t_trq)) { @@ -209,9 +217,9 @@ KASSERT(*tlenp > 0, ("%s: segment doesn't contain any data", __func__)); - KASSERT(SEQ_LEQ(tp->rcv_nxt, th->th_seq), + KASSERT(SEQ_LEQ(tp->rcv_nxt, th_seq), ("%s: sequence number below rcv_nxt", __func__)); - KASSERT(!(tp->rcv_nxt == th->th_seq) || !(TAILQ_EMPTY(&tp->t_trq)), + KASSERT(!(tp->rcv_nxt == th_seq) || !(TAILQ_EMPTY(&tp->t_trq)), ("%s: got missing segment but queue is empty", __func__)); #ifdef INVARIANTS @@ -253,8 +261,8 @@ * vs. actual real data with 2k clusters and 1500 byte packets. * This shouldn't be too much of a problem though. */ - if (th->th_seq != tp->rcv_nxt && - tp->t_trqmcnt > sbspace(&so->so_rcv)) { + if (th_seq != tp->rcv_nxt && + tp->t_trqmcnt > (sbspace(&so->so_rcv) / 4 * 5)) { tcpstat.tcps_reass_overflow++; tcpstat.tcps_rcvmemdrop++; m_freem(m); @@ -281,9 +289,9 @@ /* Check if we've already received FIN; we can't accept data beyond it. */ tqe = TAILQ_LAST(&tp->t_trq, trq_head); - if (tqe && (tqe->trq_thflags & TH_FIN) && SEQ_LEQ(tqe->trq_seq, th->th_seq)) { + if (tqe && (tqe->trq_thflags & TH_FIN) && SEQ_LEQ(tqe->trq_seq, th_seq)) { /* Properly count retransmitted perfect matching FIN. */ - if (tqe->trq_seq == th->th_seq && *tlenp > 0) + if (tqe->trq_seq == th_seq && *tlenp > 0) tcpstat.tcps_rcvoopack++; else { tcpstat.tcps_rcvpackafterfin++; @@ -296,7 +304,7 @@ /* Check if this segments FIN is before the end of the last block. */ if (tqe && (thflags & TH_FIN) && - SEQ_GT(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) { + SEQ_GT(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) { /* TCP statistics. */ tcpstat.tcps_rcvpackafterfin++; tcpstat.tcps_rcvbyteafterfin += *tlenp; @@ -306,7 +314,7 @@ } /* Check if this segment directly attaches to the end. */ - if (tqe && tqe->trq_seq + tqe->trq_len == th->th_seq) { + if (tqe && tqe->trq_seq + tqe->trq_len == th_seq) { tqe->trq_len += *tlenp; tqe->trq_mcnt += mcnt; tp->t_trqmcnt += mcnt; @@ -326,7 +334,7 @@ } /* Check if beyond last block. */ - if (tqe && SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq)) + if (tqe && SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq)) goto insert; /* Check if this is the first segment. */ @@ -334,14 +342,14 @@ goto insert; /* Check if this is the missing segment. */ - if (tp->rcv_nxt == th->th_seq) { + if (tp->rcv_nxt == th_seq) { tqe = TAILQ_FIRST(&tp->t_trq); - KASSERT(SEQ_GT(tqe->trq_seq, th->th_seq), + KASSERT(SEQ_GT(tqe->trq_seq, th_seq), ("%s: first block starts below missing segment", __func__)); /* Check if segment prepends first block. */ - if (SEQ_LEQ(tqe->trq_seq, th->th_seq + *tlenp)) { + if (SEQ_LEQ(tqe->trq_seq, th_seq + *tlenp)) { /* Trim tail of segment. */ - if ((i = SEQ_DELTA(tqe->trq_seq, th->th_seq + *tlenp))) { + if ((i = SEQ_DELTA(tqe->trq_seq, th_seq + *tlenp))) { m_adj(m, -i); *tlenp -= i; /* TCP statistics. */ @@ -356,7 +364,7 @@ tqe->trq_mcnt += mcnt; tp->t_trqmcnt += mcnt; tcp_reass_mcnt += mcnt; - tqe->trq_seq = th->th_seq; + tqe->trq_seq = th_seq; n = m_last(m); n->m_next = tqe->trq_m; tqe->trq_m = m; @@ -372,15 +380,15 @@ /* See where it fits. */ TAILQ_FOREACH_SAFE(tqe, &tp->t_trq, trq_q, tqen) { /* Segment is after this blocks coverage. */ - if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq)) + if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq)) continue; /* Segment is after the previous one but before this one. */ - if (SEQ_GT(tqe->trq_seq, th->th_seq + *tlenp)) + if (SEQ_GT(tqe->trq_seq, th_seq + *tlenp)) break; /* Insert as new block. */ /* Segment is already fully covered. */ - if (SEQ_LEQ(tqe->trq_seq, th->th_seq) && - SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) { + if (SEQ_LEQ(tqe->trq_seq, th_seq) && + SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) { tcpstat.tcps_rcvduppack++; tcpstat.tcps_rcvdupbyte += *tlenp; tcpstat.tcps_reass_covered++; @@ -396,8 +404,8 @@ } /* Segment covers and extends on both ends. */ - if (SEQ_GT(tqe->trq_seq, th->th_seq) && - SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) { + if (SEQ_GT(tqe->trq_seq, th_seq) && + SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) { /* Replace block content. */ tp->t_trqmcnt -= tqe->trq_mcnt; m_freem(tqe->trq_m); @@ -405,7 +413,7 @@ tqe->trq_mcnt = mcnt; tp->t_trqmcnt += mcnt; tcp_reass_mcnt += mcnt; - tqe->trq_seq = th->th_seq; + tqe->trq_seq = th_seq; tqe->trq_m = m; tqe->trq_ml = m_last(m); tqe->trq_thflags |= thflags; @@ -422,13 +430,13 @@ } /* Segment prepends to this block. */ - if (SEQ_GT(tqe->trq_seq, th->th_seq) && - SEQ_LEQ(tqe->trq_seq, th->th_seq + *tlenp) && - SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp)) { + if (SEQ_GT(tqe->trq_seq, th_seq) && + SEQ_LEQ(tqe->trq_seq, th_seq + *tlenp) && + SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp)) { KASSERT(!(thflags & TH_FIN), ("%s: new segment with FIN can't prepend", __func__)); /* Trim tail of segment. */ - if ((i = SEQ_DELTA(tqe->trq_seq, th->th_seq + *tlenp))) { + if ((i = SEQ_DELTA(tqe->trq_seq, th_seq + *tlenp))) { m_adj(m, -i); *tlenp -= i; /* TCP statistics. */ @@ -443,7 +451,7 @@ tqe->trq_mcnt += mcnt; tp->t_trqmcnt += mcnt; tcp_reass_mcnt += mcnt; - tqe->trq_seq = th->th_seq; + tqe->trq_seq = th_seq; n = m_last(m); n->m_next = tqe->trq_m; tqe->trq_m = m; @@ -456,11 +464,11 @@ } /* Segment appends to this block. */ - if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq + *tlenp) && - SEQ_LEQ(tqe->trq_seq, th->th_seq) && - SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th->th_seq)) { + if (SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq + *tlenp) && + SEQ_LEQ(tqe->trq_seq, th_seq) && + SEQ_GEQ(tqe->trq_seq + tqe->trq_len, th_seq)) { /* Trim head of segment. */ - if ((i = SEQ_DELTA(tqe->trq_seq + tqe->trq_len, th->th_seq))) { + if ((i = SEQ_DELTA(tqe->trq_seq + tqe->trq_len, th_seq))) { m_adj(m, i); *tlenp -= i; /* TCP Statistics. */ @@ -489,7 +497,7 @@ insert: /* Prepare to insert into block queue. */ - if (tp->rcv_nxt == th->th_seq) { + if (tp->rcv_nxt == th_seq) { /* * Use temporary struct trq on the stack for missing * segment to prevent blocking of all reassembly queues @@ -507,7 +515,7 @@ tcpstat.tcps_reass_blocks++; } tcp_reass_qsize++; - tqen->trq_seq = th->th_seq; + tqen->trq_seq = th_seq; tqen->trq_len = *tlenp; tqen->trq_mcnt = mcnt; tp->t_trqmcnt += mcnt; @@ -517,7 +525,7 @@ tqen->trq_thflags |= thflags; /* Where to insert. */ - if (tqe != NULL && SEQ_LT(tqe->trq_seq + tqe->trq_len, th->th_seq)) + if (tqe != NULL && SEQ_LT(tqe->trq_seq + tqe->trq_len, th_seq)) TAILQ_INSERT_AFTER(&tp->t_trq, tqe, tqen, trq_q); else if (tqe != NULL) TAILQ_INSERT_BEFORE(tqe, tqen, trq_q); @@ -535,7 +543,7 @@ LIST_INSERT_HEAD(&tp->t_trq_sack, tqen, trq_s); /* Missing segment? */ - if (tp->rcv_nxt != th->th_seq) + if (tp->rcv_nxt != th_seq) return (0); present: /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802070929.m179TOXi043375>