Use --user x:y notation (not working yet)
authorJagger <robert@swiecki.net>
Sat, 23 Jan 2016 06:05:24 +0000 (07:05 +0100)
committerJagger <robert@swiecki.net>
Sat, 23 Jan 2016 06:05:24 +0000 (07:05 +0100)
cmdline.c
common.h
contain.c

index c73f06b1ed11786b6befe2fcdc0c2f61edcf7f14..e222ff32adb0c1ed9cfcbca6363d812ea247c70b 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -90,13 +90,14 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
 
        LOG_I
            ("Jail parameters: hostname:'%s', chroot:'%s', process:'%s', port:%d, "
-            "max_conns_per_ip:%u, uid:%u, gid:%u, time_limit:%ld, personality:%#lx, daemonize:%s, "
+            "max_conns_per_ip:%u, uid:(ns:%u, global:%u), gid:(ns:%u, global:%u), time_limit:%ld, personality:%#lx, daemonize:%s, "
             "clone_newnet:%s, clone_newuser:%s, clone_newns:%s, clone_newpid:%s, "
             "clone_newipc:%s, clonew_newuts:%s, apply_sandbox:%s, keep_caps:%s, "
             "tmpfs_size:%zu",
             nsjconf->hostname, nsjconf->chroot, nsjconf->argv[0], nsjconf->port,
-            nsjconf->max_conns_per_ip, nsjconf->uid, nsjconf->gid, nsjconf->tlimit,
-            nsjconf->personality, logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
+            nsjconf->max_conns_per_ip, nsjconf->inside_uid, nsjconf->outside_uid,
+            nsjconf->inside_gid, nsjconf->outside_gid, nsjconf->tlimit, nsjconf->personality,
+            logYesNo(nsjconf->daemonize), logYesNo(nsjconf->clone_newnet),
             logYesNo(nsjconf->clone_newuser), logYesNo(nsjconf->clone_newns),
             logYesNo(nsjconf->clone_newpid), logYesNo(nsjconf->clone_newipc),
             logYesNo(nsjconf->clone_newuts), logYesNo(nsjconf->apply_sandbox),
@@ -151,7 +152,7 @@ rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
 /* findSpecDestination mutates spec (source:dest) to have a null byte instead
  * of ':' in between source and dest, then returns a pointer to the dest
  * string. */
-static char *cmdlineMountParam(char *spec)
+static char *cmdlineSplitStrByColon(char *spec)
 {
        char *dest = spec;
        while (*dest != ':' && *dest != '\0') {
@@ -170,6 +171,74 @@ static char *cmdlineMountParam(char *spec)
        }
 }
 
+static bool cmdlineParseUid(struct nsjconf_t *nsjconf, char *str)
+{
+       if (str == NULL) {
+               return true;
+       }
+
+       char *second = cmdlineSplitStrByColon(str);
+
+       struct passwd *pw = getpwnam(str);
+       if (pw != NULL) {
+               nsjconf->inside_uid = pw->pw_uid;
+       } else if (cmdlineIsANumber(str)) {
+               nsjconf->inside_uid = (uid_t) strtoull(str, NULL, 0);
+       } else {
+               LOG_E("No such user '%s'", str);
+               return false;
+       }
+
+       if (str == second) {
+               return true;
+       }
+
+       pw = getpwnam(second);
+       if (pw != NULL) {
+               nsjconf->outside_uid = pw->pw_uid;
+       } else if (cmdlineIsANumber(second)) {
+               nsjconf->outside_uid = (uid_t) strtoull(second, NULL, 0);
+       } else {
+               LOG_E("No such user '%s'", second);
+               return false;
+       }
+       return true;
+}
+
+static bool cmdlineParseGid(struct nsjconf_t *nsjconf, char *str)
+{
+       if (str == NULL) {
+               return true;
+       }
+
+       char *second = cmdlineSplitStrByColon(str);
+
+       struct group *gr = getgrnam(str);
+       if (gr != NULL) {
+               nsjconf->inside_gid = gr->gr_gid;
+       } else if (cmdlineIsANumber(str)) {
+               nsjconf->inside_gid = (gid_t) strtoull(str, NULL, 0);
+       } else {
+               LOG_E("No such group '%s'", str);
+               return false;
+       }
+
+       if (str == second) {
+               return true;
+       }
+
+       gr = getgrnam(second);
+       if (gr != NULL) {
+               nsjconf->outside_gid = gr->gr_gid;
+       } else if (cmdlineIsANumber(second)) {
+               nsjconf->outside_gid = (gid_t) strtoull(second, NULL, 0);
+       } else {
+               LOG_E("No such group '%s'", second);
+               return false;
+       }
+       return true;
+}
+
 bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
 {
        /*  *INDENT-OFF* */
@@ -179,8 +248,6 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                .chroot = "",
                .argv = NULL,
                .port = 31337,
-               .uid = -1,
-               .gid = -1,
                .daemonize = false,
                .tlimit = 0,
                .apply_sandbox = true,
@@ -204,8 +271,10 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                .is_root_rw = false,
                .is_silent = false,
                .iface = NULL,
-               .initial_uid = getuid(),
-               .initial_gid = getgid(),
+               .inside_uid = getuid(),
+               .inside_gid = getgid(),
+               .outside_uid = getuid(),
+               .outside_gid = getgid(),
                .max_conns_per_ip = 0,
                .tmpfs_size = 4 * (1024 * 1024),
                .mount_proc = true,
@@ -215,8 +284,8 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
        TAILQ_INIT(&nsjconf->pids);
        TAILQ_INIT(&nsjconf->mountpts);
 
-       const char *user = "nobody";
-       const char *group = "nobody";
+       char *user = NULL;
+       char *group = NULL;
        const char *logfile = NULL;
        static char cmdlineTmpfsSz[PATH_MAX] = "size=4194304";
 
@@ -407,7 +476,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                        {
                                struct mounts_t *p = util_malloc(sizeof(struct mounts_t));
                                p->src = optarg;
-                               p->dst = cmdlineMountParam(optarg);
+                               p->dst = cmdlineSplitStrByColon(optarg);
                                p->flags = MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY;
                                p->options = NULL;
                                p->fs_type = NULL;
@@ -418,7 +487,7 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                        {
                                struct mounts_t *p = util_malloc(sizeof(struct mounts_t));
                                p->src = optarg;
-                               p->dst = cmdlineMountParam(optarg);
+                               p->dst = cmdlineSplitStrByColon(optarg);
                                p->flags = MS_BIND | MS_REC | MS_PRIVATE;
                                p->options = NULL;
                                p->fs_type = NULL;
@@ -496,29 +565,17 @@ bool cmdlineParse(int argc, char *argv[], struct nsjconf_t * nsjconf)
                return false;
        }
 
-       nsjconf->argv = &argv[optind];
-       if (nsjconf->argv[0] == NULL) {
-               LOG_E("No command provided");
-               cmdlineUsage(argv[0], custom_opts);
+       if (cmdlineParseUid(nsjconf, user) == false) {
                return false;
        }
-
-       struct passwd *pw = getpwnam(user);
-       if (pw != NULL) {
-               nsjconf->uid = pw->pw_uid;
-       } else if (cmdlineIsANumber(user)) {
-               nsjconf->uid = (uid_t) strtoull(user, NULL, 0);
-       } else {
-               LOG_E("No such user '%s'", user);
+       if (cmdlineParseGid(nsjconf, group) == false) {
                return false;
        }
-       struct group *gr = getgrnam(group);
-       if (gr != NULL) {
-               nsjconf->gid = gr->gr_gid;
-       } else if (cmdlineIsANumber(group)) {
-               nsjconf->gid = (gid_t) strtoull(group, NULL, 0);
-       } else {
-               LOG_E("No such group '%s'", group);
+
+       nsjconf->argv = &argv[optind];
+       if (nsjconf->argv[0] == NULL) {
+               LOG_E("No command provided");
+               cmdlineUsage(argv[0], custom_opts);
                return false;
        }
 
index 77bc96ac7bf67b0d5f465928153016f0a85566ad..65bf184ab6f38372a20c5e2c64e2c07121379cce 100644 (file)
--- a/common.h
+++ b/common.h
@@ -60,8 +60,6 @@ struct nsjconf_t {
        const char *cwd;
        char *const *argv;
        int port;
-       uid_t uid;
-       gid_t gid;
        bool daemonize;
        time_t tlimit;
        bool apply_sandbox;
@@ -87,8 +85,10 @@ struct nsjconf_t {
        bool is_root_rw;
        bool is_silent;
        char *iface;
-       uid_t initial_uid;
-       gid_t initial_gid;
+       uid_t outside_uid;
+       gid_t outside_gid;
+       uid_t inside_uid;
+       gid_t inside_gid;
        unsigned int max_conns_per_ip;
        size_t tmpfs_size;
        bool mount_proc;
index 223408eb3c3420d5ce50b539fc8b2d0330c2cb89..38a3c7d8624540a500def5dbde91342f3cd0254c 100644 (file)
--- a/contain.c
+++ b/contain.c
@@ -62,7 +62,7 @@ static bool containSetGroups(void)
        return true;
 }
 
-static bool containUidGidMap(struct nsjconf_t *nsjconf, uid_t uid, gid_t gid)
+static bool containUidGidMap(struct nsjconf_t *nsjconf)
 {
        if (nsjconf->clone_newuser == false) {
                return true;
@@ -74,8 +74,8 @@ static bool containUidGidMap(struct nsjconf_t *nsjconf, uid_t uid, gid_t gid)
                PLOG_E("open('/proc/self/uid_map', O_WRONLY | O_CLOEXEC)");
                return false;
        }
-       snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)uid,
-                (unsigned long)nsjconf->initial_uid);
+       snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_uid,
+                (unsigned long)nsjconf->outside_uid);
        LOG_D("Writing '%s' to /proc/self/uid_map", map);
        if (write(fd, map, strlen(map)) == -1) {
                PLOG_E("write('/proc/self/uid_map', %d, '%s')", fd, map);
@@ -88,8 +88,8 @@ static bool containUidGidMap(struct nsjconf_t *nsjconf, uid_t uid, gid_t gid)
                PLOG_E("open('/proc/self/gid_map', O_WRONLY | O_CLOEXEC)");
                return false;
        }
-       snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)gid,
-                (unsigned long)nsjconf->initial_gid);
+       snprintf(map, sizeof(map), "%lu %lu 1", (unsigned long)nsjconf->inside_gid,
+                (unsigned long)nsjconf->outside_gid);
        LOG_D("Writing '%s' to /proc/self/gid_map", map);
        if (write(fd, map, strlen(map)) == -1) {
                PLOG_E("write('/proc/self/gid_map', %d, '%s')", fd, map);
@@ -105,7 +105,7 @@ bool containInitUserNs(struct nsjconf_t * nsjconf)
        if (containSetGroups() == false) {
                return false;
        }
-       if (containUidGidMap(nsjconf, nsjconf->uid, nsjconf->gid) == false) {
+       if (containUidGidMap(nsjconf) == false) {
                return false;
        }
        return true;
@@ -120,12 +120,12 @@ bool containDropPrivs(struct nsjconf_t * nsjconf)
        if (setgroups(0, group_list) == -1) {
                PLOG_D("setgroups(NULL) failed");
        }
-       if (setresgid(nsjconf->gid, nsjconf->gid, nsjconf->gid) == -1) {
-               PLOG_E("setresgid(%u)", nsjconf->gid);
+       if (setresgid(nsjconf->inside_gid, nsjconf->inside_gid, nsjconf->inside_gid) == -1) {
+               PLOG_E("setresgid(%u)", nsjconf->inside_gid);
                return false;
        }
-       if (setresuid(nsjconf->uid, nsjconf->uid, nsjconf->uid) == -1) {
-               PLOG_E("setresuid(%u)", nsjconf->uid);
+       if (setresuid(nsjconf->inside_uid, nsjconf->inside_uid, nsjconf->inside_uid) == -1) {
+               PLOG_E("setresuid(%u)", nsjconf->inside_uid);
                return false;
        }
 #ifndef PR_SET_NO_NEW_PRIVS