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 <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2018-01-02 23:41:10 +01:00
parent 46ad64ab26
commit 4160c3a088
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D
4 changed files with 57 additions and 26 deletions

View File

@ -1267,25 +1267,41 @@ next:
return r; 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) 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"); SYSERROR("Failed to setgid to 0");
if (setresuid(0,0,0) < 0) if (setresuid(nsuid, nsuid, nsuid) < 0)
SYSERROR("Failed to setuid to 0"); SYSERROR("Failed to setuid to 0");
if (setgroups(0, NULL) < 0) if (setgroups(0, NULL) < 0)
SYSERROR("Failed to clear groups"); SYSERROR("Failed to clear groups");
return cgroup_rmdir(path); return cgroup_rmdir(arg->path);
} }
void recursive_destroy(char *path, struct lxc_conf *conf) void recursive_destroy(char *path, struct lxc_conf *conf)
{ {
int r; 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)) 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 else
r = cgroup_rmdir(path); r = cgroup_rmdir(path);
@ -1445,11 +1461,6 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
return true; return true;
} }
struct chown_data {
struct cgfsng_handler_data *d;
uid_t origuid; /* target uid in parent namespace */
};
/* /*
* chgrp the container cgroups to container group. We leave * chgrp the container cgroups to container group. We leave
* the container owner as cgroup owner. So we must make the * the container owner as cgroup owner. So we must make the
@ -1460,13 +1471,15 @@ struct chown_data {
*/ */
static int chown_cgroup_wrapper(void *data) static int chown_cgroup_wrapper(void *data)
{ {
struct chown_data *arg = data;
uid_t destuid;
int i; 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"); SYSERROR("Failed to setgid to 0");
if (setresuid(0,0,0) < 0) if (setresuid(nsuid, nsuid, nsuid) < 0)
SYSERROR("Failed to setuid to 0"); SYSERROR("Failed to setuid to 0");
if (setgroups(0, NULL) < 0) if (setgroups(0, NULL) < 0)
SYSERROR("Failed to clear groups"); SYSERROR("Failed to clear groups");
@ -1476,7 +1489,7 @@ static int chown_cgroup_wrapper(void *data)
for (i = 0; hierarchies[i]; i++) { for (i = 0; hierarchies[i]; i++) {
char *fullpath, *path = hierarchies[i]->fullcgpath; 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); SYSERROR("Error chowning %s to %d", path, (int) destuid);
return -1; return -1;
} }
@ -1494,7 +1507,7 @@ static int chown_cgroup_wrapper(void *data)
* insists on doing) * insists on doing)
*/ */
fullpath = must_make_path(path, "tasks", NULL); 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, WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid,
strerror(errno)); strerror(errno));
if (chmod(fullpath, 0664) < 0) if (chmod(fullpath, 0664) < 0)
@ -1513,7 +1526,7 @@ static int chown_cgroup_wrapper(void *data)
continue; continue;
fullpath = must_make_path(path, "cgroup.subtree_control", NULL); 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, WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid,
strerror(errno)); strerror(errno));
if (chmod(fullpath, 0664) < 0) if (chmod(fullpath, 0664) < 0)
@ -1521,7 +1534,7 @@ static int chown_cgroup_wrapper(void *data)
free(fullpath); free(fullpath);
fullpath = must_make_path(path, "cgroup.threads", NULL); 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, WARN("Failed chowning %s to %d: %s", fullpath, (int) destuid,
strerror(errno)); strerror(errno));
if (chmod(fullpath, 0664) < 0) if (chmod(fullpath, 0664) < 0)
@ -1535,7 +1548,7 @@ static int chown_cgroup_wrapper(void *data)
static bool cgfsng_chown(void *hdata, struct lxc_conf *conf) static bool cgfsng_chown(void *hdata, struct lxc_conf *conf)
{ {
struct cgfsng_handler_data *d = hdata; struct cgfsng_handler_data *d = hdata;
struct chown_data wrap; struct generic_userns_exec_data wrap;
if (!d) if (!d)
return false; return false;
@ -1543,8 +1556,10 @@ static bool cgfsng_chown(void *hdata, struct lxc_conf *conf)
if (lxc_list_empty(&conf->id_map)) if (lxc_list_empty(&conf->id_map))
return true; return true;
wrap.d = d;
wrap.origuid = geteuid(); wrap.origuid = geteuid();
wrap.path = NULL;
wrap.d = d;
wrap.conf = conf;
if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap, if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap,
"chown_cgroup_wrapper") < 0) { "chown_cgroup_wrapper") < 0) {

View File

@ -2828,20 +2828,27 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
* Return true if id was found, false otherwise. * Return true if id was found, false otherwise.
*/ */
bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype,
unsigned long *val) unsigned long *val)
{ {
struct lxc_list *it; struct lxc_list *it;
struct id_map *map; 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) { lxc_list_for_each(it, &conf->id_map) {
map = it->elem; map = it->elem;
if (map->idtype != idtype) if (map->idtype != idtype)
continue; continue;
if (map->nsid != 0) if (map->nsid != nsid)
continue; continue;
*val = map->hostid; *val = map->hostid;
return true; return true;
} }
return false; return false;
} }
@ -3839,6 +3846,8 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
struct id_map *map; struct id_map *map;
char c = '1'; char c = '1';
int ret = -1, status = -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 lxc_list *idmap = NULL, *tmplist = NULL;
struct id_map *container_root_uid = NULL, *container_root_gid = NULL, struct id_map *container_root_uid = NULL, *container_root_gid = NULL,
*host_uid_map = NULL, *host_gid_map = NULL; *host_uid_map = NULL, *host_gid_map = NULL;
@ -3866,7 +3875,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
/* Find container root mappings. */ /* Find container root mappings. */
euid = geteuid(); 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) { if (!container_root_uid) {
DEBUG("Failed to find mapping for container root uid %d", 0); DEBUG("Failed to find mapping for container root uid %d", 0);
goto on_error; goto on_error;
@ -3875,7 +3884,7 @@ int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
host_uid_map = container_root_uid; host_uid_map = container_root_uid;
egid = getegid(); 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) { if (!container_root_gid) {
DEBUG("Failed to find mapping for container root gid %d", 0); DEBUG("Failed to find mapping for container root gid %d", 0);
goto on_error; goto on_error;

View File

@ -1687,7 +1687,7 @@ static int set_config_idmaps(const char *key, const char *value,
lxc_conf->root_nsuid_map = idmap; 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) if (idmap->nsid == 0)
lxc_conf->root_nsgid_map = idmap; lxc_conf->root_nsgid_map = idmap;

View File

@ -999,7 +999,14 @@ static int do_start(void *data)
* privilege over our namespace. * privilege over our namespace.
*/ */
if (!lxc_list_empty(&handler->conf->id_map)) { 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) if (ret < 0)
goto out_warn_father; goto out_warn_father;