From: Christian Brauner Date: Wed, 10 Jun 2020 21:33:59 +0000 (+0200) Subject: conf: kill old chown_mapped_root() X-Git-Tag: lxc-5.0.0~419^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e1a327abaa91d6d0219cedfb0d7fd053ececdb2;p=thirdparty%2Flxc.git conf: kill old chown_mapped_root() It's now a wrapper around userns_exec_mapped_root() which allows us to avoid fork() + exec() lxc-usernsexec makes things way nicer to test with ASAN etc. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 52a8f4399..428d06a2b 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2896,127 +2896,6 @@ again: return freeid; } -int chown_mapped_root_exec_wrapper(void *args) -{ - execvp("lxc-usernsexec", args); - return -1; -} - -/* chown_mapped_root: for an unprivileged user with uid/gid X to - * chown a dir to subuid/subgid Y, he needs to run chown as root - * in a userns where nsid 0 is mapped to hostuid/hostgid Y, and - * nsid Y is mapped to hostuid/hostgid X. That way, the container - * root is privileged with respect to hostuid/hostgid X, allowing - * him to do the chown. - */ -int chown_mapped_root(const char *path, const struct lxc_conf *conf) -{ - uid_t rootuid, rootgid; - int hostuid, hostgid, ret; - struct stat sb; - char map1[100], map2[100], map3[100], map4[100], map5[100]; - char ugid[100]; - const char *args1[] = {"lxc-usernsexec", - "-m", map1, - "-m", map2, - "-m", map3, - "-m", map5, - "--", "chown", ugid, path, - NULL}; - const char *args2[] = {"lxc-usernsexec", - "-m", map1, - "-m", map2, - "-m", map3, - "-m", map4, - "-m", map5, - "--", "chown", ugid, path, - NULL}; - char cmd_output[PATH_MAX]; - - rootuid = get_mapped_rootid(conf, ID_TYPE_UID); - if (!uid_valid(rootuid)) - return log_error(-1, "No uid mapping for container root"); - - rootgid = get_mapped_rootid(conf, ID_TYPE_GID); - if (!gid_valid(rootgid)) - return log_error(-1, "No gid mapping for container root"); - - hostuid = geteuid(); - if (hostuid == 0) { - if (chown(path, rootuid, rootgid) < 0) - return log_error(-1, "Error chowning %s", path); - - return 0; - } - - /* nothing to do */ - if (rootuid == hostuid) - return log_info(0, "Container root is our uid; no need to chown"); - - /* save the current gid of "path" */ - if (stat(path, &sb) < 0) - return log_error(-1, "Error stat %s", path); - - /* Update the path argument in case this was overlayfs. */ - args1[sizeof(args1) / sizeof(args1[0]) - 2] = path; - args2[sizeof(args2) / sizeof(args2[0]) - 2] = path; - - /* - * A file has to be group-owned by a gid mapped into the - * container, or the container won't be privileged over it. - */ - hostgid = getegid(); - DEBUG("trying to chown \"%s\" to %d", path, hostgid); - if (sb.st_uid == hostuid && - mapped_hostid(sb.st_gid, conf, ID_TYPE_GID) < 0 && - chown(path, -1, hostgid) < 0) - return log_error(-1, "Failed chgrping %s", path); - - /* "u:0:rootuid:1" */ - ret = snprintf(map1, 100, "u:0:%d:1", rootuid); - if (ret < 0 || ret >= 100) - return log_error(-1, "Error uid printing map string"); - - /* "u:hostuid:hostuid:1" */ - ret = snprintf(map2, 100, "u:%d:%d:1", hostuid, hostuid); - if (ret < 0 || ret >= 100) - return log_error(-1, "Error uid printing map string"); - - /* "g:0:rootgid:1" */ - ret = snprintf(map3, 100, "g:0:%d:1", rootgid); - if (ret < 0 || ret >= 100) - return log_error(-1, "Error gid printing map string"); - - /* "g:pathgid:rootgid+pathgid:1" */ - ret = snprintf(map4, 100, "g:%d:%d:1", (gid_t)sb.st_gid, - rootgid + (gid_t)sb.st_gid); - if (ret < 0 || ret >= 100) - return log_error(-1, "Error gid printing map string"); - - /* "g:hostgid:hostgid:1" */ - ret = snprintf(map5, 100, "g:%d:%d:1", hostgid, hostgid); - if (ret < 0 || ret >= 100) - return log_error(-1, "Error gid printing map string"); - - /* "0:pathgid" (chown) */ - ret = snprintf(ugid, 100, "0:%d", (gid_t)sb.st_gid); - if (ret < 0 || ret >= 100) - return log_error(-1, "Error owner printing format string for chown"); - - if (hostgid == sb.st_gid) - ret = run_command(cmd_output, sizeof(cmd_output), - chown_mapped_root_exec_wrapper, - (void *)args1); - else - ret = run_command(cmd_output, sizeof(cmd_output), - chown_mapped_root_exec_wrapper, - (void *)args2); - if (ret < 0) - ERROR("lxc-usernsexec failed: %s", cmd_output); - - return ret; -} - /* NOTE: Must not be called from inside the container namespace! */ int lxc_create_tmp_proc_mount(struct lxc_conf *conf) { diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 63d6e8cfb..17cec5d59 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -443,7 +443,6 @@ extern int setup_resource_limits(struct lxc_list *limits, pid_t pid); extern int find_unmapped_nsid(const struct lxc_conf *conf, enum idtype idtype); extern int mapped_hostid(unsigned id, const struct lxc_conf *conf, enum idtype idtype); -extern int chown_mapped_root(const char *path, const struct lxc_conf *conf); extern int userns_exec_1(const struct lxc_conf *conf, int (*fn)(void *), void *data, const char *fn_name); extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), @@ -476,5 +475,9 @@ extern int userns_exec_minimal(const struct lxc_conf *conf, int (*fn_child)(void *), void *fn_child_data); extern int userns_exec_mapped_root(const char *path, int path_fd, const struct lxc_conf *conf); +static inline int chown_mapped_root(const char *path, const struct lxc_conf *conf) +{ + return userns_exec_mapped_root(path, -EBADF, conf); +} #endif /* __LXC_CONF_H */