Date: Thu, 20 Jan 2005 17:47:57 -0500 From: "Mark W. Krentel" <krentel@dreamscape.com> To: Kris Kennaway <kris@obsecurity.org>, freebsd-current@freebsd.org Cc: Alan Cox <alc@cs.rice.edu> Subject: Re: fstat triggered INVARIANTS panic in memrw() Message-ID: <200501202247.j0KMlvJH032907@blue.mwk.domain> In-Reply-To: Your message of "Tue, 18 Jan 2005 23:02:20 CST." <20050119050220.GU3194@noel.cs.rice.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
First, let me check that your panic requires three things to trigger:
(1) heavy load, in your case ports building, (2) INVARIANTS compiled
into the kernel, and (3) many calls to fstat(1). Is that right?
Also, you're running 6.0-current on an x86 SMP machine? Can you bound
the problem between two dates, that is, you compiled kernel/world on
date X and it was ok, and updated on date Y and it panicked? Are you
changing the default kernel address space (3 Gig user and 1 Gig
kernel) via KVA_PAGES?
Following Alan's diagnosis, I added some printf()s to check the
arguments to kernacc() and vm_map_check_protection(). I didn't get a
panic, but I can confirm that kernacc() is being called with arguments
that constitute address wrap. My tests were on a single-CPU P3-933.
I ran buildworld along with a loop of fstat(1)s, and the address wrap
happened within seconds. It required both (1) and (3) above,
INVARIANTS may be a red herring, I'm not sure.
How long did it take for your machine to panic? Mine didn't panic,
but maybe I didn't run the test long enough, or maybe I don't have
enough open files.
Anyway, try this patch, see if it avoids the panic for you.
--Mark
Index: vm_glue.c
===================================================================
RCS file: /data/ncvs/src/sys/vm/vm_glue.c,v
retrieving revision 1.209
diff -u -r1.209 vm_glue.c
--- vm_glue.c 7 Jan 2005 02:29:27 -0000 1.209
+++ vm_glue.c 20 Jan 2005 22:01:21 -0000
@@ -133,6 +133,11 @@
KASSERT((rw & ~VM_PROT_ALL) == 0,
("illegal ``rw'' argument to kernacc (%x)\n", rw));
+
+ if ((vm_offset_t)addr + len > kernel_map->max_offset ||
+ (vm_offset_t)addr + len < (vm_offset_t)addr)
+ return (FALSE);
+
prot = rw;
saddr = trunc_page((vm_offset_t)addr);
eaddr = round_page((vm_offset_t)addr + len);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200501202247.j0KMlvJH032907>
