Now that SYSVSHM is modularized, reattach the linkages from uvm so that

we can correctly clean up on process exit or fork.

Without this, firefox attaches to a shared memory segment but doesn't
detach before exit.  Thus once firefox causes an autoload for sysv_ipc
it cannot be unloaded since the segment still retains references.
This commit is contained in:
pgoyette 2015-11-05 00:10:47 +00:00
parent 9875a0c6a0
commit 51126f7011
3 changed files with 32 additions and 20 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysv_shm.c,v 1.128 2015/05/13 01:16:15 pgoyette Exp $ */
/* $NetBSD: sysv_shm.c,v 1.129 2015/11/05 00:10:47 pgoyette Exp $ */
/*-
* Copyright (c) 1999, 2007 The NetBSD Foundation, Inc.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sysv_shm.c,v 1.128 2015/05/13 01:16:15 pgoyette Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysv_shm.c,v 1.129 2015/11/05 00:10:47 pgoyette Exp $");
#ifdef _KERNEL_OPT
#include "opt_sysv.h"
@ -990,6 +990,10 @@ shminit(void)
kern_has_sysvshm = 1;
/* Load the callback function pointers for the uvm subsystem */
uvm_shmexit = shmexit;
uvm_shmfork = shmfork;
sysvipcinit();
}
@ -1006,6 +1010,10 @@ shmfini(void)
return 1;
}
/* Clear the callback function pointers for the uvm subsystem */
uvm_shmexit = NULL;
uvm_shmfork = NULL;
/* Destroy all condvars */
for (i = 0; i < shminfo.shmmni; i++)
cv_destroy(&shm_cv[i]);

View File

@ -1,4 +1,4 @@
/* $NetBSD: shm.h,v 1.49 2015/05/13 01:16:15 pgoyette Exp $ */
/* $NetBSD: shm.h,v 1.50 2015/11/05 00:10:48 pgoyette Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@ -178,6 +178,9 @@ void shmfork(struct vmspace *, struct vmspace *);
void shmexit(struct vmspace *);
int shmctl1(struct lwp *, int, int, struct shmid_ds *);
extern void (*uvm_shmexit)(struct vmspace *);
extern void (*uvm_shmfork)(struct vmspace *, struct vmspace *);
#define SYSCTL_FILL_SHM(src, dst) do { \
SYSCTL_FILL_PERM((src).shm_perm, (dst).shm_perm); \
(dst).shm_segsz = (src).shm_segsz; \

View File

@ -1,4 +1,4 @@
/* $NetBSD: uvm_map.c,v 1.335 2015/09/24 14:35:15 christos Exp $ */
/* $NetBSD: uvm_map.c,v 1.336 2015/11/05 00:10:48 pgoyette Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.335 2015/09/24 14:35:15 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.336 2015/11/05 00:10:48 pgoyette Exp $");
#include "opt_ddb.h"
#include "opt_uvmhist.h"
@ -90,9 +90,7 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.335 2015/09/24 14:35:15 christos Exp $
#include "opt_user_va0_disable_default.h"
#endif
#ifdef SYSVSHM
#include <sys/shm.h>
#endif
#include <uvm/uvm.h>
#include <uvm/uvm_readahead.h>
@ -299,6 +297,15 @@ static vsize_t uvm_rb_maxgap(const struct vm_map_entry *);
(ROOT_ENTRY(map) == (entry) \
? NULL : (struct vm_map_entry *)RB_FATHER(&(entry)->rb_node))
/*
* These get filled in if/when SYSVSHM shared memory code is loaded
*
* We do this with function pointers rather the #ifdef SYSVSHM so the
* SYSVSHM code can be loaded and unloaded
*/
void (*uvm_shmexit)(struct vmspace *) = NULL;
void (*uvm_shmfork)(struct vmspace *, struct vmspace *) = NULL;
static int
uvm_map_compare_nodes(void *ctx, const void *nparent, const void *nkey)
{
@ -4071,14 +4078,11 @@ uvmspace_exec(struct lwp *l, vaddr_t start, vaddr_t end, bool topdown)
* vm space!
*/
#ifdef SYSVSHM
/*
* SYSV SHM semantics require us to kill all segments on an exec
*/
if (ovm->vm_shm)
shmexit(ovm);
#endif
if (uvm_shmexit && ovm->vm_shm)
(*uvm_shmexit)(ovm);
/*
* POSIX 1003.1b -- "lock future mappings" is revoked
@ -4170,11 +4174,10 @@ uvmspace_free(struct vmspace *vm)
map->flags |= VM_MAP_DYING;
pmap_remove_all(map->pmap);
#ifdef SYSVSHM
/* Get rid of any SYSV shared memory segments. */
if (vm->vm_shm != NULL)
shmexit(vm);
#endif
if (uvm_shmexit && vm->vm_shm != NULL)
(*uvm_shmexit)(vm);
if (map->nentries) {
uvm_unmap_remove(map, vm_map_min(map), vm_map_max(map),
@ -4456,10 +4459,8 @@ uvmspace_fork(struct vmspace *vm1)
pmap_update(old_map->pmap);
vm_map_unlock(old_map);
#ifdef SYSVSHM
if (vm1->vm_shm)
shmfork(vm1, vm2);
#endif
if (uvm_shmfork && vm1->vm_shm)
(*uvm_shmfork)(vm1, vm2);
#ifdef PMAP_FORK
pmap_fork(vm1->vm_map.pmap, vm2->vm_map.pmap);