jail: Don't allow jail_set(2) to resurrect dying jails.
Currently, a prison in "dying" state (removed but still holding resources) can be brought back to alive state via "jail -d", or the JAIL_DYING flag to jail_set(2). This seemed like a good idea at the time. Its main use was to improve support for specifying the jid when creating a jail, which also seemed like a good idea at the time. But resurrecting a jail that was partway through thr process of shutting down is trouble waiting to happen. This patch deprecates that flag, leaving it as a no-op for creating jails (but still useful for looking at dying jails). It sill allows creating a new jail with the same jid as a dying one, but will renumber the old one in that case. That's imperfect, but allows for current behavior. Reviewed by: bz Differential Revision: https://reviews.freebsd.org/D28150
This commit is contained in:
parent
376330aca1
commit
ed31b3f4a1
|
@ -23,7 +23,7 @@
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd February 19, 2021
|
.Dd November 29, 2023
|
||||||
.Dt JAIL 2
|
.Dt JAIL 2
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -185,7 +185,9 @@ it, as with the
|
||||||
.Fn jail_attach
|
.Fn jail_attach
|
||||||
system call.
|
system call.
|
||||||
.It Dv JAIL_DYING
|
.It Dv JAIL_DYING
|
||||||
Allow setting a jail that is in the process of being removed.
|
This is deprecated in
|
||||||
|
.Fn jail_set
|
||||||
|
and has no effect.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
|
|
|
@ -136,8 +136,10 @@ SX_SYSINIT(allprison_lock, &allprison_lock, "allprison");
|
||||||
struct prisonlist allprison = TAILQ_HEAD_INITIALIZER(allprison);
|
struct prisonlist allprison = TAILQ_HEAD_INITIALIZER(allprison);
|
||||||
LIST_HEAD(, prison_racct) allprison_racct;
|
LIST_HEAD(, prison_racct) allprison_racct;
|
||||||
int lastprid = 0;
|
int lastprid = 0;
|
||||||
|
int lastdeadid = 0;
|
||||||
|
|
||||||
static int get_next_prid(struct prison **insprp);
|
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 drflags);
|
||||||
static void prison_complete(void *context, int pending);
|
static void prison_complete(void *context, int pending);
|
||||||
static void prison_deref(struct prison *pr, int flags);
|
static void prison_deref(struct prison *pr, int flags);
|
||||||
|
@ -977,7 +979,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
#endif
|
#endif
|
||||||
struct vfsopt *opt;
|
struct vfsopt *opt;
|
||||||
struct vfsoptlist *opts;
|
struct vfsoptlist *opts;
|
||||||
struct prison *pr, *deadpr, *inspr, *mypr, *ppr, *tpr;
|
struct prison *pr, *deadpr, *dinspr, *inspr, *mypr, *ppr, *tpr;
|
||||||
struct vnode *root;
|
struct vnode *root;
|
||||||
char *domain, *errmsg, *host, *name, *namelc, *p, *path, *uuid;
|
char *domain, *errmsg, *host, *name, *namelc, *p, *path, *uuid;
|
||||||
char *g_path, *osrelstr;
|
char *g_path, *osrelstr;
|
||||||
|
@ -988,10 +990,10 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
#endif
|
#endif
|
||||||
unsigned long hid;
|
unsigned long hid;
|
||||||
size_t namelen, onamelen, pnamelen;
|
size_t namelen, onamelen, pnamelen;
|
||||||
int born, created, cuflags, descend, drflags, enforce;
|
int created, cuflags, descend, drflags, enforce;
|
||||||
int error, errmsg_len, errmsg_pos;
|
int error, errmsg_len, errmsg_pos;
|
||||||
int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
|
int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
|
||||||
int jid, jsys, len, level;
|
int deadid, jid, jsys, len, level;
|
||||||
int childmax, osreldt, rsnum, slevel;
|
int childmax, osreldt, rsnum, slevel;
|
||||||
#ifdef INET
|
#ifdef INET
|
||||||
int ip4s;
|
int ip4s;
|
||||||
|
@ -1404,6 +1406,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
*/
|
*/
|
||||||
pr = NULL;
|
pr = NULL;
|
||||||
inspr = NULL;
|
inspr = NULL;
|
||||||
|
deadpr = NULL;
|
||||||
if (cuflags == JAIL_CREATE && jid == 0 && name != NULL) {
|
if (cuflags == JAIL_CREATE && jid == 0 && name != NULL) {
|
||||||
namelc = strrchr(name, '.');
|
namelc = strrchr(name, '.');
|
||||||
jid = strtoul(namelc != NULL ? namelc + 1 : name, &p, 10);
|
jid = strtoul(namelc != NULL ? namelc + 1 : name, &p, 10);
|
||||||
|
@ -1433,69 +1436,38 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
continue;
|
continue;
|
||||||
if (inspr->pr_id > jid)
|
if (inspr->pr_id > jid)
|
||||||
break;
|
break;
|
||||||
pr = inspr;
|
if (prison_isalive(inspr)) {
|
||||||
mtx_lock(&pr->pr_mtx);
|
pr = inspr;
|
||||||
drflags |= PD_LOCKED;
|
mtx_lock(&pr->pr_mtx);
|
||||||
|
drflags |= PD_LOCKED;
|
||||||
|
} else {
|
||||||
|
/* Note a dying jail to handle later. */
|
||||||
|
deadpr = inspr;
|
||||||
|
}
|
||||||
inspr = NULL;
|
inspr = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pr != NULL) {
|
if (cuflags == JAIL_CREATE && pr != NULL) {
|
||||||
/* Create: jid must not exist. */
|
/*
|
||||||
if (cuflags == JAIL_CREATE) {
|
* Even creators that cannot see the jail will
|
||||||
/*
|
* get EEXIST.
|
||||||
* Even creators that cannot see the jail will
|
*/
|
||||||
* get EEXIST.
|
error = EEXIST;
|
||||||
*/
|
vfs_opterror(opts, "jail %d already exists", jid);
|
||||||
error = EEXIST;
|
goto done_deref;
|
||||||
vfs_opterror(opts, "jail %d already exists",
|
}
|
||||||
jid);
|
if ((pr == NULL)
|
||||||
goto done_deref;
|
? cuflags == JAIL_UPDATE
|
||||||
}
|
: !prison_ischild(mypr, pr)) {
|
||||||
if (!prison_ischild(mypr, pr)) {
|
/*
|
||||||
/*
|
* Updaters get ENOENT for nonexistent jails,
|
||||||
* Updaters get ENOENT if they cannot see the
|
* or for jails they cannot see. The latter
|
||||||
* jail. This is true even for CREATE | UPDATE,
|
* case is true even for CREATE | UPDATE,
|
||||||
* which normally cannot give this error.
|
* which normally cannot give this error.
|
||||||
*/
|
*/
|
||||||
error = ENOENT;
|
error = ENOENT;
|
||||||
vfs_opterror(opts, "jail %d not found", jid);
|
vfs_opterror(opts, "jail %d not found", jid);
|
||||||
goto done_deref;
|
goto done_deref;
|
||||||
}
|
|
||||||
ppr = pr->pr_parent;
|
|
||||||
if (!prison_isalive(ppr)) {
|
|
||||||
error = ENOENT;
|
|
||||||
vfs_opterror(opts, "jail %d is dying",
|
|
||||||
ppr->pr_id);
|
|
||||||
goto done_deref;
|
|
||||||
}
|
|
||||||
if (!prison_isalive(pr)) {
|
|
||||||
if (!(flags & JAIL_DYING)) {
|
|
||||||
error = ENOENT;
|
|
||||||
vfs_opterror(opts, "jail %d is dying",
|
|
||||||
jid);
|
|
||||||
goto done_deref;
|
|
||||||
}
|
|
||||||
if ((flags & JAIL_ATTACH) ||
|
|
||||||
(pr_flags & PR_PERSIST)) {
|
|
||||||
/*
|
|
||||||
* A dying jail might be resurrected
|
|
||||||
* (via attach or persist), but first
|
|
||||||
* it must determine if another jail
|
|
||||||
* has claimed its name. Accomplish
|
|
||||||
* this by implicitly re-setting the
|
|
||||||
* name.
|
|
||||||
*/
|
|
||||||
if (name == NULL)
|
|
||||||
name = prison_name(mypr, pr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Update: jid must exist. */
|
|
||||||
if (cuflags == JAIL_UPDATE) {
|
|
||||||
error = ENOENT;
|
|
||||||
vfs_opterror(opts, "jail %d not found", jid);
|
|
||||||
goto done_deref;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1547,54 +1519,35 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
if (namelc[0] != '\0') {
|
if (namelc[0] != '\0') {
|
||||||
pnamelen =
|
pnamelen =
|
||||||
(ppr == &prison0) ? 0 : strlen(ppr->pr_name) + 1;
|
(ppr == &prison0) ? 0 : strlen(ppr->pr_name) + 1;
|
||||||
deadpr = NULL;
|
|
||||||
FOREACH_PRISON_CHILD(ppr, tpr) {
|
FOREACH_PRISON_CHILD(ppr, tpr) {
|
||||||
if (tpr != pr &&
|
if (tpr == pr || !prison_isalive(tpr) ||
|
||||||
!strcmp(tpr->pr_name + pnamelen, namelc)) {
|
strcmp(tpr->pr_name + pnamelen, namelc))
|
||||||
if (prison_isalive(tpr)) {
|
continue;
|
||||||
if (pr == NULL &&
|
if (cuflags == JAIL_CREATE || pr != NULL) {
|
||||||
cuflags != JAIL_CREATE) {
|
/*
|
||||||
/*
|
* Create, or update(jid): name must
|
||||||
* Use this jail
|
* not exist in an active sibling jail.
|
||||||
* for updates.
|
*/
|
||||||
*/
|
error = EEXIST;
|
||||||
pr = tpr;
|
|
||||||
mtx_lock(&pr->pr_mtx);
|
|
||||||
drflags |= PD_LOCKED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Create, or update(jid):
|
|
||||||
* name must not exist in an
|
|
||||||
* active sibling jail.
|
|
||||||
*/
|
|
||||||
error = EEXIST;
|
|
||||||
vfs_opterror(opts,
|
|
||||||
"jail \"%s\" already exists",
|
|
||||||
name);
|
|
||||||
goto done_deref;
|
|
||||||
}
|
|
||||||
if (pr == NULL &&
|
|
||||||
cuflags != JAIL_CREATE) {
|
|
||||||
deadpr = tpr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If no active jail is found, use a dying one. */
|
|
||||||
if (deadpr != NULL && pr == NULL) {
|
|
||||||
if (flags & JAIL_DYING) {
|
|
||||||
pr = deadpr;
|
|
||||||
mtx_lock(&pr->pr_mtx);
|
|
||||||
drflags |= PD_LOCKED;
|
|
||||||
} else if (cuflags == JAIL_UPDATE) {
|
|
||||||
error = ENOENT;
|
|
||||||
vfs_opterror(opts,
|
vfs_opterror(opts,
|
||||||
"jail \"%s\" is dying", name);
|
"jail \"%s\" already exists", name);
|
||||||
goto done_deref;
|
goto done_deref;
|
||||||
}
|
}
|
||||||
|
/* Use this jail for updates. */
|
||||||
|
pr = tpr;
|
||||||
|
mtx_lock(&pr->pr_mtx);
|
||||||
|
drflags |= PD_LOCKED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* Update: name must exist if no jid. */
|
/*
|
||||||
else if (cuflags == JAIL_UPDATE && pr == NULL) {
|
* Update: name must exist if no jid is specified.
|
||||||
|
* As with the jid case, the jail must be currently
|
||||||
|
* visible, or else even CREATE | UPDATE will get
|
||||||
|
* an error.
|
||||||
|
*/
|
||||||
|
if ((pr == NULL)
|
||||||
|
? cuflags == JAIL_UPDATE
|
||||||
|
: !prison_isalive(pr)) {
|
||||||
error = ENOENT;
|
error = ENOENT;
|
||||||
vfs_opterror(opts, "jail \"%s\" not found",
|
vfs_opterror(opts, "jail \"%s\" not found",
|
||||||
name);
|
name);
|
||||||
|
@ -1618,6 +1571,36 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
vfs_opterror(opts, "prison limit exceeded");
|
vfs_opterror(opts, "prison limit exceeded");
|
||||||
goto done_deref;
|
goto done_deref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deadpr != NULL) {
|
||||||
|
/*
|
||||||
|
* The prison being created has the same ID as a dying
|
||||||
|
* one. Handle this by giving the dying jail a new ID.
|
||||||
|
* This may cause some confusion to user space, but
|
||||||
|
* only to those listing dying jails.
|
||||||
|
*/
|
||||||
|
deadid = get_next_deadid(&dinspr);
|
||||||
|
if (deadid == 0) {
|
||||||
|
error = EAGAIN;
|
||||||
|
vfs_opterror(opts, "no available jail IDs");
|
||||||
|
goto done_deref;
|
||||||
|
}
|
||||||
|
mtx_lock(&deadpr->pr_mtx);
|
||||||
|
deadpr->pr_id = deadid;
|
||||||
|
mtx_unlock(&deadpr->pr_mtx);
|
||||||
|
if (dinspr == deadpr)
|
||||||
|
inspr = deadpr;
|
||||||
|
else {
|
||||||
|
inspr = TAILQ_NEXT(deadpr, pr_list);
|
||||||
|
TAILQ_REMOVE(&allprison, deadpr, pr_list);
|
||||||
|
if (dinspr != NULL)
|
||||||
|
TAILQ_INSERT_AFTER(&allprison, dinspr,
|
||||||
|
deadpr, pr_list);
|
||||||
|
else
|
||||||
|
TAILQ_INSERT_HEAD(&allprison, deadpr,
|
||||||
|
pr_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (jid == 0 && (jid = get_next_prid(&inspr)) == 0) {
|
if (jid == 0 && (jid = get_next_prid(&inspr)) == 0) {
|
||||||
error = EAGAIN;
|
error = EAGAIN;
|
||||||
vfs_opterror(opts, "no available jail IDs");
|
vfs_opterror(opts, "no available jail IDs");
|
||||||
|
@ -2017,14 +2000,13 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
* Persistent prisons get an extra reference, and prisons losing their
|
* Persistent prisons get an extra reference, and prisons losing their
|
||||||
* persist flag lose that reference.
|
* persist flag lose that reference.
|
||||||
*/
|
*/
|
||||||
born = !prison_isalive(pr);
|
|
||||||
if (ch_flags & PR_PERSIST & (pr_flags ^ pr->pr_flags)) {
|
if (ch_flags & PR_PERSIST & (pr_flags ^ pr->pr_flags)) {
|
||||||
if (pr_flags & PR_PERSIST) {
|
if (pr_flags & PR_PERSIST) {
|
||||||
prison_hold(pr);
|
prison_hold(pr);
|
||||||
/*
|
/*
|
||||||
* This may make a dead prison alive again, but wait
|
* This may be a new prison's first user reference,
|
||||||
* to label it as such until after OSD calls have had
|
* but wait to call it alive until after OSD calls
|
||||||
* a chance to run (and perhaps to fail).
|
* have had a chance to run (and perhaps to fail).
|
||||||
*/
|
*/
|
||||||
refcount_acquire(&pr->pr_uref);
|
refcount_acquire(&pr->pr_uref);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2039,7 +2021,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
* Any errors past this point will need to de-persist newly created
|
* Any errors past this point will need to de-persist newly created
|
||||||
* prisons, as well as call remove methods.
|
* prisons, as well as call remove methods.
|
||||||
*/
|
*/
|
||||||
if (born)
|
if (created)
|
||||||
drflags |= PD_KILL;
|
drflags |= PD_KILL;
|
||||||
|
|
||||||
#ifdef RACCT
|
#ifdef RACCT
|
||||||
|
@ -2092,7 +2074,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Let the modules do their work. */
|
/* Let the modules do their work. */
|
||||||
if (born) {
|
if (created) {
|
||||||
error = osd_jail_call(pr, PR_METHOD_CREATE, opts);
|
error = osd_jail_call(pr, PR_METHOD_CREATE, opts);
|
||||||
if (error)
|
if (error)
|
||||||
goto done_deref;
|
goto done_deref;
|
||||||
|
@ -2105,7 +2087,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
* A new prison is now ready to be seen; either it has gained a user
|
* A new prison is now ready to be seen; either it has gained a user
|
||||||
* reference via persistence, or is about to gain one via attachment.
|
* reference via persistence, or is about to gain one via attachment.
|
||||||
*/
|
*/
|
||||||
if (born) {
|
if (created) {
|
||||||
drflags = prison_lock_xlock(pr, drflags);
|
drflags = prison_lock_xlock(pr, drflags);
|
||||||
pr->pr_state = PRISON_STATE_ALIVE;
|
pr->pr_state = PRISON_STATE_ALIVE;
|
||||||
}
|
}
|
||||||
|
@ -2135,7 +2117,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (born && pr != &prison0 && (pr->pr_allow & PR_ALLOW_NFSD) != 0 &&
|
if (created && pr != &prison0 && (pr->pr_allow & PR_ALLOW_NFSD) != 0 &&
|
||||||
(pr->pr_root->v_vflag & VV_ROOT) == 0)
|
(pr->pr_root->v_vflag & VV_ROOT) == 0)
|
||||||
printf("Warning jail jid=%d: mountd/nfsd requires a separate"
|
printf("Warning jail jid=%d: mountd/nfsd requires a separate"
|
||||||
" file system\n", pr->pr_id);
|
" file system\n", pr->pr_id);
|
||||||
|
@ -2242,6 +2224,55 @@ get_next_prid(struct prison **insprp)
|
||||||
return (jid);
|
return (jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the next available ID for a renumbered dead prison. This is the same
|
||||||
|
* as get_next_prid, but counting backward from the end of the range.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
get_next_deadid(struct prison **dinsprp)
|
||||||
|
{
|
||||||
|
struct prison *dinspr;
|
||||||
|
int deadid, minid;
|
||||||
|
|
||||||
|
deadid = lastdeadid ? lastdeadid - 1 : JAIL_MAX;
|
||||||
|
/*
|
||||||
|
* Take two reverse passes through the allprison list: first
|
||||||
|
* starting with the proposed deadid, then ending with it.
|
||||||
|
*/
|
||||||
|
for (minid = 1; minid != 0; ) {
|
||||||
|
TAILQ_FOREACH_REVERSE(dinspr, &allprison, prisonlist, pr_list) {
|
||||||
|
if (dinspr->pr_id > deadid)
|
||||||
|
continue;
|
||||||
|
if (dinspr->pr_id < deadid) {
|
||||||
|
/* Found an opening. */
|
||||||
|
minid = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (--deadid < minid) {
|
||||||
|
if (lastdeadid == minid || lastdeadid == 0)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The entire legal range
|
||||||
|
* has been traversed
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Try again from the end. */
|
||||||
|
deadid = JAIL_MAX;
|
||||||
|
minid = lastdeadid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dinspr == NULL) {
|
||||||
|
/* Found room at the beginning of the list. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dinsprp = dinspr;
|
||||||
|
lastdeadid = deadid;
|
||||||
|
return (deadid);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct jail_get_args {
|
* struct jail_get_args {
|
||||||
* struct iovec *iovp;
|
* struct iovec *iovp;
|
||||||
|
|
|
@ -99,7 +99,7 @@ enum prison_state {
|
||||||
#define JAIL_UPDATE 0x02 /* Update parameters of existing jail */
|
#define JAIL_UPDATE 0x02 /* Update parameters of existing jail */
|
||||||
#define JAIL_ATTACH 0x04 /* Attach to jail upon creation */
|
#define JAIL_ATTACH 0x04 /* Attach to jail upon creation */
|
||||||
#define JAIL_DYING 0x08 /* Allow getting a dying jail */
|
#define JAIL_DYING 0x08 /* Allow getting a dying jail */
|
||||||
#define JAIL_SET_MASK 0x0f
|
#define JAIL_SET_MASK 0x0f /* JAIL_DYING is deprecated/ignored here */
|
||||||
#define JAIL_GET_MASK 0x08
|
#define JAIL_GET_MASK 0x08
|
||||||
|
|
||||||
#define JAIL_SYS_DISABLE 0
|
#define JAIL_SYS_DISABLE 0
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
.\" SUCH DAMAGE.
|
.\" SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd September 1, 2023
|
.Dd November 29, 2023
|
||||||
.Dt JAIL 8
|
.Dt JAIL 8
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -144,10 +144,6 @@ jail if it does exist.
|
||||||
.Pp
|
.Pp
|
||||||
Other available options are:
|
Other available options are:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl d
|
|
||||||
Allow making changes to a dying jail, equivalent to the
|
|
||||||
.Va allow.dying
|
|
||||||
parameter.
|
|
||||||
.It Fl f Ar conf_file
|
.It Fl f Ar conf_file
|
||||||
Use configuration file
|
Use configuration file
|
||||||
.Ar conf_file
|
.Ar conf_file
|
||||||
|
@ -215,6 +211,17 @@ parameter.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Print a message on every operation, such as running commands and
|
Print a message on every operation, such as running commands and
|
||||||
mounting filesystems.
|
mounting filesystems.
|
||||||
|
.It Fl d
|
||||||
|
This is deprecated and is equivalent to the
|
||||||
|
.Va allow.dying
|
||||||
|
parameter, which is also deprecated.
|
||||||
|
It used to allow making changes to a
|
||||||
|
.Va dying
|
||||||
|
jail.
|
||||||
|
Now such jails are always replaced when a new jail is created with the same
|
||||||
|
.Va jid
|
||||||
|
or
|
||||||
|
.Va name .
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
If no arguments are given after the options, the operation (except
|
If no arguments are given after the options, the operation (except
|
||||||
|
@ -955,9 +962,14 @@ filesystem on the chrooted
|
||||||
.Pa /proc
|
.Pa /proc
|
||||||
directory.
|
directory.
|
||||||
.It Va allow.dying
|
.It Va allow.dying
|
||||||
Allow making changes to a
|
This is deprecated and has no effect.
|
||||||
|
It used to allow making changes to a
|
||||||
.Va dying
|
.Va dying
|
||||||
jail.
|
jail.
|
||||||
|
Now such jails are always replaced when a new jail is created with the same
|
||||||
|
.Va jid
|
||||||
|
or
|
||||||
|
.Va name .
|
||||||
.It Va depend
|
.It Va depend
|
||||||
Specify a jail (or jails) that this jail depends on.
|
Specify a jail (or jails) that this jail depends on.
|
||||||
When this jail is to be created, any jail(s) it depends on must already exist.
|
When this jail is to be created, any jail(s) it depends on must already exist.
|
||||||
|
|
|
@ -61,7 +61,7 @@ const char *separator = "\t";
|
||||||
static void clear_persist(struct cfjail *j);
|
static void clear_persist(struct cfjail *j);
|
||||||
static int update_jail(struct cfjail *j);
|
static int update_jail(struct cfjail *j);
|
||||||
static int rdtun_params(struct cfjail *j, int dofail);
|
static int rdtun_params(struct cfjail *j, int dofail);
|
||||||
static void running_jid(struct cfjail *j, int dflag);
|
static void running_jid(struct cfjail *j);
|
||||||
static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg,
|
static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg,
|
||||||
const char *noname_msg);
|
const char *noname_msg);
|
||||||
static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp,
|
static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp,
|
||||||
|
@ -137,7 +137,7 @@ main(int argc, char **argv)
|
||||||
const char *cfname;
|
const char *cfname;
|
||||||
size_t sysvallen;
|
size_t sysvallen;
|
||||||
unsigned op, pi;
|
unsigned op, pi;
|
||||||
int ch, docf, error, i, oldcl, sysval;
|
int ch, docf, dying_warned, error, i, oldcl, sysval;
|
||||||
int dflag, eflag, Rflag;
|
int dflag, eflag, Rflag;
|
||||||
#if defined(INET) || defined(INET6)
|
#if defined(INET) || defined(INET6)
|
||||||
char *cs, *ncs;
|
char *cs, *ncs;
|
||||||
|
@ -377,6 +377,7 @@ main(int argc, char **argv)
|
||||||
* operation on it. When that is done, the jail may be finished,
|
* operation on it. When that is done, the jail may be finished,
|
||||||
* or it may go back for the next step.
|
* or it may go back for the next step.
|
||||||
*/
|
*/
|
||||||
|
dying_warned = 0;
|
||||||
while ((j = next_jail()))
|
while ((j = next_jail()))
|
||||||
{
|
{
|
||||||
if (j->flags & JF_FAILED) {
|
if (j->flags & JF_FAILED) {
|
||||||
|
@ -397,11 +398,13 @@ main(int argc, char **argv)
|
||||||
import_params(j) < 0)
|
import_params(j) < 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (j->intparams[IP_ALLOW_DYING] && !dying_warned) {
|
||||||
|
warnx("%s", "the 'allow.dying' parameter and '-d' flag"
|
||||||
|
"are deprecated and have no effect.");
|
||||||
|
dying_warned = 1;
|
||||||
|
}
|
||||||
if (!j->jid)
|
if (!j->jid)
|
||||||
running_jid(j,
|
running_jid(j);
|
||||||
(j->flags & (JF_SET | JF_DEPEND)) == JF_SET
|
|
||||||
? dflag || bool_param(j->intparams[IP_ALLOW_DYING])
|
|
||||||
: 0);
|
|
||||||
if (finish_command(j))
|
if (finish_command(j))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -615,9 +618,9 @@ create_jail(struct cfjail *j)
|
||||||
{
|
{
|
||||||
struct iovec jiov[4];
|
struct iovec jiov[4];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct jailparam *jp, *setparams, *setparams2, *sjp;
|
struct jailparam *jp, *setparams, *sjp;
|
||||||
const char *path;
|
const char *path;
|
||||||
int dopersist, ns, jid, dying, didfail;
|
int dopersist, ns;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the jail's path, with a better error message than jail_set
|
* Check the jail's path, with a better error message than jail_set
|
||||||
|
@ -657,57 +660,8 @@ create_jail(struct cfjail *j)
|
||||||
*sjp++ = *jp;
|
*sjp++ = *jp;
|
||||||
ns = sjp - setparams;
|
ns = sjp - setparams;
|
||||||
|
|
||||||
didfail = 0;
|
|
||||||
j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE);
|
j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE);
|
||||||
if (j->jid < 0 && errno == EEXIST &&
|
if (j->jid < 0) {
|
||||||
bool_param(j->intparams[IP_ALLOW_DYING]) &&
|
|
||||||
int_param(j->intparams[KP_JID], &jid) && jid != 0) {
|
|
||||||
/*
|
|
||||||
* The jail already exists, but may be dying.
|
|
||||||
* Make sure it is, in which case an update is appropriate.
|
|
||||||
*/
|
|
||||||
jiov[0].iov_base = __DECONST(char *, "jid");
|
|
||||||
jiov[0].iov_len = sizeof("jid");
|
|
||||||
jiov[1].iov_base = &jid;
|
|
||||||
jiov[1].iov_len = sizeof(jid);
|
|
||||||
jiov[2].iov_base = __DECONST(char *, "dying");
|
|
||||||
jiov[2].iov_len = sizeof("dying");
|
|
||||||
jiov[3].iov_base = &dying;
|
|
||||||
jiov[3].iov_len = sizeof(dying);
|
|
||||||
if (jail_get(jiov, 4, JAIL_DYING) < 0) {
|
|
||||||
/*
|
|
||||||
* It could be that the jail just barely finished
|
|
||||||
* dying, or it could be that the jid never existed
|
|
||||||
* but the name does. In either case, another try
|
|
||||||
* at creating the jail should do the right thing.
|
|
||||||
*/
|
|
||||||
if (errno == ENOENT)
|
|
||||||
j->jid = jailparam_set_note(j, setparams, ns,
|
|
||||||
JAIL_CREATE);
|
|
||||||
} else if (dying) {
|
|
||||||
j->jid = jid;
|
|
||||||
if (rdtun_params(j, 1) < 0) {
|
|
||||||
j->jid = -1;
|
|
||||||
didfail = 1;
|
|
||||||
} else {
|
|
||||||
sjp = setparams2 = alloca((j->njp + dopersist) *
|
|
||||||
sizeof(struct jailparam));
|
|
||||||
for (jp = setparams; jp < setparams + ns; jp++)
|
|
||||||
if (!JP_RDTUN(jp) ||
|
|
||||||
!strcmp(jp->jp_name, "jid"))
|
|
||||||
*sjp++ = *jp;
|
|
||||||
j->jid = jailparam_set_note(j, setparams2,
|
|
||||||
sjp - setparams2, JAIL_UPDATE | JAIL_DYING);
|
|
||||||
/*
|
|
||||||
* Again, perhaps the jail just finished dying.
|
|
||||||
*/
|
|
||||||
if (j->jid < 0 && errno == ENOENT)
|
|
||||||
j->jid = jailparam_set_note(j,
|
|
||||||
setparams, ns, JAIL_CREATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (j->jid < 0 && !didfail) {
|
|
||||||
jail_warnx(j, "%s", jail_errmsg);
|
jail_warnx(j, "%s", jail_errmsg);
|
||||||
failed(j);
|
failed(j);
|
||||||
}
|
}
|
||||||
|
@ -772,9 +726,7 @@ update_jail(struct cfjail *j)
|
||||||
if (!JP_RDTUN(jp))
|
if (!JP_RDTUN(jp))
|
||||||
*++sjp = *jp;
|
*++sjp = *jp;
|
||||||
|
|
||||||
jid = jailparam_set_note(j, setparams, ns,
|
jid = jailparam_set_note(j, setparams, ns, JAIL_UPDATE);
|
||||||
bool_param(j->intparams[IP_ALLOW_DYING])
|
|
||||||
? JAIL_UPDATE | JAIL_DYING : JAIL_UPDATE);
|
|
||||||
if (jid < 0) {
|
if (jid < 0) {
|
||||||
jail_warnx(j, "%s", jail_errmsg);
|
jail_warnx(j, "%s", jail_errmsg);
|
||||||
failed(j);
|
failed(j);
|
||||||
|
@ -815,8 +767,7 @@ rdtun_params(struct cfjail *j, int dofail)
|
||||||
rtjp->jp_value = NULL;
|
rtjp->jp_value = NULL;
|
||||||
}
|
}
|
||||||
rval = 0;
|
rval = 0;
|
||||||
if (jailparam_get(rtparams, nrt,
|
if (jailparam_get(rtparams, nrt, 0) > 0) {
|
||||||
bool_param(j->intparams[IP_ALLOW_DYING]) ? JAIL_DYING : 0) > 0) {
|
|
||||||
rtjp = rtparams + 1;
|
rtjp = rtparams + 1;
|
||||||
for (jp = j->jp; rtjp < rtparams + nrt; jp++) {
|
for (jp = j->jp; rtjp < rtparams + nrt; jp++) {
|
||||||
if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) {
|
if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) {
|
||||||
|
@ -863,7 +814,7 @@ rdtun_params(struct cfjail *j, int dofail)
|
||||||
* Get the jail's jid if it is running.
|
* Get the jail's jid if it is running.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
running_jid(struct cfjail *j, int dflag)
|
running_jid(struct cfjail *j)
|
||||||
{
|
{
|
||||||
struct iovec jiov[2];
|
struct iovec jiov[2];
|
||||||
const char *pval;
|
const char *pval;
|
||||||
|
@ -889,7 +840,7 @@ running_jid(struct cfjail *j, int dflag)
|
||||||
j->jid = -1;
|
j->jid = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
j->jid = jail_get(jiov, 2, dflag ? JAIL_DYING : 0);
|
j->jid = jail_get(jiov, 2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -918,10 +869,9 @@ jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp,
|
||||||
|
|
||||||
jid = jailparam_set(jp, njp, flags);
|
jid = jailparam_set(jp, njp, flags);
|
||||||
if (verbose > 0) {
|
if (verbose > 0) {
|
||||||
jail_note(j, "jail_set(%s%s)",
|
jail_note(j, "jail_set(%s)",
|
||||||
(flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE
|
(flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE
|
||||||
? "JAIL_CREATE" : "JAIL_UPDATE",
|
? "JAIL_CREATE" : "JAIL_UPDATE");
|
||||||
(flags & JAIL_DYING) ? " | JAIL_DYING" : "");
|
|
||||||
for (i = 0; i < njp; i++) {
|
for (i = 0; i < njp; i++) {
|
||||||
printf(" %s", jp[i].jp_name);
|
printf(" %s", jp[i].jp_name);
|
||||||
if (jp[i].jp_value == NULL)
|
if (jp[i].jp_value == NULL)
|
||||||
|
|
Loading…
Reference in New Issue