From: Christian Brauner Date: Tue, 2 Jan 2018 22:41:10 +0000 (+0100) Subject: cgfsng: use init {g,u}id X-Git-Tag: lxc-2.0.10~435 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=864b0618cbeef0d1307f91cc6c6fe13c42f33849;p=thirdparty%2Flxc.git cgfsng: use init {g,u}id If no id mapping for the container's root id is defined try to us the id mappings specified via lxc.init.{g,u}id. Closes #2033. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c index 26c25a214..c0367ee85 100644 --- a/src/lxc/cgroups/cgfsng.c +++ b/src/lxc/cgroups/cgfsng.c @@ -1244,25 +1244,41 @@ next: return r; } +struct generic_userns_exec_data { + struct cgfsng_handler_data *d; + struct lxc_conf *conf; + uid_t origuid; /* target uid in parent namespace */ + char *path; +}; + static int rmdir_wrapper(void *data) { - char *path = data; + struct generic_userns_exec_data *arg = data; + uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid; + gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid; - if (setresgid(0,0,0) < 0) + if (setresgid(nsgid, nsgid, nsgid) < 0) SYSERROR("Failed to setgid to 0"); - if (setresuid(0,0,0) < 0) + if (setresuid(nsuid, nsuid, nsuid) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); - return cgroup_rmdir(path); + return cgroup_rmdir(arg->path); } void recursive_destroy(char *path, struct lxc_conf *conf) { int r; + struct generic_userns_exec_data wrap; + + wrap.origuid = 0; + wrap.d = NULL; + wrap.path = path; + wrap.conf = conf; + if (conf && !lxc_list_empty(&conf->id_map)) - r = userns_exec_1(conf, rmdir_wrapper, path, "rmdir_wrapper"); + r = userns_exec_1(conf, rmdir_wrapper, &wrap, "rmdir_wrapper"); else r = cgroup_rmdir(path); @@ -1433,13 +1449,15 @@ struct chown_data { */ static int chown_cgroup_wrapper(void *data) { - struct chown_data *arg = data; - uid_t destuid; int i; + uid_t destuid; + struct generic_userns_exec_data *arg = data; + uid_t nsuid = (arg->conf->root_nsuid_map != NULL) ? 0 : arg->conf->init_uid; + gid_t nsgid = (arg->conf->root_nsgid_map != NULL) ? 0 : arg->conf->init_gid; - if (setresgid(0,0,0) < 0) + if (setresgid(nsgid, nsgid, nsgid) < 0) SYSERROR("Failed to setgid to 0"); - if (setresuid(0,0,0) < 0) + if (setresuid(nsuid, nsuid, nsuid) < 0) SYSERROR("Failed to setuid to 0"); if (setgroups(0, NULL) < 0) SYSERROR("Failed to clear groups"); @@ -1449,7 +1467,7 @@ static int chown_cgroup_wrapper(void *data) for (i = 0; hierarchies[i]; i++) { char *fullpath, *path = hierarchies[i]->fullcgpath; - if (chown(path, destuid, 0) < 0) { + if (chown(path, destuid, nsgid) < 0) { SYSERROR("Error chowning %s to %d", path, (int) destuid); return -1; } @@ -1467,7 +1485,7 @@ static int chown_cgroup_wrapper(void *data) * insists on doing) */ fullpath = must_make_path(path, "tasks", NULL); - if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT) + if (chown(fullpath, destuid, nsgid) < 0 && errno != ENOENT) WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid, strerror(errno)); if (chmod(fullpath, 0664) < 0) @@ -1486,7 +1504,7 @@ static int chown_cgroup_wrapper(void *data) continue; fullpath = must_make_path(path, "cgroup.subtree_control", NULL); - if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT) + if (chown(fullpath, destuid, nsgid) < 0 && errno != ENOENT) WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid, strerror(errno)); if (chmod(fullpath, 0664) < 0) @@ -1494,7 +1512,7 @@ static int chown_cgroup_wrapper(void *data) free(fullpath); fullpath = must_make_path(path, "cgroup.threads", NULL); - if (chown(fullpath, destuid, 0) < 0 && errno != ENOENT) + if (chown(fullpath, destuid, nsgid) < 0 && errno != ENOENT) WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid, strerror(errno)); if (chmod(fullpath, 0664) < 0) @@ -1508,7 +1526,7 @@ static int chown_cgroup_wrapper(void *data) static bool cgfsng_chown(void *hdata, struct lxc_conf *conf) { struct cgfsng_handler_data *d = hdata; - struct chown_data wrap; + struct generic_userns_exec_data wrap; if (!d) return false; @@ -1516,8 +1534,10 @@ static bool cgfsng_chown(void *hdata, struct lxc_conf *conf) if (lxc_list_empty(&conf->id_map)) return true; - wrap.d = d; wrap.origuid = geteuid(); + wrap.path = NULL; + wrap.d = d; + wrap.conf = conf; if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap, "chown_cgroup_wrapper") < 0) { diff --git a/src/lxc/conf.c b/src/lxc/conf.c index e4411d9b9..834e78986 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2576,20 +2576,27 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid) * Return true if id was found, false otherwise. */ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, - unsigned long *val) + unsigned long *val) { struct lxc_list *it; struct id_map *map; + unsigned nsid; + + if (idtype == ID_TYPE_UID) + nsid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid; + else + nsid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid; lxc_list_for_each(it, &conf->id_map) { map = it->elem; if (map->idtype != idtype) continue; - if (map->nsid != 0) + if (map->nsid != nsid) continue; *val = map->hostid; return true; } + return false; } @@ -3591,6 +3598,8 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, struct id_map *map; char c = '1'; int ret = -1, status = -1; + uid_t nsuid = (conf->root_nsuid_map != NULL) ? 0 : conf->init_uid; + gid_t nsgid = (conf->root_nsgid_map != NULL) ? 0 : conf->init_gid; struct lxc_list *idmap = NULL, *tmplist = NULL; struct id_map *container_root_uid = NULL, *container_root_gid = NULL, *host_uid_map = NULL, *host_gid_map = NULL; @@ -3618,7 +3627,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, /* Find container root mappings. */ euid = geteuid(); - container_root_uid = mapped_nsid_add(conf, 0, ID_TYPE_UID); + container_root_uid = mapped_nsid_add(conf, nsuid, ID_TYPE_UID); if (!container_root_uid) { DEBUG("Failed to find mapping for container root uid %d", 0); goto on_error; @@ -3627,7 +3636,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data, host_uid_map = container_root_uid; egid = getegid(); - container_root_gid = mapped_nsid_add(conf, 0, ID_TYPE_GID); + container_root_gid = mapped_nsid_add(conf, nsgid, ID_TYPE_GID); if (!container_root_gid) { DEBUG("Failed to find mapping for container root gid %d", 0); goto on_error; diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 77f06edc7..ccd45a2fa 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -1877,7 +1877,7 @@ static int set_config_idmaps(const char *key, const char *value, lxc_conf->root_nsuid_map = idmap; - if (!lxc_conf->root_nsuid_map && idmap->idtype == ID_TYPE_GID) + if (!lxc_conf->root_nsgid_map && idmap->idtype == ID_TYPE_GID) if (idmap->nsid == 0) lxc_conf->root_nsgid_map = idmap; diff --git a/src/lxc/start.c b/src/lxc/start.c index f362fa575..2494c49c2 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -1041,7 +1041,14 @@ static int do_start(void *data) * privilege over our namespace. */ if (!lxc_list_empty(&handler->conf->id_map)) { - ret = lxc_switch_uid_gid(0, 0); + uid_t nsuid = (handler->conf->root_nsuid_map != NULL) + ? 0 + : handler->conf->init_uid; + gid_t nsgid = (handler->conf->root_nsgid_map != NULL) + ? 0 + : handler->conf->init_gid; + + ret = lxc_switch_uid_gid(nsuid, nsgid); if (ret < 0) goto out_warn_father;