From archie@whistle.com Mon Nov 29 17:47:53 1999
Return-Path: <archie@whistle.com>
Received: from bubba.whistle.com (bubba.whistle.com [207.76.205.7])
	by hub.freebsd.org (Postfix) with ESMTP id 42AB6152DB
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 29 Nov 1999 17:47:24 -0800 (PST)
	(envelope-from archie@whistle.com)
Received: (from archie@localhost)
	by bubba.whistle.com (8.9.2/8.9.2) id RAA26187;
	Mon, 29 Nov 1999 17:47:23 -0800 (PST)
Message-Id: <199911300147.RAA26187@bubba.whistle.com>
Date: Mon, 29 Nov 1999 17:47:23 -0800 (PST)
From: Archie Cobbs <archie@whistle.com>
Reply-To: archie@whistle.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: tcp_input() fails to update m->m_pkthdr.len
X-Send-Pr-Version: 3.2

>Number:         15175
>Category:       kern
>Synopsis:       tcp_input() fails to update m->m_pkthdr.len
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov 29 17:50:01 PST 1999
>Closed-Date:    Sat Jun 9 17:00:48 PDT 2001
>Last-Modified:  Sat Jun 09 17:01:05 PDT 2001
>Originator:     Archie Cobbs
>Release:        FreeBSD 3.3-STABLE and 4.0-CURRENT
>Organization:
Whistle Communications, Inc.
>Environment:

>Description:

See sys/netinet/tcp_input.c, line 376:

        /*
         * 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);

Notice that m->m_pkthdr.len is not updated, and therefore the mbuf
becomes inconsistent.  Apparently this doesn't matter much in normal
use.  However, netgraph(4) is strict about checking the consistency
of mbufs and the above omission causes a panic later on.

>How-To-Repeat:

	Input TCP data

>Fix:
	
   if ((m->m_flags & M_PKTHDR) != 0)
	m->m_pkthdr.len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr);

   [ Can we always assume ((m->m_flags & M_PKTHDR) != 0) here?? ]


>Release-Note:
>Audit-Trail:

From: Archie Cobbs <archie@whistle.com>
To: freebsd-gnats-submit@freebsd.org
Cc:  
Subject: Re: kern/15175: tcp_input() fails to update m->m_pkthdr.len
Date: Wed, 26 Jan 2000 16:32:47 -0800 (PST)

 This bug is fixed in 4.0-current thanks to the IPv6 integration.
 However, it remains in 3.4-stable.. below is a patch that fixes it
 with some KASSERT's to insure that the M_PKTHDR assumptions are
 correct.
 
 -Archie
 
 ___________________________________________________________________________
 Archie Cobbs   *   Whistle Communications, Inc.  *   http://www.whistle.com
 
 Index: sys/netinet/ip_input.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
 retrieving revision 1.111.2.5
 diff -u -r1.111.2.5 ip_input.c
 --- ip_input.c	2000/01/18 16:03:55	1.111.2.5
 +++ ip_input.c	2000/01/26 23:57:18
 @@ -909,9 +909,14 @@
  	(void) m_free(dtom(fp));
  	m->m_len += (IP_VHL_HL(ip->ip_vhl) << 2);
  	m->m_data -= (IP_VHL_HL(ip->ip_vhl) << 2);
 -	/* some debugging cruft by sklower, below, will go away soon */
 -	if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
 +
 +	/*
 +	 * Recompute total packet length
 +	 */
 +	KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__));
 +	{
  		register int plen = 0;
 +
  		for (t = m; m; m = m->m_next)
  			plen += m->m_len;
  		t->m_pkthdr.len = plen;
 Index: sys/netinet/tcp_input.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/tcp_input.c,v
 retrieving revision 1.82.2.3
 diff -u -r1.82.2.3 tcp_input.c
 --- tcp_input.c	1999/10/14 11:49:38	1.82.2.3
 +++ tcp_input.c	2000/01/26 23:57:22
 @@ -292,6 +292,8 @@
  	short ostate = 0;
  #endif
  
 +	KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__));
 +
  	bzero((char *)&to, sizeof(to));
  
  	tcpstat.tcps_rcvtotal++;
 @@ -371,8 +373,14 @@
  	/*
  	 * 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);
 +	{
 +		const int diff = sizeof(struct tcpiphdr) + off
 +					- sizeof(struct tcphdr);
 +
 +		m->m_data += diff;
 +		m->m_len -= diff;
 +		m->m_pkthdr.len -= diff;
 +	}
  
  	/*
  	 * Locate pcb for segment.
 @@ -1954,8 +1962,11 @@
  	struct tcpiphdr *ti;
  	register struct mbuf *m;
  {
 +	struct mbuf *m0 = m;
  	int cnt = ti->ti_urp - 1;
  
 +	KASSERT(m->m_flags & M_PKTHDR, ("%s: not pkthdr", __FUNCTION__));
 +
  	while (cnt >= 0) {
  		if (m->m_len > cnt) {
  			char *cp = mtod(m, caddr_t) + cnt;
 @@ -1965,6 +1976,7 @@
  			tp->t_oobflags |= TCPOOB_HAVEDATA;
  			bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1));
  			m->m_len--;
 +			m0->m_pkthdr.len--;
  			return;
  		}
  		cnt -= m->m_len;
 
State-Changed-From-To: open->closed 
State-Changed-By: dd 
State-Changed-When: Sat Jun 9 17:00:48 PDT 2001 
State-Changed-Why:  
RELENG_3 no longer supported for anything but the most critical fixes. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=15175 
>Unformatted:
