From nobody@FreeBSD.org  Tue Aug 24 13:53:22 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 295C01065698
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 24 Aug 2010 13:53:22 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id F1BA48FC08
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 24 Aug 2010 13:53:21 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o7ODrLXl084079
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 24 Aug 2010 13:53:21 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o7ODrLDH084078;
	Tue, 24 Aug 2010 13:53:21 GMT
	(envelope-from nobody)
Message-Id: <201008241353.o7ODrLDH084078@www.freebsd.org>
Date: Tue, 24 Aug 2010 13:53:21 GMT
From: Jens Kassel <jens.kassel@servicefactory.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: kernel panic in ipfilter IP fragments with TCP paylaod in reverse order  
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         149937
>Category:       kern
>Synopsis:       [ipfilter] [patch] kernel panic in ipfilter IP fragments with TCP paylaod in reverse order
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    cy
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Aug 24 14:00:02 UTC 2010
>Closed-Date:    
>Last-Modified:  Wed Jul 03 05:22:39 UTC 2013
>Originator:     Jens Kassel
>Release:        FreeBSD 7.2
>Organization:
Servicefactory AB
>Environment:
FreeBSD h167.servicefactory.com 7.2-RELEASE FreeBSD 7.2-RELEASE #0: Fri May  1 08:49:13 UTC 2009     root@walker.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
Kernel panic in ipfilter when trying to NAT IP fragments with TCP payload sent in "wrong" order. The following line in ip_nat.c will crash on NULL pointer.



 if (nat->nat_p == IPPROTO_TCP)
                nat->nat_seqnext[0] = ntohl(tcp->th_seq);


tcp is not set.


This is not fixed in FreeBSD 8.1
>How-To-Repeat:
Set up ipnat:
List of active MAP/Redirect filters:
map bge2 10.10.0.0/24 -> 0.0.0.0/32 proxy port ftp ftp/tcp
map bge2 10.10.0.0/24 -> 0.0.0.0/32 portmap tcp/udp 1025:65500
map bge2 10.10.0.0/24 -> 0.0.0.0/32
map lo3 10.10.0.0/24 -> 127.0.0.3/32 portmap tcp/udp 9000:65500
map lo0 10.10.0.0/24 -> 127.0.0.1/32 portmap udp 9000:65500
map-block lo0 10.10.0.0/24 -> 127.0.0.1/32 ports 10 tcp
rdr lo0 0.0.0.0/0 port 80 -> 127.0.0.1 port 65501 tcp
rdr lo0 0.0.0.0/0 port 443 -> 127.0.0.1 port 65502 tcp
rdr lo3 0.0.0.0/0 port 8080 -> 127.0.0.3 port 65504 tcp
rdr lo1 0.0.0.0/0 port 8080 -> 127.0.0.2 port 65503 tcp
map lo1 10.10.0.0/24 -> 127.0.0.2/32 portmap tcp/udp 9000:65500

List of active sessions:



Send correct fragmented IP packet with proto TCP and offset larger than 0 (not first fragment). Source 10.10.0.x. Destination some externel host.
>Fix:
The following patch will discard these fragments if sent in reverse order (solving the problem).


--- ip_nat.c.org        2010-08-24 13:43:56.000000000 +0200
+++ ip_nat.c    2010-08-24 14:41:33.000000000 +0200
@@ -3770,6 +3770,17 @@
                if ((nflags & IPN_TCPUDP))
                        tcp = fin->fin_dp;
        }
+       else
+        {
+                /* Discard TCP unknown fragments out of order
+                */
+                if ((IPPROTO_TCP == fin->fin_p) &&  !fr_nat_knownfrag(fin))
+                {
+                       nat_stats.ns_badnat++;
+                        return -1;
+                }
+        }
+

        ipa = fin->fin_saddr;

@@ -4065,6 +4076,17 @@
                        dport = tcp->th_dport;
                }
        }
+       else
+        {
+                /* Discard TCP unknown fragments out of order
+                */
+                if ((IPPROTO_TCP == fin->fin_p) &&  !fr_nat_knownfrag(fin))
+                {
+                       nat_stats.ns_badnat++;
+                        return -1;
+                }
+        }
+

        in = fin->fin_dst;


>Release-Note:
>Audit-Trail:

From: "Jens" <jens.kassel@servicefactory.com>
To: <bug-followup@FreeBSD.org>
Cc:  
Subject: Re: kern/149937: kernel panic in ipfilter IP fragments with TCP paylaod in reverse order
Date: Thu, 26 Aug 2010 13:23:07 +0200

 This is a multi-part message in MIME format.
 
 ------=_NextPart_000_004B_01CB4521.D27F8180
 Content-Type: text/plain;
 	charset="us-ascii"
 Content-Transfer-Encoding: 7bit
 
 Use this patch instead
 
 --- ip_nat.c.orig       2009-04-15 05:14:26.000000000 +0200
 +++ ip_nat.c    2010-08-26 13:14:32.000000000 +0200
 @@ -3783,7 +3783,16 @@
         else if ((nat = nat_outlookup(fin, nflags|NAT_SEARCH, (u_int)fin->fin_p,
                                       fin->fin_src, fin->fin_dst))) {
                 nflags = nat->nat_flags;
 -       } else {
 +       }
 +       else if ((fin->fin_p == IPPROTO_TCP) &&
 +               ((fin->fin_off != 0) || (fin->fin_flx & FI_SHORT)))
 +       {
 +               /* Discard TCP IP fragmentes without matching NAT rule
 +               (or if fragment lock is set) if offset is nonezero */
 +               nat = NULL;
 +               nat_stats.ns_badnat++;
 +       }
 +       else {
                 u_32_t hv, msk, nmsk;
  
                 /*
 @@ -4078,7 +4087,16 @@
         else if ((nat = nat_inlookup(fin, nflags|NAT_SEARCH, (u_int)fin->fin_p,
                                      fin->fin_src, in))) {
                 nflags = nat->nat_flags;
 -       } else {
 +       }
 +       else if ((fin->fin_p == IPPROTO_TCP) &&
 +               ((fin->fin_off != 0) || (fin->fin_flx & FI_SHORT)))
 +       {
 +               /* Discard TCP IP fragmentes without matching NAT rule
 +               (or if fragment lock is set) if offset is nonezero */
 +               nat = NULL;
 +               nat_stats.ns_badnat++;
 +       }
 +       else {
                 u_32_t hv, msk, rmsk;
  
                 RWLOCK_EXIT(&ipf_nat);
 
 ------=_NextPart_000_004B_01CB4521.D27F8180--
 
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Fri Aug 27 07:42:03 UTC 2010 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=149937 
Responsible-Changed-From-To: freebsd-net->cy 
Responsible-Changed-By: cy 
Responsible-Changed-When: Wed Jul 3 05:22:21 UTC 2013 
Responsible-Changed-Why:  
Mine. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=149937 
>Unformatted:
