aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorJamie Gritton <jamie@FreeBSD.org>2024-03-17 05:11:14 +0000
committerJamie Gritton <jamie@FreeBSD.org>2024-03-17 05:11:14 +0000
commitd50685b303e3353aa1aeaea022a80f31e3732a29 (patch)
tree86d3c92973309be3f041ab0e465c08280ff6118e /usr.sbin
parent75464941dc17876af2e99ea90c687bd7df873d73 (diff)
downloadsrc-d50685b303e3353aa1aeaea022a80f31e3732a29.tar.gz
src-d50685b303e3353aa1aeaea022a80f31e3732a29.zip
jail: add the -C flag to clean up after a partially removed jail
Differential Revision: https://reviews.freebsd.org/D42670
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/jail/jail.89
-rw-r--r--usr.sbin/jail/jail.c56
-rw-r--r--usr.sbin/jail/jailp.h1
-rw-r--r--usr.sbin/jail/state.c4
4 files changed, 54 insertions, 16 deletions
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index e49c3fe95e7f..d58192623952 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd January 17, 2024
+.Dd March 16, 2024
.Dt JAIL 8
.Os
.Sh NAME
@@ -33,13 +33,13 @@
.Ss From Configuration File
.Nm
.Op Fl cm
-.Op Fl dqv
+.Op Fl Cdqv
.Op Fl f Ar conf_file
.Op Fl p Ar limit
.Op Ar jail
.Nm
.Op Fl r
-.Op Fl qv
+.Op Fl Cqv
.Op Fl f Ar conf_file
.Op Fl p Ar limit
.Op Cm * | Ar jail ...
@@ -144,6 +144,9 @@ jail if it does exist.
.Pp
Other available options are:
.Bl -tag -width indent
+.It Fl C
+Clean up after an already-removed jail, running commands and operations
+that are typically run following jail removal.
.It Fl f Ar conf_file
Use configuration file
.Ar conf_file
diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c
index df0a32321794..53e05870ff26 100644
--- a/usr.sbin/jail/jail.c
+++ b/usr.sbin/jail/jail.c
@@ -128,6 +128,24 @@ static const enum intparam stopcommands[] = {
IP__NULL
};
+static const enum intparam cleancommands[] = {
+ IP__NULL,
+ IP_EXEC_POSTSTOP,
+ IP_MOUNT_PROCFS,
+ IP_MOUNT_FDESCFS,
+ IP_MOUNT_DEVFS,
+ IP__MOUNT_FROM_FSTAB,
+ IP_MOUNT,
+#ifdef INET6
+ IP__IP6_IFADDR,
+#endif
+#ifdef INET
+ IP__IP4_IFADDR,
+#endif
+ IP_EXEC_RELEASE,
+ IP__NULL
+};
+
int
main(int argc, char **argv)
{
@@ -153,11 +171,14 @@ main(int argc, char **argv)
cfname = CONF_FILE;
JidFile = NULL;
- while ((ch = getopt(argc, argv, "cde:f:hiJ:lmn:p:qrRs:u:U:v")) != -1) {
+ while ((ch = getopt(argc, argv, "cCde:f:hiJ:lmn:p:qrRs:u:U:v")) != -1) {
switch (ch) {
case 'c':
op |= JF_START;
break;
+ case 'C':
+ op |= JF_CLEANUP;
+ break;
case 'd':
dflag = 1;
break;
@@ -305,7 +326,7 @@ main(int argc, char **argv)
note_remove = docf || argc > 1 || wild_jail_name(argv[0]);
} else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) {
/* Single jail specified on the command line */
- if (Rflag)
+ if (Rflag || (op & JF_CLEANUP))
usage();
docf = 0;
for (i = 0; i < argc; i++) {
@@ -355,7 +376,7 @@ main(int argc, char **argv)
/* Find out which jails will be run. */
dep_setup(docf);
error = 0;
- if (op == JF_STOP) {
+ if ((op & JF_OP_MASK) == JF_STOP) {
for (i = 0; i < argc; i++)
if (start_state(argv[i], docf, op, Rflag) < 0)
error = 1;
@@ -415,22 +436,24 @@ main(int argc, char **argv)
* depending on the jail's current status.
*/
case JF_START_SET:
- j->flags = j->jid < 0 ? JF_START : JF_SET;
+ j->flags = j->jid < 0
+ ? (j->flags & JF_CLEANUP) | JF_START : JF_SET;
break;
case JF_SET_RESTART:
- if (j->jid < 0) {
+ if (j->jid < 0 && !(j->flags & JF_CLEANUP)) {
jail_quoted_warnx(j, "not found",
"no jail specified");
failed(j);
continue;
}
- j->flags = rdtun_params(j, 0) ? JF_RESTART : JF_SET;
+ j->flags = rdtun_params(j, 0)
+ ? (j->flags & JF_CLEANUP) | JF_RESTART : JF_SET;
if (j->flags == JF_RESTART)
dep_reset(j);
break;
case JF_START_SET_RESTART:
- j->flags = j->jid < 0 ? JF_START
- : rdtun_params(j, 0) ? JF_RESTART : JF_SET;
+ j->flags = j->jid < 0 ? JF_START : rdtun_params(j, 0)
+ ? (j->flags & JF_CLEANUP) | JF_RESTART : JF_SET;
if (j->flags == JF_RESTART)
dep_reset(j);
}
@@ -449,11 +472,18 @@ main(int argc, char **argv)
continue;
if (j->jid > 0)
goto jail_create_done;
+ if (j->flags & JF_CLEANUP) {
+ j->flags |= JF_STOP;
+ j->comparam = cleancommands;
+ } else
+ j->comparam = startcommands;
j->comparam = startcommands;
j->comstring = NULL;
}
if (next_command(j))
continue;
+ if (j->flags & JF_STOP)
+ goto jail_remove_done;
jail_create_done:
clear_persist(j);
if (jfp != NULL)
@@ -485,7 +515,10 @@ main(int argc, char **argv)
if (j->comparam == NULL) {
if (dep_check(j))
continue;
- if (j->jid < 0) {
+ if (j->flags & JF_CLEANUP) {
+ j->comparam = j->jid < 0
+ ? cleancommands : stopcommands;
+ } else if (j->jid < 0) {
if (!(j->flags & (JF_DEPEND|JF_WILD))) {
if (verbose >= 0)
jail_quoted_warnx(j,
@@ -494,7 +527,8 @@ main(int argc, char **argv)
}
goto jail_remove_done;
}
- j->comparam = stopcommands;
+ else
+ j->comparam = stopcommands;
j->comstring = NULL;
} else if ((j->flags & JF_FAILED) && j->jid > 0)
goto jail_remove_done;
@@ -504,7 +538,7 @@ main(int argc, char **argv)
dep_done(j, 0);
if ((j->flags & (JF_START | JF_FAILED)) == JF_START) {
j->comparam = NULL;
- j->flags &= ~JF_STOP;
+ j->flags &= ~(JF_STOP | JF_CLEANUP);
dep_reset(j);
requeue(j, j->ndeps ? &depend : &ready);
}
diff --git a/usr.sbin/jail/jailp.h b/usr.sbin/jail/jailp.h
index 74ef2a8acab8..ccd96f5f247e 100644
--- a/usr.sbin/jail/jailp.h
+++ b/usr.sbin/jail/jailp.h
@@ -67,6 +67,7 @@
#define JF_TIMEOUT 0x0200 /* A command (or process kill) timed out */
#define JF_SLEEPQ 0x0400 /* Waiting on a command and/or timeout */
#define JF_FROM_RUNQ 0x0800 /* Has already been on the run queue */
+#define JF_CLEANUP 0x1000 /* -C Run post-removal commands */
#define JF_OP_MASK (JF_START | JF_SET | JF_STOP)
#define JF_RESTART (JF_START | JF_STOP)
diff --git a/usr.sbin/jail/state.c b/usr.sbin/jail/state.c
index 6cbe879acc55..1d200beacef9 100644
--- a/usr.sbin/jail/state.c
+++ b/usr.sbin/jail/state.c
@@ -306,7 +306,7 @@ start_state(const char *target, int docf, unsigned state, int running)
int jid;
char namebuf[MAXHOSTNAMELEN];
- if (!target || (!docf && state != JF_STOP) ||
+ if (!target || (!docf && (state & JF_OP_MASK) != JF_STOP) ||
(!running && !strcmp(target, "*"))) {
/*
* For a global wildcard (including no target specified),
@@ -365,7 +365,7 @@ start_state(const char *target, int docf, unsigned state, int running)
}
} else {
j = find_jail(target);
- if (j == NULL && state == JF_STOP) {
+ if (j == NULL && (state & JF_OP_MASK) == JF_STOP) {
/* Allow -[rR] to specify a currently running jail. */
j = running_jail(target, JAIL_DYING);
}