bectl(8): Support unjailing a boot environment

The given parameter may either be a jid, jail name, or a BE name.  In all
cases, the parameter will be resolved to a jid and bectl(8) will
sanity-check that there's actually a BE mounted at the requested jail root
before invoking jail_remove(2).
This commit is contained in:
Kyle Evans 2018-07-26 03:14:58 +00:00
parent 843e39ce7b
commit ad765da4e8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bectl/; revision=336730
3 changed files with 87 additions and 26 deletions

View File

@ -4,6 +4,7 @@ PROG= bectl
MAN= bectl.8
LIBADD+= be
LIBADD+= jail
LIBADD+= nvpair
CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common

View File

@ -175,8 +175,7 @@ Specifying
.Fl f
will force the unmount if busy.
.Pp
.It Ic unjail
.Ao Ar beName Ac
.It Ic unjail Ao Ar jailID | jailName | beName Ac
.Pp
Destroys the jail created from the given boot environment.
.Pp

View File

@ -30,6 +30,7 @@
#include <sys/jail.h>
#include <sys/mount.h>
#include <errno.h>
#include <jail.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
@ -50,6 +51,8 @@ static int bectl_cmd_jail(int argc, char *argv[]);
static int bectl_cmd_list(int argc, char *argv[]);
static int bectl_cmd_mount(int argc, char *argv[]);
static int bectl_cmd_rename(int argc, char *argv[]);
static int bectl_search_jail_paths(const char *mnt);
static int bectl_locate_jail(const char *ident);
static int bectl_cmd_unjail(int argc, char *argv[]);
static int bectl_cmd_unmount(int argc, char *argv[]);
@ -74,7 +77,7 @@ usage(bool explicit)
"\tbectl list [-a] [-D] [-H] [-s]\n"
"\tbectl mount beName [mountpoint]\n"
"\tbectl rename origBeName newBeName\n"
"\tbectl { ujail | unjail } ⟨jailID | jailName⟩ bootenv\n"
"\tbectl { ujail | unjail } ⟨jailID | jailName | bootenv)\n"
"\tbectl { umount | unmount } [-f] beName\n");
return (explicit ? 0 : EX_USAGE);
@ -447,7 +450,6 @@ bectl_cmd_list(int argc, char *argv[])
return (usage(false));
}
if (be_prop_list_alloc(&props) != 0) {
fprintf(stderr, "bectl list: failed to allocate prop nvlist\n");
return (1);
@ -534,41 +536,100 @@ bectl_cmd_rename(int argc, char *argv[])
return (0);
}
static int
bectl_search_jail_paths(const char *mnt)
{
char jailpath[MAXPATHLEN + 1];
int jid;
jid = 0;
(void)mnt;
while ((jid = jail_getv(0, "lastjid", &jid, "path", &jailpath,
NULL)) != -1) {
if (strcmp(jailpath, mnt) == 0)
return (jid);
}
return (-1);
}
/*
* Locate a jail based on an arbitrary identifier. This may be either a name,
* a jid, or a BE name. Returns the jid or -1 on failure.
*/
static int
bectl_locate_jail(const char *ident)
{
nvlist_t *belist, *props;
char *mnt;
int jid;
/* Try the easy-match first */
jid = jail_getid(ident);
if (jid != -1)
return (jid);
/* Attempt to try it as a BE name, first */
if (be_prop_list_alloc(&belist) != 0)
return (-1);
if (be_get_bootenv_props(be, belist) != 0)
return (-1);
if (nvlist_lookup_nvlist(belist, ident, &props) == 0) {
/* We'll attempt to resolve the jid by way of mountpoint */
if (nvlist_lookup_string(props, "mountpoint", &mnt) == 0) {
jid = bectl_search_jail_paths(mnt);
be_prop_list_free(belist);
return (jid);
}
be_prop_list_free(belist);
}
return (-1);
}
static int
bectl_cmd_unjail(int argc, char *argv[])
{
char *cmd, *target;
int opt;
bool force;
char path[MAXPATHLEN + 1];
char *cmd, *name, *target;
int jid;
/* Store alias used */
cmd = argv[0];
force = false;
while ((opt = getopt(argc, argv, "f")) != -1) {
switch (opt) {
case 'f':
force = true;
break;
default:
fprintf(stderr, "bectl %s: unknown option '-%c'\n",
cmd, optopt);
return (usage(false));
}
}
argc -= optind;
argv += optind;
if (argc != 1) {
if (argc != 2) {
fprintf(stderr, "bectl %s: wrong number of arguments\n", cmd);
return (usage(false));
}
target = argv[0];
target = argv[1];
/* Locate the jail */
if ((jid = bectl_locate_jail(target)) == -1) {
fprintf(stderr, "bectl %s: failed to locate BE by '%s'\n", cmd, target);
return (1);
}
bzero(&path, MAXPATHLEN + 1);
name = jail_getname(jid);
if (jail_getv(0, "name", name, "path", path, NULL) != jid) {
free(name);
fprintf(stderr, "bectl %s: failed to get path for jail requested by '%s'\n", cmd, target);
return (1);
}
free(name);
if (be_mounted_at(be, path, NULL) != 0) {
fprintf(stderr, "bectl %s: jail requested by '%s' not a BE\n", cmd, target);
return (1);
}
jail_remove(jid);
/* unjail logic goes here */
return (0);
}