jail: implement OCI user additionalGIDs
authorDaniel Golle <daniel@makrotopia.org>
Sat, 18 Jul 2020 23:35:16 +0000 (00:35 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Sun, 19 Jul 2020 18:26:09 +0000 (19:26 +0100)
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
jail/jail.c

index f844b57127b72c14f8a32ed97d3baecf9fecc463..287307f602d08cdb5b04ba6336d038c7fab5ae5b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2020 Daniel Golle <daniel@makrotopia.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License version 2.1
@@ -91,6 +92,8 @@ static struct {
        int pw_uid;
        int pw_gid;
        int gr_gid;
+       gid_t *additional_gids;
+       size_t num_additional_gids;
        int require_jail;
        struct {
                struct hook_execvpe **createRuntime;
@@ -860,6 +863,18 @@ static int exec_jail(void *pipes_ptr)
        }
        run_hooks(opts.hooks.startContainer);
 
+       if (!(opts.namespace & CLONE_NEWUSER)) {
+               get_jail_user(&pw_uid, &pw_gid, &gr_gid);
+
+               set_jail_user(opts.pw_uid?:pw_uid, opts.pw_gid?:pw_gid, opts.gr_gid?:gr_gid);
+       }
+
+       if (opts.additional_gids &&
+           (setgroups(opts.num_additional_gids, opts.additional_gids) < 0)) {
+               ERROR("setgroups failed: %m\n");
+               exit(EXIT_FAILURE);
+       }
+
        if (applyOCIcapabilities(opts.capset))
                exit(EXIT_FAILURE);
 
@@ -871,12 +886,6 @@ static int exec_jail(void *pipes_ptr)
                exit(EXIT_FAILURE);
        }
 
-       if (!(opts.namespace & CLONE_NEWUSER)) {
-               get_jail_user(&pw_uid, &pw_gid, &gr_gid);
-
-               set_jail_user(opts.pw_uid?:pw_uid, opts.pw_gid?:pw_gid, opts.gr_gid?:gr_gid);
-       }
-
        char **envp = build_envp(opts.seccomp, opts.envp);
        if (!envp)
                exit(EXIT_FAILURE);
@@ -1216,6 +1225,9 @@ static const struct blobmsg_policy oci_process_user_policy[] = {
 
 static int parseOCIprocessuser(struct blob_attr *msg) {
        struct blob_attr *tb[__OCI_PROCESS_USER_MAX];
+       struct blob_attr *cur;
+       int rem;
+       int has_gid = 0;
 
        blobmsg_parse(oci_process_user_policy, __OCI_PROCESS_USER_MAX, tb, blobmsg_data(msg), blobmsg_len(msg));
 
@@ -1225,9 +1237,37 @@ static int parseOCIprocessuser(struct blob_attr *msg) {
        if (tb[OCI_PROCESS_USER_GID]) {
                opts.pw_gid = blobmsg_get_u32(tb[OCI_PROCESS_USER_GID]);
                opts.gr_gid = blobmsg_get_u32(tb[OCI_PROCESS_USER_GID]);
+               has_gid = 1;
+       }
+
+       if (tb[OCI_PROCESS_USER_ADDITIONALGIDS]) {
+               size_t gidcnt = 0;
+
+               blobmsg_for_each_attr(cur, tb[OCI_PROCESS_USER_ADDITIONALGIDS], rem) {
+                       ++gidcnt;
+                       if (has_gid && (blobmsg_get_u32(cur) == opts.gr_gid))
+                               continue;
+               }
+
+               if (gidcnt) {
+                       opts.additional_gids = calloc(gidcnt + has_gid, sizeof(gid_t));
+                       gidcnt = 0;
+
+                       /* always add primary GID to set of GIDs if set */
+                       if (has_gid)
+                               opts.additional_gids[gidcnt++] = opts.gr_gid;
+
+                       blobmsg_for_each_attr(cur, tb[OCI_PROCESS_USER_ADDITIONALGIDS], rem) {
+                               if (has_gid && (blobmsg_get_u32(cur) == opts.gr_gid))
+                                       continue;
+                               opts.additional_gids[gidcnt++] = blobmsg_get_u32(cur);
+                       }
+                       opts.num_additional_gids = gidcnt;
+               }
+               DEBUG("read %lu additional groups\n", gidcnt);
        }
 
-       /* ToDo: umask, additional GIDs */
+       /* ToDo: umask */
 
        return 0;
 }