diff options
author | dillon <dillon@FreeBSD.org> | 2003-01-13 23:04:32 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 2003-01-13 23:04:32 +0000 |
commit | ce710d36cc14755344115d36e5459a39e385e64d (patch) | |
tree | 3c875a6ad9627d4125943a71834883e1b354baa5 /sys/kern | |
parent | e08a8297e2779e8d6e2160c041440e8f3908ece8 (diff) | |
download | FreeBSD-src-ce710d36cc14755344115d36e5459a39e385e64d.zip FreeBSD-src-ce710d36cc14755344115d36e5459a39e385e64d.tar.gz |
It is possible for an active aio to prevent shared memory from being
dereferenced when a process exits due to the vmspace ref-count being
bumped. Change shmexit() and shmexit_myhook() to take a vmspace instead
of a process and call it in vmspace_dofree(). This way if it is missed
in exit1()'s early-resource-free it will still be caught when the zombie is
reaped.
Also fix a potential race in shmexit_myhook() by NULLing out
vmspace->vm_shm prior to calling shm_delete_mapping() and free().
MFC after: 7 days
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_exec.c | 3 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 3 | ||||
-rw-r--r-- | sys/kern/sysv_ipc.c | 7 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 32 |
4 files changed, 20 insertions, 25 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 543bd6a..0ee36ba 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -864,8 +864,7 @@ exec_new_vmspace(imgp, sv) map = &vmspace->vm_map; if (vmspace->vm_refcnt == 1 && vm_map_min(map) == sv->sv_minuser && vm_map_max(map) == sv->sv_maxuser) { - if (vmspace->vm_shm) - shmexit(p); + shmexit(vmspace); vm_page_lock_queues(); pmap_remove_pages(vmspace_pmap(vmspace), vm_map_min(map), vm_map_max(map)); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 8737bed..c34f26f 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -297,8 +297,7 @@ exit1(td, rv) */ ++vm->vm_exitingcnt; if (--vm->vm_refcnt == 0) { - if (vm->vm_shm) - shmexit(p); + shmexit(vm); vm_page_lock_queues(); pmap_remove_pages(vmspace_pmap(vm), vm_map_min(&vm->vm_map), vm_map_max(&vm->vm_map)); diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c index fc5fd8f..55d39de 100644 --- a/sys/kern/sysv_ipc.c +++ b/sys/kern/sysv_ipc.c @@ -42,7 +42,7 @@ #include <sys/ucred.h> void (*shmfork_hook)(struct proc *, struct proc *) = NULL; -void (*shmexit_hook)(struct proc *) = NULL; +void (*shmexit_hook)(struct vmspace *) = NULL; /* called from kern_fork.c */ void @@ -57,12 +57,11 @@ shmfork(p1, p2) /* called from kern_exit.c */ void -shmexit(p) - struct proc *p; +shmexit(struct vmspace *vm) { if (shmexit_hook != NULL) - shmexit_hook(p); + shmexit_hook(vm); return; } diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 6c9d34a..04c9b2a 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -97,12 +97,12 @@ static void shm_deallocate_segment(struct shmid_ds *); static int shm_find_segment_by_key(key_t); static struct shmid_ds *shm_find_segment_by_shmid(int); static struct shmid_ds *shm_find_segment_by_shmidx(int); -static int shm_delete_mapping(struct proc *p, struct shmmap_state *); +static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *); static void shmrealloc(void); static void shminit(void); static int sysvshm_modload(struct module *, int, void *); static int shmunload(void); -static void shmexit_myhook(struct proc *p); +static void shmexit_myhook(struct vmspace *vm); static void shmfork_myhook(struct proc *p1, struct proc *p2); static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS); @@ -214,9 +214,7 @@ shm_deallocate_segment(shmseg) } static int -shm_delete_mapping(p, shmmap_s) - struct proc *p; - struct shmmap_state *shmmap_s; +shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s) { struct shmid_ds *shmseg; int segnum, result; @@ -227,8 +225,7 @@ shm_delete_mapping(p, shmmap_s) segnum = IPCID_TO_IX(shmmap_s->shmid); shmseg = &shmsegs[segnum]; size = round_page(shmseg->shm_segsz); - result = vm_map_remove(&p->p_vmspace->vm_map, shmmap_s->va, - shmmap_s->va + size); + result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size); if (result != KERN_SUCCESS) return (EINVAL); shmmap_s->shmid = -1; @@ -278,7 +275,7 @@ shmdt(td, uap) error = EINVAL; goto done2; } - error = shm_delete_mapping(p, shmmap_s); + error = shm_delete_mapping(p->p_vmspace, shmmap_s); done2: mtx_unlock(&Giant); return (error); @@ -768,20 +765,21 @@ shmfork_myhook(p1, p2) } static void -shmexit_myhook(p) - struct proc *p; +shmexit_myhook(struct vmspace *vm) { - struct shmmap_state *shmmap_s; + struct shmmap_state *base, *shm; int i; GIANT_REQUIRED; - shmmap_s = p->p_vmspace->vm_shm; - for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) - if (shmmap_s->shmid != -1) - shm_delete_mapping(p, shmmap_s); - free(p->p_vmspace->vm_shm, M_SHM); - p->p_vmspace->vm_shm = NULL; + if ((base = vm->vm_shm) != NULL) { + vm->vm_shm = NULL; + for (i = 0, shm = base; i < shminfo.shmseg; i++, shm++) { + if (shm->shmid != -1) + shm_delete_mapping(vm, shm); + } + free(base, M_SHM); + } } static void |