summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exit.c
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2002-12-15 18:50:04 +0000
committerdillon <dillon@FreeBSD.org>2002-12-15 18:50:04 +0000
commit2925e70a14eb46bd10c8905fd619024bb19f7f9d (patch)
treedc75f5c7dd091cc88d3a3e3cb29cc922f32d144b /sys/kern/kern_exit.c
parenta8978bcb956a21704b2db069d37f09c6c01395b1 (diff)
downloadFreeBSD-src-2925e70a14eb46bd10c8905fd619024bb19f7f9d.zip
FreeBSD-src-2925e70a14eb46bd10c8905fd619024bb19f7f9d.tar.gz
Fix a refcount race with the vmspace structure. In order to prevent
resource starvation we clean-up as much of the vmspace structure as we can when the last process using it exits. The rest of the structure is cleaned up when it is reaped. But since exit1() decrements the ref count it is possible for a double-free to occur if someone else, such as the process swapout code, references and then dereferences the structure. Additionally, the final cleanup of the structure should not occur until the last process referencing it is reaped. This commit solves the problem by introducing a secondary reference count, calling 'vm_exitingcnt'. The normal reference count is decremented on exit and vm_exitingcnt is incremented. vm_exitingcnt is decremented when the process is reaped. When both vm_exitingcnt and vm_refcnt are 0, the structure is freed for real. MFC after: 3 weeks
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r--sys/kern/kern_exit.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 38d8092..8737bed 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -287,7 +287,15 @@ exit1(td, rv)
* Need to do this early enough that we can still sleep.
* Can't free the entire vmspace as the kernel stack
* may be mapped within that space also.
+ *
+ * Processes sharing the same vmspace may exit in one order, and
+ * get cleaned up by vmspace_exit() in a different order. The
+ * last exiting process to reach this point releases as much of
+ * the environment as it can, and the last process cleaned up
+ * by vmspace_exit() (which decrements exitingcnt) cleans up the
+ * remainder.
*/
+ ++vm->vm_exitingcnt;
if (--vm->vm_refcnt == 0) {
if (vm->vm_shm)
shmexit(p);
@@ -297,7 +305,6 @@ exit1(td, rv)
vm_page_unlock_queues();
(void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map),
vm_map_max(&vm->vm_map));
- vm->vm_freer = p;
}
sx_xlock(&proctree_lock);
OpenPOWER on IntegriCloud