FreeBSD Bugzilla – Attachment 234850 Details for
Bug 257555
POSIX shared memory: Cleanup non-anonymous allocations on jail exit
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Remove a prison's shm segments when the prison is removed
shm.diff (text/plain), 6.95 KB, created by
Jamie Gritton
on 2022-06-22 03:28:44 UTC
(
hide
)
Description:
Remove a prison's shm segments when the prison is removed
Filename:
MIME Type:
Creator:
Jamie Gritton
Created:
2022-06-22 03:28:44 UTC
Size:
6.95 KB
patch
obsolete
>diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c >index 0521e06ce223..2175f8dde3a0 100644 >--- a/sys/kern/kern_jail.c >+++ b/sys/kern/kern_jail.c >@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$"); > #include <sys/jail.h> > #include <sys/linker.h> > #include <sys/lock.h> >+#include <sys/mman.h> > #include <sys/mutex.h> > #include <sys/racct.h> > #include <sys/rctl.h> >@@ -143,6 +144,7 @@ static void prison_complete(void *context, int pending); > static void prison_deref(struct prison *pr, int flags); > static void prison_deref_kill(struct prison *pr, struct prisonlist *freeprison); > static int prison_lock_xlock(struct prison *pr, int flags); >+static void prison_cleanup(struct prison *pr); > static void prison_free_not_last(struct prison *pr); > static void prison_proc_free_not_last(struct prison *pr); > static void prison_set_allow_locked(struct prison *pr, unsigned flag, >@@ -2994,8 +2996,7 @@ prison_deref(struct prison *pr, int flags) > pr->pr_state = PRISON_STATE_DYING; > mtx_unlock(&pr->pr_mtx); > flags &= ~PD_LOCKED; >- (void)osd_jail_call(pr, >- PR_METHOD_REMOVE, NULL); >+ prison_cleanup(pr); > } > } > } >@@ -3150,7 +3151,7 @@ prison_deref_kill(struct prison *pr, struct prisonlist *freeprison) > } > if (!(cpr->pr_flags & PR_REMOVE)) > continue; >- (void)osd_jail_call(cpr, PR_METHOD_REMOVE, NULL); >+ prison_cleanup(cpr); > mtx_lock(&cpr->pr_mtx); > cpr->pr_flags &= ~PR_REMOVE; > if (cpr->pr_flags & PR_PERSIST) { >@@ -3186,7 +3187,7 @@ prison_deref_kill(struct prison *pr, struct prisonlist *freeprison) > if (rpr != NULL) > LIST_REMOVE(rpr, pr_sibling); > >- (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); >+ prison_cleanup(pr); > mtx_lock(&pr->pr_mtx); > if (pr->pr_flags & PR_PERSIST) { > pr->pr_flags &= ~PR_PERSIST; >@@ -3232,6 +3233,19 @@ prison_lock_xlock(struct prison *pr, int flags) > return flags; > } > >+/* >+ * Release prison resources when it starts dying (when the last user >+ * reference is dropped, or when it is killed). >+ */ >+static void >+prison_cleanup(struct prison *pr) >+{ >+ sx_assert(&allprison_lock, SA_XLOCKED); >+ mtx_assert(&pr->pr_mtx, MA_NOTOWNED); >+ shm_prison_cleanup(pr); >+ (void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL); >+} >+ > /* > * Set or clear a permission bit in the pr_allow field, passing restrictions > * (cleared permission) down to child jails. >diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c >index 658b48e2e2e1..2e902fe0ec90 100644 >--- a/sys/kern/sysv_shm.c >+++ b/sys/kern/sysv_shm.c >@@ -149,7 +149,7 @@ static int shm_prison_check(void *, void *); > static int shm_prison_set(void *, void *); > static int shm_prison_get(void *, void *); > static int shm_prison_remove(void *, void *); >-static void shm_prison_cleanup(struct prison *); >+static void shm_prison_doremove(struct prison *); > > /* > * Tuneable values. >@@ -1158,7 +1158,7 @@ shm_prison_set(void *obj, void *data) > prison_unlock(pr); > if (orpr != NULL) { > if (orpr == pr) >- shm_prison_cleanup(pr); >+ shm_prison_doremove(pr); > /* Disable all child jails as well. */ > FOREACH_PRISON_DESCENDANT(pr, tpr, descend) { > prison_lock(tpr); >@@ -1167,7 +1167,7 @@ shm_prison_set(void *obj, void *data) > osd_jail_del(tpr, shm_prison_slot); > prison_unlock(tpr); > if (trpr == tpr) >- shm_prison_cleanup(tpr); >+ shm_prison_doremove(tpr); > } else { > prison_unlock(tpr); > descend = 0; >@@ -1193,7 +1193,7 @@ shm_prison_set(void *obj, void *data) > prison_unlock(pr); > if (orpr != nrpr) { > if (orpr == pr) >- shm_prison_cleanup(pr); >+ shm_prison_doremove(pr); > if (orpr != NULL) { > /* Change child jails matching the old root, */ > FOREACH_PRISON_DESCENDANT(pr, tpr, descend) { >@@ -1205,7 +1205,7 @@ shm_prison_set(void *obj, void *data) > shm_prison_slot, nrpr); > prison_unlock(tpr); > if (trpr == tpr) >- shm_prison_cleanup(tpr); >+ shm_prison_doremove(tpr); > } else { > prison_unlock(tpr); > descend = 0; >@@ -1249,13 +1249,13 @@ shm_prison_remove(void *obj, void *data __unused) > rpr = osd_jail_get(pr, shm_prison_slot); > prison_unlock(pr); > if (rpr == pr) >- shm_prison_cleanup(pr); >+ shm_prison_doremove(pr); > SYSVSHM_UNLOCK(); > return (0); > } > > static void >-shm_prison_cleanup(struct prison *pr) >+shm_prison_doremove(struct prison *pr) > { > struct shmid_kernel *shmseg; > int i; >diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c >index 9f556efde3f1..d30707a88ebe 100644 >--- a/sys/kern/uipc_shm.c >+++ b/sys/kern/uipc_shm.c >@@ -125,6 +125,7 @@ static void shm_init(void *arg); > static void shm_insert(char *path, Fnv32_t fnv, struct shmfd *shmfd); > static struct shmfd *shm_lookup(char *path, Fnv32_t fnv); > static int shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred); >+static void shm_doremove(struct shm_mapping *map); > static int shm_dotruncate_cookie(struct shmfd *shmfd, off_t length, > void *rl_cookie); > static int shm_dotruncate_locked(struct shmfd *shmfd, off_t length, >@@ -982,6 +983,26 @@ shm_init(void *arg) > } > SYSINIT(shm_init, SI_SUB_SYSV_SHM, SI_ORDER_ANY, shm_init, NULL); > >+/* >+ * Remove shared memory objects that belong to a dying prison. >+ */ >+void >+shm_prison_cleanup(struct prison *pr) >+{ >+ struct shm_mapping *shmm, *tshmm; >+ u_long i; >+ >+ sx_xlock(&shm_dict_lock); >+ for (i = 0; i < shm_hash + 1; i++) { >+ LIST_FOREACH_SAFE(shmm, &shm_dictionary[i], sm_link, tshmm) { >+ if (shmm->sm_shmfd->shm_object->cred && >+ shmm->sm_shmfd->shm_object->cred->cr_prison == pr) >+ shm_doremove(shmm); >+ } >+ } >+ sx_xunlock(&shm_dict_lock); >+} >+ > /* > * Dictionary management. We maintain an in-kernel dictionary to map > * paths to shmfd objects. We use the FNV hash on the path to store >@@ -1034,11 +1055,7 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred) > FREAD | FWRITE); > if (error) > return (error); >- map->sm_shmfd->shm_path = NULL; >- LIST_REMOVE(map, sm_link); >- shm_drop(map->sm_shmfd); >- free(map->sm_path, M_SHMFD); >- free(map, M_SHMFD); >+ shm_doremove(map); > return (0); > } > } >@@ -1046,6 +1063,16 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred) > return (ENOENT); > } > >+static void >+shm_doremove(struct shm_mapping *map) >+{ >+ map->sm_shmfd->shm_path = NULL; >+ LIST_REMOVE(map, sm_link); >+ shm_drop(map->sm_shmfd); >+ free(map->sm_path, M_SHMFD); >+ free(map, M_SHMFD); >+} >+ > int > kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, > int shmflags, struct filecaps *fcaps, const char *name __unused) >diff --git a/sys/sys/mman.h b/sys/sys/mman.h >index a07b3550d51a..ea74c2a75183 100644 >--- a/sys/sys/mman.h >+++ b/sys/sys/mman.h >@@ -300,6 +300,8 @@ struct shmfd { > #endif > > #ifdef _KERNEL >+struct prison; >+ > int shm_map(struct file *fp, size_t size, off_t offset, void **memp); > int shm_unmap(struct file *fp, void *mem, size_t size); > >@@ -309,6 +311,7 @@ struct shmfd *shm_hold(struct shmfd *shmfd); > void shm_drop(struct shmfd *shmfd); > int shm_dotruncate(struct shmfd *shmfd, off_t length); > bool shm_largepage(struct shmfd *shmfd); >+void shm_prison_cleanup(struct prison *pr); > > extern struct fileops shm_ops; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 257555
: 234850