PERFORCE change 134972 for review

Andre Oppermann andre at FreeBSD.org
Thu Feb 7 01:29:25 PST 2008


http://perforce.freebsd.org/chv.cgi?CH=134972

Change 134972 by andre at 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:
 	/*


More information about the p4-projects mailing list