From owner-freebsd-bugs@FreeBSD.ORG Wed Jun 16 18:00:42 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3FD5B16A4CE for ; Wed, 16 Jun 2004 18:00:42 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 334A343D4C for ; Wed, 16 Jun 2004 18:00:42 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.11/8.12.11) with ESMTP id i5GI0eJX063076 for ; Wed, 16 Jun 2004 18:00:40 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id i5GI0e3I063071; Wed, 16 Jun 2004 18:00:40 GMT (envelope-from gnats) Resent-Date: Wed, 16 Jun 2004 18:00:40 GMT Resent-Message-Id: <200406161800.i5GI0e3I063071@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Mark W. Krentel" Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5A1E816A4FC for ; Wed, 16 Jun 2004 17:53:55 +0000 (GMT) Received: from www.freebsd.org (www.freebsd.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3DB1B43D1F for ; Wed, 16 Jun 2004 17:53:55 +0000 (GMT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.12.11/8.12.11) with ESMTP id i5GHrivJ097900 for ; Wed, 16 Jun 2004 17:53:44 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.12.11/8.12.11/Submit) id i5GHrh5D097899; Wed, 16 Jun 2004 17:53:43 GMT (envelope-from nobody) Message-Id: <200406161753.i5GHrh5D097899@www.freebsd.org> Date: Wed, 16 Jun 2004 17:53:43 GMT From: "Mark W. Krentel" To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-2.3 Subject: kern/68017: fork with INHERIT_NONE miscounts VM map sizes X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Jun 2004 18:00:42 -0000 >Number: 68017 >Category: kern >Synopsis: fork with INHERIT_NONE miscounts VM map sizes >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Jun 16 18:00:40 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Mark W. Krentel >Release: 5.2-Current as of May 26, 2004 >Organization: none >Environment: 5.2-Current as of May 26, 2004 >Description: During fork(), vmspace_fork() in sys/vm/vm_map.c constructs the new vmspace and vm_map by copying map entries according to their inheritance. Map entries with VM_INHERIT_NONE are correctly skipped, but the size of the new map is incorrectly and always set to the size of the old map, thus ingoring the INHERIT_NONE regions. new_map->size = old_map->size; This results in a new size that is too large whenever the original process has any region with inheritance INHERIT_NONE. Furthermore, the following fields in struct vmspace are also bcopy()'d directly from the old vmspace without regard to the inheritance of the segments. #define vm_startcopy vm_rssize segsz_t vm_rssize; /* current resident set size in pages */ segsz_t vm_swrss; /* resident set size before last swap */ segsz_t vm_tsize; /* text size (pages) XXX */ segsz_t vm_dsize; /* data size (pages) XXX */ segsz_t vm_ssize; /* stack size (pages) */ caddr_t vm_taddr; /* (c) user virtual address of text */ caddr_t vm_daddr; /* (c) user virtual address of data */ caddr_t vm_maxsaddr; /* user VA at max stack growth */ #define vm_endcopy vm_exitingcnt vm_taddr and vm_daddr are probably ok, but some of the others may also be incorrect if the original process has regions with INHERIT_NONE. Btw, nentries in struct vm_map is computed correctly because it is initialized to 0 in vm_map_zinit() and then incremented in vm_map_entry_link(). I guess no one ever uses INHERIT_NONE. In 5.2 with INVARIANTS turned on, vm_map_zdtor() notices the discrepancy in vm_map.size and panics, which is pretty noticeable. >How-To-Repeat: In 5.2 with INVARIANTS turned on, the following program produces a panic in vm_map_zdtor() because map->size > 0 when the child exits. #include #include #include int main() { void *p; p = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0); minherit(p, 4096, INHERIT_NONE); fork(); return (0); } >Fix: This patch fixes the vm_map.size problem. Note that size (along with nentries) is initialized to 0 in vm_map_zinit(). I don't really know enough about the other vmspace entries (vm_tsize, vm_dsize, etc.) to offer an intelligent patch for them. Index: sys/vm/vm_map.c =================================================================== RCS file: /data/ncvs/src/sys/vm/vm_map.c,v retrieving revision 1.338 diff -u -r1.338 vm_map.c --- sys/vm/vm_map.c 25 May 2004 18:28:52 -0000 1.338 +++ sys/vm/vm_map.c 16 Jun 2004 17:22:49 -0000 @@ -2431,6 +2431,7 @@ */ vm_map_entry_link(new_map, new_map->header.prev, new_entry); + new_map->size += new_entry->end - new_entry->start; /* * Update the physical map @@ -2452,6 +2453,7 @@ new_entry->object.vm_object = NULL; vm_map_entry_link(new_map, new_map->header.prev, new_entry); + new_map->size += new_entry->end - new_entry->start; vm_map_copy_entry(old_map, new_map, old_entry, new_entry); break; @@ -2459,7 +2461,6 @@ old_entry = old_entry->next; } - new_map->size = old_map->size; old_map->infork = 0; vm_map_unlock(old_map); >Release-Note: >Audit-Trail: >Unformatted: