Subject: Re: Syn cache corrupts kernel data!!
To: Juergen Hannken-Illjes <hannken@serv1.eis.cs.tu-bs.de>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: current-users
Date: 07/27/1997 14:12:37
On Sun, 27 Jul 1997 19:00:22 +0200 (MET DST) 
 hannken@serv1.eis.cs.tu-bs.de (Juergen Hannken-Illjes) wrote:

 > I found a severe bug due to the new `syn_cache' functionality in
 > netinet/tcp_input.c

Yow, nice hunting!  That bit of code allows a TIME_WAIT socket to be
discarded if a new connection is being attempted.  Apparently, this slipped
through my tests because I don't see a large number of connections in
TIME_WAIT!

Your solution is basically correct, however I have tidied it up a bit,
and added some comments about what is happening.  Can you please test
this patch and let me know if it solves the problem for you?

(P.S. Sorry I didn't get to this until now; I was out sailing all day
yesterday with hpeyerl@netbsd.org and carrel@netbsd.org :-)

Jason R. Thorpe                                       thorpej@nas.nasa.gov
NASA Ames Research Center                               Home: 408.866.1912
NAS: M/S 258-6                                          Work: 415.604.0935
Moffett Field, CA 94035                                Pager: 415.428.6939

Index: tcp_input.c
===================================================================
RCS file: /mastersrc/netbsd/src/sys/netinet/tcp_input.c,v
retrieving revision 1.25
diff -c -r1.25 tcp_input.c
*** tcp_input.c	1997/07/25 21:19:39	1.25
--- tcp_input.c	1997/07/27 20:59:17
***************
*** 280,286 ****
  	register struct inpcb *inp;
  	caddr_t optp = NULL;
  	int optlen = 0;
! 	int len, tlen, off;
  	register struct tcpcb *tp = 0;
  	register int tiflags;
  	struct socket *so = NULL;
--- 280,286 ----
  	register struct inpcb *inp;
  	caddr_t optp = NULL;
  	int optlen = 0;
! 	int len, tlen, off, hdroptlen;
  	register struct tcpcb *tp = 0;
  	register int tiflags;
  	struct socket *so = NULL;
***************
*** 598,605 ****
  	/*
  	 * Drop TCP, IP headers and TCP options.
  	 */
! 	m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
! 	m->m_len  -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);
  
  	/*
  	 * Calculate amount of space in receive window,
--- 598,606 ----
  	/*
  	 * Drop TCP, IP headers and TCP options.
  	 */
! 	hdroptlen  = sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
! 	m->m_data += hdroptlen;
! 	m->m_len  -= hdroptlen;
  
  	/*
  	 * Calculate amount of space in receive window,
***************
*** 812,817 ****
--- 813,826 ----
  			    SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
  				iss = tp->rcv_nxt + TCP_ISSINCR;
  				tp = tcp_close(tp);
+ 				/*
+ 				 * We have already advanced the mbuf
+ 				 * pointers past the IP+TCP headers and
+ 				 * options.  Restore those pointers before
+ 				 * attempting to use the TCP header again.
+ 				 */
+ 				m->m_data -= hdroptlen;
+ 				m->m_len  += hdroptlen;
  				goto findpcb;
  			}
  			/*