summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2003-01-13 23:04:32 +0000
committerdillon <dillon@FreeBSD.org>2003-01-13 23:04:32 +0000
commitce710d36cc14755344115d36e5459a39e385e64d (patch)
tree3c875a6ad9627d4125943a71834883e1b354baa5 /sys/kern
parente08a8297e2779e8d6e2160c041440e8f3908ece8 (diff)
downloadFreeBSD-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.c3
-rw-r--r--sys/kern/kern_exit.c3
-rw-r--r--sys/kern/sysv_ipc.c7
-rw-r--r--sys/kern/sysv_shm.c32
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
OpenPOWER on IntegriCloud