jail: allow passing environment variable to procd jailed process
authorDaniel Golle <daniel@makrotopia.org>
Thu, 11 Nov 2021 11:53:58 +0000 (11:53 +0000)
committerDaniel Golle <daniel@makrotopia.org>
Thu, 11 Nov 2021 14:02:25 +0000 (14:02 +0000)
Introduce new option '-e' to ujail which can be stated multiple times
to import environment variables to the jailed process environment.
Use that option to import selected environment variables defined for
a jailed service instance to its environment.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
jail/jail.c
service/instance.c

index 3f42bcbd96f3568aed8882d6d20aa8719afdaf0f..6e9306d0888cd5f955cfb1deb41589d69ef1f67f 100644 (file)
@@ -69,7 +69,7 @@
 #endif
 
 #define STACK_SIZE     (1024 * 1024)
-#define OPT_ARGS       "cC:d:EfFG:h:ij:J:ln:NoO:pP:r:R:sS:uU:w:T:y"
+#define OPT_ARGS       "cC:d:e:EfFG:h:ij:J:ln:NoO:pP:r:R:sS:uU:w:T:y"
 
 #define OCI_VERSION_STRING "1.0.2"
 
@@ -980,6 +980,7 @@ static void usage(void)
        fprintf(stderr, "  -C <file>\tcapabilities drop config\n");
        fprintf(stderr, "  -c\t\tset PR_SET_NO_NEW_PRIVS\n");
        fprintf(stderr, "  -n <name>\tthe name of the jail\n");
+       fprintf(stderr, "  -e <var>\timport environment variable\n");
        fprintf(stderr, "namespace jail options:\n");
        fprintf(stderr, "  -h <hostname>\tchange the hostname of the jail\n");
        fprintf(stderr, "  -N\t\tjail has network namespace\n");
@@ -2541,6 +2542,12 @@ static int pidns_fd;
 static int timens_fd;
 #endif
 static void post_create_runtime(void);
+
+struct env_e {
+       struct list_head list;
+       char *envarg;
+};
+
 int main(int argc, char **argv)
 {
        uid_t uid = getuid();
@@ -2549,6 +2556,9 @@ int main(int argc, char **argv)
        int ret = EXIT_FAILURE;
        int ch;
        char *tmp;
+       struct list_head envl = LIST_HEAD_INIT(envl);
+       struct env_e *enve, *tmpenve;
+       unsigned short int envn = 0, envc = 0;
 
        if (uid) {
                ERROR("not root, aborting: %m\n");
@@ -2578,6 +2588,11 @@ int main(int argc, char **argv)
                case 'd':
                        debug = atoi(optarg);
                        break;
+               case 'e':
+                       enve = calloc(1, sizeof(*enve));
+                       enve->envarg = optarg;
+                       list_add_tail(&enve->list, &envl);
+                       break;
                case 'p':
                        opts.namespace |= CLONE_NEWNS;
                        opts.procfs = 1;
@@ -2683,6 +2698,34 @@ int main(int argc, char **argv)
        if (opts.namespace && !opts.ocibundle)
                opts.namespace |= CLONE_NEWIPC | CLONE_NEWPID;
 
+       /*
+        * env import from cmdline is not available for OCI containers
+        */
+       if (opts.ocibundle && !list_empty(&envl)) {
+               ret=-ENOTSUP;
+               goto errout;
+       }
+
+       /*
+        * prepare list of env variables to import for slim containers
+        */
+       if (!list_empty(&envl)) {
+               list_for_each_entry(enve, &envl, list)
+                       ++envn;
+
+               opts.envp = calloc(1 + envn, sizeof(char*));
+               list_for_each_entry_safe(enve, tmpenve, &envl, list) {
+                       tmp = getenv(enve->envarg);
+                       if (tmp)
+                               asprintf(&opts.envp[envc++], "%s=%s", enve->envarg, tmp);
+
+                       list_del(&enve->list);
+                       free(enve);
+               }
+
+               opts.envp[envc] = NULL;
+       }
+
        /*
         * uid in parent user namespace representing root user in new
         * user namespace, defaults to nobody unless specified in uidMappings
index 701ca00494268ee7085a4df4d9adce51db577e9a..8cabedb8b0fd789fb0686c7b4a9f35ec3abfd441 100644 (file)
@@ -385,6 +385,11 @@ jail_run(struct service_instance *in, char **argv)
        if (in->require_jail)
                argv[argc++] = "-E";
 
+       blobmsg_list_for_each(&in->env, var) {
+               argv[argc++] = "-e";
+               argv[argc++] = (char *) blobmsg_name(var->data);
+       }
+
        blobmsg_list_for_each(&jail->mount, var) {
                const char *type = blobmsg_data(var->data);
 
@@ -1137,6 +1142,7 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
 {
        struct blob_attr *tb[__JAIL_ATTR_MAX];
        struct jail *jail = &in->jail;
+       struct blobmsg_list_node *var;
 
        blobmsg_parse(jail_attr, __JAIL_ATTR_MAX, tb,
                blobmsg_data(attr), blobmsg_data_len(attr));
@@ -1219,6 +1225,9 @@ instance_jail_parse(struct service_instance *in, struct blob_attr *attr)
                instance_fill_array(&jail->mount, tb[JAIL_ATTR_MOUNT], NULL, false);
        }
 
+       blobmsg_list_for_each(&in->env, var)
+               jail->argc += 2;
+
        if (in->seccomp)
                jail->argc += 2;