From owner-p4-projects@FreeBSD.ORG Thu Feb 7 09:29:25 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 253C916A420; Thu, 7 Feb 2008 09:29:25 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C678816A41A for ; Thu, 7 Feb 2008 09:29:24 +0000 (UTC) (envelope-from andre@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 9952513C4E9 for ; Thu, 7 Feb 2008 09:29:24 +0000 (UTC) (envelope-from andre@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m179TOXx043378 for ; Thu, 7 Feb 2008 09:29:24 GMT (envelope-from andre@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m179TOXi043375 for perforce@freebsd.org; Thu, 7 Feb 2008 09:29:24 GMT (envelope-from andre@freebsd.org) Date: Thu, 7 Feb 2008 09:29:24 GMT Message-Id: <200802070929.m179TOXi043375@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to andre@freebsd.org using -f From: Andre Oppermann To: Perforce Change Reviews Cc: Subject: PERFORCE change 134972 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Feb 2008 09:29:25 -0000 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: /*