Simplify uids/gids maps
authorRobert Swiecki <robert@swiecki.net>
Sat, 27 May 2017 23:05:27 +0000 (01:05 +0200)
committerRobert Swiecki <robert@swiecki.net>
Sat, 27 May 2017 23:05:27 +0000 (01:05 +0200)
cmdline.c
common.h
config.c
user.c
user.h

index 699e479c761e9fea8eee71eb68ec29040ac76fcb..cc68354c59d36d31c1e2e6e975f30bbb176e4da3 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -108,7 +108,7 @@ struct custom_option custom_opts[] = {
     {{"disable_clone_newuts", no_argument, NULL, 0x0406}, "Don't use CLONE_NEWUTS"},
     {{"enable_clone_newcgroup", no_argument, NULL, 0x0407}, "Use CLONE_NEWCGROUP"},
     {{"uid_mapping", required_argument, NULL, 'U'}, "Add a custom uid mapping of the form inside_uid:outside_uid:count. Setting this requires newuidmap to be present"},
-    {{"gid_mapping", required_argument, NULL, 'G'}, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newuidmap to be present"},
+    {{"gid_mapping", required_argument, NULL, 'G'}, "Add a custom gid mapping of the form inside_gid:outside_gid:count. Setting this requires newgidmap to be present"},
     {{"bindmount_ro", required_argument, NULL, 'R'}, "List of mountpoints to be mounted --bind (ro) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
     {{"bindmount", required_argument, NULL, 'B'}, "List of mountpoints to be mounted --bind (rw) inside the container. Can be specified multiple times. Supports 'source' syntax, or 'source:dest'"},
     {{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
@@ -234,34 +234,17 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
        {
                struct idmap_t *p;
                TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
-                       LOG_I("Uid map: inside_uid:%d outside_uid:%d count:%zu", p->inside_id,
-                             p->outside_id, p->count);
+                       LOG_I("Uid map: inside_uid:%d outside_uid:%d count:%zu newuidmap:%s",
+                             p->inside_id, p->outside_id, p->count,
+                             p->is_newidmap ? "true" : "false");
                        if (p->outside_id == 0) {
                                LOG_W("Process will be UID/EUID=0 in the global user namespace");
                        }
                }
                TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
-                       LOG_I("Gid map: inside_gid:%d outside_gid:%d count:%zu", p->inside_id,
-                             p->outside_id, p->count);
-                       if (p->outside_id == 0) {
-                               LOG_W("Process will be GID/EGID=0 in the global user namespace");
-                       }
-               }
-       }
-
-       {
-               struct idmap_t *p;
-               TAILQ_FOREACH(p, &nsjconf->newuidmap, pointers) {
-                       LOG_I("Newuid mapping: inside_uid:%u outside_uid:%u count:%zu",
-                             p->inside_id, p->outside_id, p->count);
-                       if (p->outside_id == 0) {
-                               LOG_W("Process will be UID/EUID=0 in the global user namespace");
-                       }
-               }
-
-               TAILQ_FOREACH(p, &nsjconf->newgidmap, pointers) {
-                       LOG_I("Newgid mapping: inside_uid:%u outside_uid:%u count:%zu",
-                             p->inside_id, p->outside_id, p->count);
+                       LOG_I("Gid map: inside_gid:%d outside_gid:%d count:%zu newgidmap:%s",
+                             p->inside_id, p->outside_id, p->count,
+                             p->is_newidmap ? "true" : "false");
                        if (p->outside_id == 0) {
                                LOG_W("Process will be GID/EGID=0 in the global user namespace");
                        }
@@ -379,8 +362,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
        TAILQ_INIT(&nsjconf->envs);
        TAILQ_INIT(&nsjconf->uids);
        TAILQ_INIT(&nsjconf->gids);
-       TAILQ_INIT(&nsjconf->newuidmap);
-       TAILQ_INIT(&nsjconf->newgidmap);
 
        static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
 
@@ -574,12 +555,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                                || strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
                                                                                              NULL,
                                                                                              0);
-
-                               struct idmap_t *p =
-                                   userParseId(i_id, o_id, count, false /* is_gid */ );
-                               if (p) {
-                                       TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
-                               } else {
+                               if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */ ,
+                                               false /* is_newidmap */ ) == false) {
                                        return false;
                                }
                        }
@@ -592,11 +569,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                                || strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
                                                                                              NULL,
                                                                                              0);
-                               struct idmap_t *p =
-                                   userParseId(i_id, o_id, count, true /* is_gid */ );
-                               if (p) {
-                                       TAILQ_INSERT_TAIL(&nsjconf->gids, p, pointers);
-                               } else {
+                               if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */ ,
+                                               false /* is_newidmap */ ) == false) {
                                        return false;
                                }
                        }
@@ -609,11 +583,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                                || strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
                                                                                              NULL,
                                                                                              0);
-                               struct idmap_t *p =
-                                   userParseId(i_id, o_id, count, false /* is_gid */ );
-                               if (p) {
-                                       TAILQ_INSERT_TAIL(&nsjconf->newuidmap, p, pointers);
-                               } else {
+                               if (userParseId(nsjconf, i_id, o_id, count, false /* is_gid */ ,
+                                               true /* is_newidmap */ ) == false) {
                                        return false;
                                }
                        }
@@ -626,11 +597,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                                                || strlen(cnt) == 0) ? 1U : (size_t) strtoull(cnt,
                                                                                              NULL,
                                                                                              0);
-                               struct idmap_t *p =
-                                   userParseId(i_id, o_id, count, true /* is_gid */ );
-                               if (p) {
-                                       TAILQ_INSERT_TAIL(&nsjconf->newgidmap, p, pointers);
-                               } else {
+                               if (userParseId(nsjconf, i_id, o_id, count, true /* is_gid */ ,
+                                               true /* is_newidmap */ ) == false) {
                                        return false;
                                }
                        }
@@ -638,7 +606,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                case 'R':{
                                struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
                                p->src = optarg;
-                               p->dst = cmdlineSplitStrByColon(optarg);
+                               const char *dst = cmdlineSplitStrByColon(optarg);
+                               p->dst = dst ? dst : optarg;
                                p->flags = MS_BIND | MS_REC | MS_RDONLY;
                                p->options = "";
                                p->fs_type = "";
@@ -649,7 +618,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                case 'B':{
                                struct mounts_t *p = utilMalloc(sizeof(struct mounts_t));
                                p->src = optarg;
-                               p->dst = cmdlineSplitStrByColon(optarg);
+                               const char *dst = cmdlineSplitStrByColon(optarg);
+                               p->dst = dst ? dst : optarg;
                                p->flags = MS_BIND | MS_REC;
                                p->options = "";
                                p->fs_type = "";
@@ -787,6 +757,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                p->inside_id = getuid();
                p->outside_id = getuid();
                p->count = 1U;
+               p->is_newidmap = false;
                TAILQ_INSERT_HEAD(&nsjconf->uids, p, pointers);
        }
        if (TAILQ_EMPTY(&nsjconf->gids)) {
@@ -794,6 +765,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                p->inside_id = getgid();
                p->outside_id = getgid();
                p->count = 1U;
+               p->is_newidmap = false;
                TAILQ_INSERT_HEAD(&nsjconf->gids, p, pointers);
        }
 
index 6fb1ab29f6b65bf2bb26a15866ab0e18e076e1c5..a03fe5c218ef7351b736e6fbf68c9a7fce325d23 100644 (file)
--- a/common.h
+++ b/common.h
@@ -79,6 +79,7 @@ struct idmap_t {
        uid_t inside_id;
        uid_t outside_id;
        size_t count;
+       bool is_newidmap;
         TAILQ_ENTRY(idmap_t) pointers;
 };
 
@@ -161,8 +162,6 @@ struct nsjconf_t {
        char *kafel_string;
         TAILQ_HEAD(udmaplist, idmap_t) uids;
         TAILQ_HEAD(gdmaplist, idmap_t) gids;
-        TAILQ_HEAD(newuidmaplist, idmap_t) newuidmap;
-        TAILQ_HEAD(newgidmaplist, idmap_t) newgidmap;
         TAILQ_HEAD(envlist, charptr_t) envs;
         TAILQ_HEAD(pidslist, pids_t) pids;
         TAILQ_HEAD(mountptslist, mounts_t) mountpts;
index 28b6a6c1c335c10a577da8efd6fb354cfa93ef40..c5fb07710ed56168ee1116c2580339d2ddd58449 100644 (file)
--- a/config.c
+++ b/config.c
@@ -155,30 +155,20 @@ static bool configParseInternal(struct nsjconf_t *nsjconf, Nsjail__NsJailConfig
        nsjconf->clone_newcgroup = njc->clone_newcgroup;
 
        for (size_t i = 0; i < njc->n_uidmap; i++) {
-               struct idmap_t *p =
-                   userParseId(njc->uidmap[i]->inside_id, njc->uidmap[i]->outside_id,
-                               njc->uidmap[i]->count, false /* is_gid */ );
-               if (p == NULL) {
+               if (userParseId
+                   (nsjconf, njc->uidmap[i]->inside_id, njc->uidmap[i]->outside_id,
+                    njc->uidmap[i]->count, false /* is_gid */ ,
+                    njc->uidmap[i]->use_newidmap) == false) {
                        return false;
                }
-               if (njc->uidmap[i]->use_newidmap) {
-                       TAILQ_INSERT_TAIL(&nsjconf->newuidmap, p, pointers);
-               } else {
-                       TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
-               }
        }
        for (size_t i = 0; i < njc->n_gidmap; i++) {
-               struct idmap_t *p =
-                   userParseId(njc->gidmap[i]->inside_id, njc->gidmap[i]->outside_id,
-                               njc->gidmap[i]->count, true /* is_gid */ );
-               if (p == NULL) {
+               if (userParseId
+                   (nsjconf, njc->gidmap[i]->inside_id, njc->gidmap[i]->outside_id,
+                    njc->gidmap[i]->count, true /* is_gid */ ,
+                    njc->gidmap[i]->use_newidmap) == false) {
                        return false;
                }
-               if (njc->gidmap[i]->use_newidmap) {
-                       TAILQ_INSERT_TAIL(&nsjconf->newgidmap, p, pointers);
-               } else {
-                       TAILQ_INSERT_TAIL(&nsjconf->gids, p, pointers);
-               }
        }
 
        nsjconf->mount_proc = njc->mount_proc;
diff --git a/user.c b/user.c
index 1eeb9078709c894ed15b131beeaf28e183b94785..1fe8dd682d03abe326f7dc07262f07edb4487a64 100644 (file)
--- a/user.c
+++ b/user.c
@@ -67,10 +67,17 @@ static bool userUidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
 
        struct idmap_t *p;
        TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
+               if (p->is_newidmap) {
+                       continue;
+               }
                utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
                              (unsigned long)p->outside_id, p->count);
        }
 
+       if (strlen(map) == 0) {
+               return true;
+       }
+
        LOG_D("Writing '%s' to '%s'", map, fname);
        if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) {
                LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map);
@@ -89,10 +96,17 @@ static bool userGidMapSelf(struct nsjconf_t *nsjconf, pid_t pid)
 
        struct idmap_t *p;
        TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
+               if (p->is_newidmap) {
+                       continue;
+               }
                utilSSnPrintf(map, sizeof(map), "%lu %lu %zu\n", (unsigned long)p->inside_id,
                              (unsigned long)p->outside_id, p->count);
        }
 
+       if (strlen(map) == 0) {
+               return true;
+       }
+
        LOG_D("Writing '%s' to '%s'", map, fname);
        if (utilWriteBufToFile(fname, map, strlen(map), O_WRONLY) == false) {
                LOG_E("utilWriteBufToFile('%s', '%s') failed", fname, map);
@@ -117,7 +131,10 @@ static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
        idx++;
 
        struct idmap_t *p;
-       TAILQ_FOREACH(p, &nsjconf->newgidmap, pointers) {
+       TAILQ_FOREACH(p, &nsjconf->gids, pointers) {
+               if (p->is_newidmap == false) {
+                       continue;
+               }
                if ((idx + 4) >= ARRAYSIZE(argv)) {
                        LOG_W("Number of arguments to '/usr/bin/newgidmap' too big");
                        return false;
@@ -138,6 +155,10 @@ static bool userGidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
 
        argv[idx] = NULL;
 
+       if (idx < 4) {
+               return true;
+       }
+
        if (subprocSystem(argv, environ) != 0) {
                LOG_E("'/usr/bin/newgidmap' failed");
                return false;
@@ -161,7 +182,10 @@ static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
        idx++;
 
        struct idmap_t *p;
-       TAILQ_FOREACH(p, &nsjconf->newuidmap, pointers) {
+       TAILQ_FOREACH(p, &nsjconf->uids, pointers) {
+               if (p->is_newidmap == false) {
+                       continue;
+               }
                if ((idx + 4) >= ARRAYSIZE(argv)) {
                        LOG_W("Number of arguments to '/usr/bin/newuidmap' too big");
                        return false;
@@ -182,6 +206,10 @@ static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
 
        argv[idx] = NULL;
 
+       if (idx < 4) {
+               return true;
+       }
+
        if (subprocSystem(argv, environ) != 0) {
                LOG_E("'/usr/bin/newuidmap' failed");
                return false;
@@ -192,20 +220,19 @@ static bool userUidMapExternal(struct nsjconf_t *nsjconf, pid_t pid UNUSED)
 
 static bool userUidGidMap(struct nsjconf_t *nsjconf, pid_t pid)
 {
-       if (TAILQ_EMPTY(&nsjconf->newgidmap)) {
-               if (!userGidMapSelf(nsjconf, pid)) {
-                       return false;
-               }
-       } else {
-               if (!userGidMapExternal(nsjconf, pid)) {
-                       return false;
-               }
+       if (!userGidMapSelf(nsjconf, pid)) {
+               return false;
        }
-       if (TAILQ_EMPTY(&nsjconf->newgidmap)) {
-               return userUidMapSelf(nsjconf, pid);
-       } else {
-               return userUidMapExternal(nsjconf, pid);
+       if (!userGidMapExternal(nsjconf, pid)) {
+               return false;
        }
+       if (!userUidMapSelf(nsjconf, pid)) {
+               return false;
+       }
+       if (!userUidMapExternal(nsjconf, pid)) {
+               return false;
+       }
+       return true;
 }
 
 bool userInitNsFromParent(struct nsjconf_t * nsjconf, pid_t pid)
@@ -284,7 +311,8 @@ static gid_t cmdParseGid(const char *id)
        return -1;
 }
 
-struct idmap_t *userParseId(const char *i_id, const char *o_id, size_t cnt, bool is_gid)
+bool userParseId(struct nsjconf_t * nsjconf, const char *i_id, const char *o_id, size_t cnt,
+                bool is_gid, bool is_newidmap)
 {
        uid_t inside_id;
        uid_t outside_id;
@@ -292,24 +320,24 @@ struct idmap_t *userParseId(const char *i_id, const char *o_id, size_t cnt, bool
        if (is_gid) {
                inside_id = cmdParseGid(i_id);
                if (inside_id == (uid_t) - 1) {
-                       LOG_E("Cannot parse '%s' as GID", i_id);
-                       return NULL;
+                       LOG_W("Cannot parse '%s' as GID", i_id);
+                       return false;
                }
                outside_id = cmdParseGid(o_id);
                if (inside_id == (uid_t) - 1) {
-                       LOG_E("Cannot parse '%s' as GID", o_id);
-                       return NULL;
+                       LOG_W("Cannot parse '%s' as GID", o_id);
+                       return false;
                }
        } else {
                inside_id = cmdParseUid(i_id);
                if (inside_id == (uid_t) - 1) {
-                       LOG_E("Cannot parse '%s' as UID", i_id);
-                       return NULL;
+                       LOG_W("Cannot parse '%s' as UID", i_id);
+                       return false;
                }
                outside_id = cmdParseUid(o_id);
                if (inside_id == (uid_t) - 1) {
-                       LOG_E("Cannot parse '%s' as UID", o_id);
-                       return NULL;
+                       LOG_W("Cannot parse '%s' as UID", o_id);
+                       return false;
                }
        }
 
@@ -317,5 +345,13 @@ struct idmap_t *userParseId(const char *i_id, const char *o_id, size_t cnt, bool
        p->inside_id = inside_id;
        p->outside_id = outside_id;
        p->count = cnt;
-       return p;
+       p->is_newidmap = is_newidmap;
+
+       if (is_gid) {
+               TAILQ_INSERT_TAIL(&nsjconf->gids, p, pointers);
+       } else {
+               TAILQ_INSERT_TAIL(&nsjconf->uids, p, pointers);
+       }
+
+       return true;
 }
diff --git a/user.h b/user.h
index ebca4593c2b6e6909e38a815a47720c082fe40b6..9f9f995811aa9af4d4badba36c0f79d6a6ca96a2 100644 (file)
--- a/user.h
+++ b/user.h
@@ -29,6 +29,7 @@
 bool userInitNsFromParent(struct nsjconf_t *nsjconf, pid_t pid);
 bool userInitNsFromChild(struct nsjconf_t *nsjconf);
 
-struct idmap_t *userParseId(const char *i_id, const char *o_id, size_t cnt, bool is_gid);
+bool userParseId(struct nsjconf_t *nsjconf, const char *i_id, const char *o_id, size_t cnt,
+                bool is_gid, bool is_newidmap);
 
 #endif                         /* NS_USER_H */