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>