Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160295619
D57674.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D57674.diff
View Options
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -157,7 +157,7 @@
static int get_next_prid(struct prison **insprp);
static int get_next_deadid(struct prison **insprp);
-static int do_jail_attach(struct thread *td, struct prison *pr, int drflags);
+static int do_jail_attach(struct thread *td, struct prison *pr, int *drflagsp);
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);
@@ -2300,7 +2300,10 @@
pr->pr_state = PRISON_STATE_ALIVE;
}
- /* Attach this process to the prison if requested. */
+ /*
+ * Attach this process to the prison if requested. This will
+ * unlock allprison_lock, meaning changes are now user-visible.
+ */
if (flags & JAIL_ATTACH) {
#ifdef MAC
error = mac_prison_check_attach(td->td_ucred, pr);
@@ -2310,9 +2313,7 @@
goto done_deref;
}
#endif
- error = do_jail_attach(td, pr,
- prison_lock_xlock(pr, drflags & PD_LOCK_FLAGS));
- drflags &= ~(PD_LOCKED | PD_LIST_XLOCKED);
+ error = do_jail_attach(td, pr, &drflags);
if (error) {
vfs_opterror(opts, "attach failed");
goto done_deref;
@@ -3055,37 +3056,37 @@
sys_jail_attach(struct thread *td, struct jail_attach_args *uap)
{
struct prison *pr;
- int error;
+ int drflags, error;
error = priv_check(td, PRIV_JAIL_ATTACH);
if (error)
return (error);
sx_slock(&allprison_lock);
+ drflags = PD_LIST_SLOCKED;
pr = prison_find_child(td->td_ucred->cr_prison, uap->jid);
if (pr == NULL) {
- sx_sunlock(&allprison_lock);
- return (EINVAL);
+ error = EINVAL;
+ goto done;
}
+ drflags |= PD_LOCKED;
#ifdef MAC
error = mac_prison_check_attach(td->td_ucred, pr);
if (error != 0)
- goto unlock;
+ goto done;
#endif
/* Do not allow a process to attach to a prison that is not alive. */
if (!prison_isalive(pr)) {
error = EINVAL;
- goto unlock;
+ goto done;
}
- return (do_jail_attach(td, pr, PD_LOCKED | PD_LIST_SLOCKED));
+ error = do_jail_attach(td, pr, &drflags);
-unlock:
-
- mtx_unlock(&pr->pr_mtx);
- sx_sunlock(&allprison_lock);
+ done:
+ prison_deref(pr, drflags);
return (error);
}
@@ -3103,9 +3104,10 @@
sx_slock(&allprison_lock);
drflags = PD_LIST_SLOCKED;
+ pr = NULL;
error = jaildesc_find(td, uap->fd, &pr, &jdcred);
if (error)
- goto fail;
+ goto done;
drflags |= PD_DEREF;
error = priv_check_cred(jdcred, PRIV_JAIL_ATTACH);
#ifdef MAC
@@ -3114,33 +3116,35 @@
#endif
crfree(jdcred);
if (error)
- goto fail;
- mtx_lock(&pr->pr_mtx);
- drflags |= PD_LOCKED;
+ goto done;
/* Do not allow a process to attach to a prison that is not alive. */
if (!prison_isalive(pr)) {
error = EINVAL;
- goto fail;
+ goto done;
}
- return (do_jail_attach(td, pr, drflags));
+ error = do_jail_attach(td, pr, &drflags);
- fail:
+ done:
prison_deref(pr, drflags);
return (error);
}
+/*
+ * Attach the current process to a prison. On entry, the allprison
+ * lock should be at least shared. On exit, both it and the prison
+ * itself will be unlocked, which will be refelected in *drflagsp.
+ */
static int
-do_jail_attach(struct thread *td, struct prison *pr, int drflags)
+do_jail_attach(struct thread *td, struct prison *pr, int *drflagsp)
{
struct proc *p;
struct ucred *newcred, *oldcred;
- int error;
+ int drflags, error;
- mtx_assert(&pr->pr_mtx, MA_OWNED);
sx_assert(&allprison_lock, SX_LOCKED);
- drflags &= PD_LOCK_FLAGS;
+ KASSERT(prison_isvalid(pr), ("Attaching to invalid prison %p", pr));
/*
* XXX: Note that there is a slight race here if two threads
* in the same privileged process attempt to attach to two
@@ -3149,16 +3153,22 @@
* a process root from one prison, but attached to the jail
* of another.
*/
- if (!(drflags & PD_DEREF)) {
- prison_hold(pr);
- drflags |= PD_DEREF;
- }
- refcount_acquire(&pr->pr_uref);
- drflags |= PD_DEUREF;
- mtx_unlock(&pr->pr_mtx);
- drflags &= ~PD_LOCKED;
+
+ /*
+ * Note the caller's locking state, but gain and track our own
+ * references. The caller will see that locks have been
+ * dropped (which isn't true now, but will be after OSD calls).
+ */
+ prison_hold(pr);
+ prison_proc_hold(pr);
+ drflags = PD_DEREF | PD_DEUREF | (*drflagsp & PD_LOCK_FLAGS);
+ *drflagsp &= PD_OP_FLAGS;
/* Let modules do whatever they need to prepare for attaching. */
+ if (drflags & PD_LOCKED) {
+ mtx_unlock(&pr->pr_mtx);
+ drflags &= ~PD_LOCKED;
+ }
error = osd_jail_call(pr, PR_METHOD_ATTACH, td);
if (error)
goto e_revert_osd;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jun 24, 12:44 AM (13 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34160261
Default Alt Text
D57674.diff (4 KB)
Attached To
Mode
D57674: Clean up locking around do_jail_attach, fixing zombie jails from jail_attach_jd
Attached
Detach File
Event Timeline
Log In to Comment