Page MenuHomeFreeBSD

D19282.id54184.diff
No OneTemporary

D19282.id54184.diff

Index: sbin/bectl/bectl_jail.c
===================================================================
--- sbin/bectl/bectl_jail.c
+++ sbin/bectl/bectl_jail.c
@@ -40,95 +40,36 @@
#include <unistd.h>
#include <be.h>
-
#include "bectl.h"
-static void jailparam_grow(void);
static void jailparam_add(const char *name, const char *val);
static int jailparam_del(const char *name);
static bool jailparam_addarg(char *arg);
static int jailparam_delarg(char *arg);
+static int bectl_cmd_jail_background(void);
+static int bectl_cmd_jail_exec(void);
static int bectl_search_jail_paths(const char *mnt);
static int bectl_locate_jail(const char *ident);
-/* We'll start with 8 parameters initially and grow as needed. */
-#define INIT_PARAMCOUNT 8
+static int nvlist_to_jailparam(struct jailparam **jp);
-static struct jailparam *jp;
-static int jpcnt;
static int jpused;
static char mnt_loc[BE_MAXPATHLEN];
+static nvlist_t *jailparams;
-static void
-jailparam_grow(void)
-{
-
- jpcnt *= 2;
- jp = realloc(jp, jpcnt * sizeof(*jp));
- if (jp == NULL)
- err(2, "realloc");
-}
static void
jailparam_add(const char *name, const char *val)
{
- int i;
-
- for (i = 0; i < jpused; ++i) {
- if (strcmp(name, jp[i].jp_name) == 0)
- break;
- }
-
- if (i < jpused)
- jailparam_free(&jp[i], 1);
- else if (jpused == jpcnt)
- /* The next slot isn't allocated yet */
- jailparam_grow();
-
- if (jailparam_init(&jp[i], name) != 0)
- return;
- if (jailparam_import(&jp[i], val) != 0)
- return;
- ++jpused;
+ jpused++;
+ nvlist_add_string(jailparams, name, val);
}
static int
jailparam_del(const char *name)
{
- int i;
- char *val;
-
- for (i = 0; i < jpused; ++i) {
- if (strcmp(name, jp[i].jp_name) == 0)
- break;
- }
-
- if (i == jpused)
- return (ENOENT);
-
- for (; i < jpused - 1; ++i) {
- val = jailparam_export(&jp[i + 1]);
-
- jailparam_free(&jp[i], 1);
- /*
- * Given the context, the following will really only fail if
- * they can't allocate the copy of the name or value.
- */
- if (jailparam_init(&jp[i], jp[i + 1].jp_name) != 0) {
- free(val);
- return (ENOMEM);
- }
- if (jailparam_import(&jp[i], val) != 0) {
- jailparam_free(&jp[i], 1);
- free(val);
- return (ENOMEM);
- }
- free(val);
- }
-
- jailparam_free(&jp[i], 1);
- --jpused;
+ nvlist_remove_all(jailparams, name);
return (0);
}
@@ -145,7 +86,7 @@
arg);
return (false);
}
-
+
*val++ = '\0';
if (strcmp(name, "path") == 0) {
if (strlen(val) >= BE_MAXPATHLEN) {
@@ -176,21 +117,61 @@
return (jailparam_del(name));
}
+/* Convert our nvlist to a jailparam struct*/
+static int
+nvlist_to_jailparam(struct jailparam **jpp)
+{
+ int rc, i, jpidx;
+ char *name, *value;
+ struct jailparam *jp;
+ nvpair_t *cur;
+
+ jp = malloc(jpused * sizeof(*jp));
+ if (jp == NULL)
+ err(2, "malloc");
+
+ cur = nvlist_next_nvpair(jailparams, NULL);
+ for(i = jpidx = 0; i < jpused; i++){
+ name = nvpair_name(cur);
+ nvpair_value_string(cur, &value);
+
+ fprintf(stderr, "bectl jail: import jailparam: '%s'='%s'\n", name, value);
+ if ((rc = jailparam_init(&jp[jpidx], name)) != 0) {
+ continue;
+ }
+
+ if ((rc = jailparam_import(&jp[jpidx], value)) != 0 ){
+ continue;
+ }
+ jpidx++;
+ cur = nvlist_next_nvpair(jailparams, cur);
+ }
+
+ if (jpidx != jpused) {
+ //resize jp with the new size.
+ fprintf(stderr, "one of our params wasnt added. should resize here");
+ }
+
+ *jpp = jp;
+ return (0);
+}
+
int
bectl_cmd_jail(int argc, char *argv[])
{
char *bootenv, *mountpoint;
- int jid, mntflags, opt, ret;
+ int mntflags, opt, ret;
bool default_hostname, interactive, unjail;
- pid_t pid;
/* XXX TODO: Allow shallow */
mntflags = BE_MNT_DEEP;
default_hostname = interactive = unjail = true;
- jpcnt = INIT_PARAMCOUNT;
- jp = malloc(jpcnt * sizeof(*jp));
- if (jp == NULL)
- err(2, "malloc");
+
+ ret = nvlist_alloc(&jailparams, NV_UNIQUE_NAME, 0);
+ if (ret) {
+ fprintf(stderr, "nvlist_alloc() failed\n");
+ return (ret);
+ }
jailparam_add("persist", "true");
jailparam_add("allow.mount", "true");
@@ -242,6 +223,16 @@
return (usage(false));
}
+ if (argc > 1) {
+ if ( nvlist_exists(jailparams, "command") ||
+ nvlist_exists(jailparams, "exec.start") ){
+ fprintf(stderr, "command is defined more than once");
+ return (1);
+ }
+ jailparam_add("command", argv[1]);
+ }
+
+
bootenv = argv[0];
/*
@@ -266,7 +257,37 @@
*/
if (mountpoint == NULL)
jailparam_add("path", mnt_loc);
- /* Create the jail for now, attach later as-needed */
+
+ if (!interactive){
+ ret = bectl_cmd_jail_background();
+ } else {
+ ret = bectl_cmd_jail_exec();
+ }
+
+ if (ret || unjail)
+ be_unmount(be, bootenv, 0);
+
+ return (ret);
+}
+
+/*
+ * Convert our nvlist to a jailparam pointer and create the jail
+ * using jailparam_set. This limits us to only using jailparams and
+ * not any pseudo ones, such as 'mount.devfs'.
+ *
+ * This function frees the jailparams nvlist.
+ */
+static int
+bectl_cmd_jail_background()
+{
+ struct jailparam *jp;
+ int jid;
+
+ if( nvlist_to_jailparam(&jp) != 0 ){
+ nvlist_free(jailparams);
+ return (1);
+ }
+
jid = jailparam_set(jp, jpused, JAIL_CREATE);
if (jid == -1) {
fprintf(stderr, "unable to create jail. error: %d\n", errno);
@@ -274,11 +295,71 @@
}
jailparam_free(jp, jpused);
+ nvlist_free(jailparams);
free(jp);
- /* We're not interactive, nothing more to do here. */
- if (!interactive)
- return (0);
+ return (0);
+}
+
+/*
+ * Fork into the system's jail command so that it can handle the
+ * pesudo jailparams.
+ */
+static int
+bectl_cmd_jail_exec(){
+ char **args, *name, *value, buf[4096];
+ char **argpos; // do we need this if we have args?
+ int total;
+ pid_t pid;
+ nvpair_t *cur;
+
+ // Basically we shove everything into our buffer, while
+ // incrementing our pointer.
+ total = 0;
+
+ args = malloc( (jpused + 3) * sizeof(char *));
+ if (args == NULL) {
+ err(2, "malloc");
+ }
+
+ // bufarg keeps track of our position on the buffer,
+ argpos = args;
+
+ // our first argument starts at the adress of the
+ // buffer
+ *argpos++ = buf;
+
+ // write our jail command and, flags to the buffer
+ // we add a +1 so the null terminator exists in our buffer
+ total += sprintf(buf + total, "/usr/sbin/jail") + 1;
+ *argpos++ = buf + total;
+
+ total += sprintf(buf + total, "-c") + 1;
+ *argpos++ = buf + total;
+
+ cur = nvlist_next_nvpair(jailparams, NULL);
+ while(cur != NULL){
+ name = nvpair_name(cur);
+ nvpair_value_string(cur, &value);
+ // TODO: add range checking here to exit when we go over the
+ // buffer? or if the number returned == 1 (meaning we
+ // didnt write anything )
+ total += snprintf(buf + total, 4096 + total, "%s=%s", name, value) + 1;
+ *argpos++ = buf + total;
+
+ cur = nvlist_next_nvpair(jailparams, cur);
+ }
+
+ //*argpos = NULL;
+ args[jpused+2] = NULL;
+ nvlist_free(jailparams);
+
+ for (int i = 0; i < (jpused + 3); i++){
+ if (args[i] == NULL)
+ fprintf(stderr, "arg[%d]: NULL\n", i);
+ else
+ fprintf(stderr, "arg[%d]: %s\n", i, args[i]);
+ }
pid = fork();
switch(pid) {
@@ -286,29 +367,16 @@
perror("fork");
return (1);
case 0:
- jail_attach(jid);
- /* We're attached within the jail... good bye! */
- chdir("/");
- if (argc > 1)
- execve(argv[1], &argv[1], NULL);
- else
- execl("/bin/sh", "/bin/sh", NULL);
- fprintf(stderr, "bectl jail: failed to execute %s\n",
- (argc > 1 ? argv[1] : "/bin/sh"));
- _exit(1);
+ execvp(args[0], args);
default:
- /* Wait for the child to get back, see if we need to unjail */
waitpid(pid, NULL, 0);
}
- if (unjail) {
- jail_remove(jid);
- be_unmount(be, bootenv, 0);
- }
-
+ free(args);
return (0);
}
+
static int
bectl_search_jail_paths(const char *mnt)
{

File Metadata

Mime Type
text/plain
Expires
Mon, May 18, 3:17 AM (7 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33231184
Default Alt Text
D19282.id54184.diff (7 KB)

Event Timeline