Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/kern_jail.c
Show First 20 Lines • Show All 1,772 Lines • ▼ Show 20 Lines | if (pr_flags & PR_PERSIST) { | ||||
pr->pr_ref--; | pr->pr_ref--; | ||||
pr->pr_uref--; | pr->pr_uref--; | ||||
} | } | ||||
} | } | ||||
pr->pr_flags = (pr->pr_flags & ~ch_flags) | pr_flags; | pr->pr_flags = (pr->pr_flags & ~ch_flags) | pr_flags; | ||||
mtx_unlock(&pr->pr_mtx); | mtx_unlock(&pr->pr_mtx); | ||||
#ifdef RACCT | #ifdef RACCT | ||||
if (created) | if (racct_enable && created) | ||||
prison_racct_attach(pr); | prison_racct_attach(pr); | ||||
#endif | #endif | ||||
/* Locks may have prevented a complete restriction of child IP | /* Locks may have prevented a complete restriction of child IP | ||||
* addresses. If so, allocate some more memory and try again. | * addresses. If so, allocate some more memory and try again. | ||||
*/ | */ | ||||
#ifdef INET | #ifdef INET | ||||
while (redo_ip4) { | while (redo_ip4) { | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | if (error) { | ||||
vfs_opterror(opts, "attach failed"); | vfs_opterror(opts, "attach failed"); | ||||
if (!created) | if (!created) | ||||
prison_deref(pr, PD_DEREF); | prison_deref(pr, PD_DEREF); | ||||
goto done_errmsg; | goto done_errmsg; | ||||
} | } | ||||
} | } | ||||
#ifdef RACCT | #ifdef RACCT | ||||
if (!created) { | if (racct_enable && !created) { | ||||
if (!(flags & JAIL_ATTACH)) | if (!(flags & JAIL_ATTACH)) | ||||
sx_sunlock(&allprison_lock); | sx_sunlock(&allprison_lock); | ||||
prison_racct_modify(pr); | prison_racct_modify(pr); | ||||
if (!(flags & JAIL_ATTACH)) | if (!(flags & JAIL_ATTACH)) | ||||
sx_slock(&allprison_lock); | sx_slock(&allprison_lock); | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 773 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
free(pr->pr_ip6, M_PRISON); | free(pr->pr_ip6, M_PRISON); | ||||
#endif | #endif | ||||
if (pr->pr_cpuset != NULL) | if (pr->pr_cpuset != NULL) | ||||
cpuset_rel(pr->pr_cpuset); | cpuset_rel(pr->pr_cpuset); | ||||
osd_jail_exit(pr); | osd_jail_exit(pr); | ||||
#ifdef RACCT | #ifdef RACCT | ||||
if (racct_enable) | |||||
prison_racct_detach(pr); | prison_racct_detach(pr); | ||||
#endif | #endif | ||||
free(pr, M_PRISON); | free(pr, M_PRISON); | ||||
/* Removing a prison frees a reference on its parent. */ | /* Removing a prison frees a reference on its parent. */ | ||||
pr = ppr; | pr = ppr; | ||||
mtx_lock(&pr->pr_mtx); | mtx_lock(&pr->pr_mtx); | ||||
flags = PD_DEREF | PD_DEUREF; | flags = PD_DEREF | PD_DEUREF; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,791 Lines • ▼ Show 20 Lines | SYSCTL_JAIL_PARAM(_allow_mount, nullfs, CTLTYPE_INT | CTLFLAG_RW, | ||||
"B", "Jail may mount the nullfs file system"); | "B", "Jail may mount the nullfs file system"); | ||||
SYSCTL_JAIL_PARAM(_allow_mount, procfs, CTLTYPE_INT | CTLFLAG_RW, | SYSCTL_JAIL_PARAM(_allow_mount, procfs, CTLTYPE_INT | CTLFLAG_RW, | ||||
"B", "Jail may mount the procfs file system"); | "B", "Jail may mount the procfs file system"); | ||||
SYSCTL_JAIL_PARAM(_allow_mount, tmpfs, CTLTYPE_INT | CTLFLAG_RW, | SYSCTL_JAIL_PARAM(_allow_mount, tmpfs, CTLTYPE_INT | CTLFLAG_RW, | ||||
"B", "Jail may mount the tmpfs file system"); | "B", "Jail may mount the tmpfs file system"); | ||||
SYSCTL_JAIL_PARAM(_allow_mount, zfs, CTLTYPE_INT | CTLFLAG_RW, | SYSCTL_JAIL_PARAM(_allow_mount, zfs, CTLTYPE_INT | CTLFLAG_RW, | ||||
"B", "Jail may mount the zfs file system"); | "B", "Jail may mount the zfs file system"); | ||||
#ifdef RACCT | |||||
void | void | ||||
prison_racct_foreach(void (*callback)(struct racct *racct, | prison_racct_foreach(void (*callback)(struct racct *racct, | ||||
void *arg2, void *arg3), void *arg2, void *arg3) | void *arg2, void *arg3), void *arg2, void *arg3) | ||||
{ | { | ||||
struct prison_racct *prr; | struct prison_racct *prr; | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_slock(&allprison_lock); | sx_slock(&allprison_lock); | ||||
LIST_FOREACH(prr, &allprison_racct, prr_next) | LIST_FOREACH(prr, &allprison_racct, prr_next) | ||||
(callback)(prr->prr_racct, arg2, arg3); | (callback)(prr->prr_racct, arg2, arg3); | ||||
sx_sunlock(&allprison_lock); | sx_sunlock(&allprison_lock); | ||||
} | } | ||||
static struct prison_racct * | static struct prison_racct * | ||||
prison_racct_find_locked(const char *name) | prison_racct_find_locked(const char *name) | ||||
{ | { | ||||
struct prison_racct *prr; | struct prison_racct *prr; | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_assert(&allprison_lock, SA_XLOCKED); | sx_assert(&allprison_lock, SA_XLOCKED); | ||||
if (name[0] == '\0' || strlen(name) >= MAXHOSTNAMELEN) | if (name[0] == '\0' || strlen(name) >= MAXHOSTNAMELEN) | ||||
return (NULL); | return (NULL); | ||||
LIST_FOREACH(prr, &allprison_racct, prr_next) { | LIST_FOREACH(prr, &allprison_racct, prr_next) { | ||||
if (strcmp(name, prr->prr_name) != 0) | if (strcmp(name, prr->prr_name) != 0) | ||||
continue; | continue; | ||||
Show All 14 Lines | prison_racct_find_locked(const char *name) | ||||
return (prr); | return (prr); | ||||
} | } | ||||
struct prison_racct * | struct prison_racct * | ||||
prison_racct_find(const char *name) | prison_racct_find(const char *name) | ||||
{ | { | ||||
struct prison_racct *prr; | struct prison_racct *prr; | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_xlock(&allprison_lock); | sx_xlock(&allprison_lock); | ||||
prr = prison_racct_find_locked(name); | prr = prison_racct_find_locked(name); | ||||
sx_xunlock(&allprison_lock); | sx_xunlock(&allprison_lock); | ||||
return (prr); | return (prr); | ||||
} | } | ||||
void | void | ||||
prison_racct_hold(struct prison_racct *prr) | prison_racct_hold(struct prison_racct *prr) | ||||
{ | { | ||||
ASSERT_RACCT_ENABLED(); | |||||
refcount_acquire(&prr->prr_refcount); | refcount_acquire(&prr->prr_refcount); | ||||
} | } | ||||
static void | static void | ||||
prison_racct_free_locked(struct prison_racct *prr) | prison_racct_free_locked(struct prison_racct *prr) | ||||
{ | { | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_assert(&allprison_lock, SA_XLOCKED); | sx_assert(&allprison_lock, SA_XLOCKED); | ||||
if (refcount_release(&prr->prr_refcount)) { | if (refcount_release(&prr->prr_refcount)) { | ||||
racct_destroy(&prr->prr_racct); | racct_destroy(&prr->prr_racct); | ||||
LIST_REMOVE(prr, prr_next); | LIST_REMOVE(prr, prr_next); | ||||
free(prr, M_PRISON_RACCT); | free(prr, M_PRISON_RACCT); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
prison_racct_free(struct prison_racct *prr) | prison_racct_free(struct prison_racct *prr) | ||||
{ | { | ||||
int old; | int old; | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_assert(&allprison_lock, SA_UNLOCKED); | sx_assert(&allprison_lock, SA_UNLOCKED); | ||||
old = prr->prr_refcount; | old = prr->prr_refcount; | ||||
if (old > 1 && atomic_cmpset_int(&prr->prr_refcount, old, old - 1)) | if (old > 1 && atomic_cmpset_int(&prr->prr_refcount, old, old - 1)) | ||||
return; | return; | ||||
sx_xlock(&allprison_lock); | sx_xlock(&allprison_lock); | ||||
prison_racct_free_locked(prr); | prison_racct_free_locked(prr); | ||||
sx_xunlock(&allprison_lock); | sx_xunlock(&allprison_lock); | ||||
} | } | ||||
#ifdef RACCT | |||||
static void | static void | ||||
prison_racct_attach(struct prison *pr) | prison_racct_attach(struct prison *pr) | ||||
{ | { | ||||
struct prison_racct *prr; | struct prison_racct *prr; | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_assert(&allprison_lock, SA_XLOCKED); | sx_assert(&allprison_lock, SA_XLOCKED); | ||||
prr = prison_racct_find_locked(pr->pr_name); | prr = prison_racct_find_locked(pr->pr_name); | ||||
KASSERT(prr != NULL, ("cannot find prison_racct")); | KASSERT(prr != NULL, ("cannot find prison_racct")); | ||||
pr->pr_prison_racct = prr; | pr->pr_prison_racct = prr; | ||||
} | } | ||||
/* | /* | ||||
* Handle jail renaming. From the racct point of view, renaming means | * Handle jail renaming. From the racct point of view, renaming means | ||||
* moving from one prison_racct to another. | * moving from one prison_racct to another. | ||||
*/ | */ | ||||
static void | static void | ||||
prison_racct_modify(struct prison *pr) | prison_racct_modify(struct prison *pr) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
struct ucred *cred; | struct ucred *cred; | ||||
struct prison_racct *oldprr; | struct prison_racct *oldprr; | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_slock(&allproc_lock); | sx_slock(&allproc_lock); | ||||
sx_xlock(&allprison_lock); | sx_xlock(&allprison_lock); | ||||
if (strcmp(pr->pr_name, pr->pr_prison_racct->prr_name) == 0) { | if (strcmp(pr->pr_name, pr->pr_prison_racct->prr_name) == 0) { | ||||
sx_xunlock(&allprison_lock); | sx_xunlock(&allprison_lock); | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&allproc_lock); | ||||
return; | return; | ||||
} | } | ||||
Show All 23 Lines | prison_racct_modify(struct prison *pr) | ||||
prison_racct_free_locked(oldprr); | prison_racct_free_locked(oldprr); | ||||
sx_xunlock(&allprison_lock); | sx_xunlock(&allprison_lock); | ||||
} | } | ||||
static void | static void | ||||
prison_racct_detach(struct prison *pr) | prison_racct_detach(struct prison *pr) | ||||
{ | { | ||||
ASSERT_RACCT_ENABLED(); | |||||
sx_assert(&allprison_lock, SA_UNLOCKED); | sx_assert(&allprison_lock, SA_UNLOCKED); | ||||
if (pr->pr_prison_racct == NULL) | if (pr->pr_prison_racct == NULL) | ||||
return; | return; | ||||
prison_racct_free(pr->pr_prison_racct); | prison_racct_free(pr->pr_prison_racct); | ||||
pr->pr_prison_racct = NULL; | pr->pr_prison_racct = NULL; | ||||
} | } | ||||
#endif /* RACCT */ | #endif /* RACCT */ | ||||
▲ Show 20 Lines • Show All 116 Lines • Show Last 20 Lines |