Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Nov 1997 05:00:57 -0800
From:      Don Lewis <Don.Lewis@tsc.tdk.com>
To:        Jim Shankland <jas@flyingfox.com>, robert@cyrus.watson.org
Cc:        security@freebsd.org
Subject:   Re: new TCP/IP bug in win95 (fwd)
Message-ID:  <199711211300.FAA14741@salsa.gv.tsc.tdk.com>
In-Reply-To: Jim Shankland <jas@flyingfox.com> "Re: new TCP/IP bug in win95 (fwd)" (Nov 20,  2:08pm)

next in thread | previous in thread | raw e-mail | index | archive | help
On Nov 20,  2:08pm, Jim Shankland wrote:
} Subject: Re: new TCP/IP bug in win95 (fwd)
} Interesting.  So the TCP stack gets into a lively conversation with
} itself, since the source-address and port are the same as the
} destination address and port.
} 
} The obvious fix would appear to be to drop such packets in tcp_input.c
} when the TCP state is TCPS_LISTEN.

I think the proper fix is to move this check that is done in the ACK
processing code:

        case TCPS_SYN_RECEIVED:
                if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
                    SEQ_GT(ti->ti_ack, tp->snd_max))
                        goto dropwithreset;
                

to a point before the code that trims the data to fit the window (which
may do "goto dropafterack;").  The code for the SYN_SENT state does such
a check early in the code.

Ironically the FreeBSD tcp_input() implementation also used this part of
the SYN_SENT code in the SYN_RCVD state, but that was undone because it
the RST handling in this same section of code was not appropriate in
the SYN_RCVD state.

I think something like this (untested) patch should do the trick:

--- tcp_input.c.prev	Fri Nov 21 04:34:51 1997
+++ tcp_input.c	Fri Nov 21 05:00:07 1997
@@ -752,6 +752,17 @@
 		}
 
 	/*
+	 * If the state is SYN_RCVD:
+	 *	if seg contains an ACK, but not for our SYN,ACK, drop the input.
+	 * Otherwise continue processing
+	 */
+	case TCPS_SYN_RECEIVED:
+		if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
+		    SEQ_GT(ti->ti_ack, tp->snd_max))
+			goto dropwithreset;
+ 		break;  /* continue normal processing */
+
+	/*
 	 * If the state is SYN_SENT:
 	 *	if seg contains an ACK, but not for our SYN, drop the input.
 	 *	if seg contains a RST, then drop the connection.
@@ -1171,9 +1182,7 @@
 	 * send an RST.
 	 */
 	case TCPS_SYN_RECEIVED:
-		if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
-		    SEQ_GT(ti->ti_ack, tp->snd_max))
-			goto dropwithreset;
+		/* ACK validation was done earlier, before window trim */
 
 		tcpstat.tcps_connects++;
 		soisconnected(so);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199711211300.FAA14741>