From owner-freebsd-hackers Fri Oct 11 0: 3:34 2002 Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0D0D537B401 for ; Fri, 11 Oct 2002 00:03:31 -0700 (PDT) Received: from flamingo.mail.pas.earthlink.net (flamingo.mail.pas.earthlink.net [207.217.120.232]) by mx1.FreeBSD.org (Postfix) with ESMTP id 92E8B43EC2 for ; Fri, 11 Oct 2002 00:03:30 -0700 (PDT) (envelope-from tlambert2@mindspring.com) Received: from pool0520.cvx40-bradley.dialup.earthlink.net ([216.244.44.10] helo=mindspring.com) by flamingo.mail.pas.earthlink.net with esmtp (Exim 3.33 #1) id 17ztpX-0002LP-00; Fri, 11 Oct 2002 00:03:28 -0700 Message-ID: <3DA67778.3312A104@mindspring.com> Date: Fri, 11 Oct 2002 00:02:16 -0700 From: Terry Lambert X-Mailer: Mozilla 4.79 [en] (Win98; U) X-Accept-Language: en MIME-Version: 1.0 To: abe Cc: Bill Fumerola , hackers@freebsd.org Subject: Re: fatal trap 12 kernel panic References: <20021011044636.GA84506@dipole.informationwave.net> <20021011045013.GO80284@elvis.mu.org> <20021011044956.GA87029@dipole.informationwave.net> Content-Type: multipart/mixed; boundary="------------F3BB264D75970FAB27878B65" Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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