Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Oct 2002 00:02:16 -0700
From:      Terry Lambert <tlambert2@mindspring.com>
To:        abe <abe@informationwave.net>
Cc:        Bill Fumerola <billf@mu.org>, hackers@freebsd.org
Subject:   Re: fatal trap 12 kernel panic
Message-ID:  <3DA67778.3312A104@mindspring.com>
References:  <20021011044636.GA84506@dipole.informationwave.net> <20021011045013.GO80284@elvis.mu.org> <20021011044956.GA87029@dipole.informationwave.net>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------F3BB264D75970FAB27878B65
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

abe wrote:
> On Thu, Oct 10, 2002 at 09:50:13PM -0700, Bill Fumerola wrote:
> > On Fri, Oct 11, 2002 at 12:46:36AM -0400, abe wrote:
> > static u_int32_t dyn_buckets = 256; /* must be power of 2 */
> 
> Well another issue solved, need thicker glasses it appears.  Thanks much
> Bill.  Funny thing is, it's been running without issue for almost a year
> now.  Interesting.

Try setting it back to 500, and see if you can get a crash.

The value of dyn_buckets is seperate from the curr_dyn_buckets
in both netinet/ipfw.c and netinet/ipfw2.c.

In theory, the value is checked for a power of 2 value before
it is used, and that's used to resize.  If it isn't a power of
2, then it gets reset to back to curr_dyn_buckets.

There is a window in the resize in netinet/ipfw2.c that could
cause a probem (the old array is freed before the new array
has been successfully allocated -- order of operation bug, IMO).

But there should not be an issue with the size being changed...
particularly on ip_output() called from send() called from user
space.


There's also a problem with initial sizing, and a problem if the
initial allocation fails, and a couple other problems.  I have
attached a patch which fixes these problems.

Note: This patch may not fix your "500" problem... the correct
way to fix that is probably to have the sysctl for dyn_buckets
use a set procedure, which refuses the set if it's not a power
of 2 and/or rounds it up to the next power of 2 < 65536.

-- Terry
--------------F3BB264D75970FAB27878B65
Content-Type: text/plain; charset=us-ascii;
 name="ipfw.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ipfw.diff"

Index: ip_fw.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_fw.c,v
retrieving revision 1.188
diff -u -r1.188 ip_fw.c
--- ip_fw.c	22 Jun 2002 11:51:02 -0000	1.188
+++ ip_fw.c	11 Oct 2002 03:01:38 -0000
@@ -862,23 +862,40 @@
     struct ipfw_dyn_rule *r ;
 
     int i ;
+
+    /* new allocation or reallocation */
     if (ipfw_dyn_v == NULL ||
 		(dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
-	/* try reallocation, make sure we have a power of 2 */
+	/* make sure we have a power of 2 */
 	u_int32_t i = dyn_buckets ;
 	while ( i > 0 && (i & 1) == 0 )
 	    i >>= 1 ;
 	if (i != 1) /* not a power of 2 */
 	    dyn_buckets = curr_dyn_buckets ; /* reset */
-	else {
-	    curr_dyn_buckets = dyn_buckets ;
-	    if (ipfw_dyn_v != NULL)
-		free(ipfw_dyn_v, M_IPFW);
-	    ipfw_dyn_v = malloc(curr_dyn_buckets * sizeof r,
+
+	/* new allocation or reallocation; avoid the realloction on reset */
+	if (ipfw_dyn_v == NULL ||
+		(dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
+	    ipfw_dyn_rule **new_ipfw_dyn_v;
+
+	    /* 
+	     * try the allocation; if it's a reallocation, and the malloc
+	     * fails, keep the old area and reset, instead.
+	     */
+	    new_ipfw_dyn_v = malloc(dyn_buckets * sizeof r,
                    M_IPFW, M_DONTWAIT | M_ZERO);
-	    if (ipfw_dyn_v == NULL)
-		return NULL; /* failed ! */
+	    if (new_ipfw_dyn_v != NULL) {
+		if (ipfw_dyn_v != NULL)
+		    free(ipfw_dyn_v, M_IPFW);
+		ipfw_dyn_v = new_ipfw_dyn_v;
+		curr_dyn_buckets = dyn_buckets ;
+	    } else {
+		dyn_buckets = curr_dyn_buckets ; /* reset */
+	    }
 	}
+
+	if (ipfw_dyn_v == NULL)
+	    return NULL; /* failed ! */
     }
     i = hash_packet(id);
 

--------------F3BB264D75970FAB27878B65--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3DA67778.3312A104>