From: Serge Hallyn Date: Tue, 4 Feb 2014 19:33:10 +0000 (-0600) Subject: create: pass --mapped-gid to templates next to --mapped-uid X-Git-Tag: lxc-1.0.0.beta4~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2133f58c66ab7627a4159fafbb75106c556b014d;p=thirdparty%2Flxc.git create: pass --mapped-gid to templates next to --mapped-uid That way templates can fix group ownership alongside uid ownership. Signed-off-by: Serge Hallyn Acked-by: Stéphane Graber --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index d4578f349..fed532737 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3177,13 +3177,13 @@ bool get_mapped_rootid(struct lxc_conf *conf, enum idtype idtype, return false; } -int mapped_hostid(int id, struct lxc_conf *conf) +int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype) { struct lxc_list *it; struct id_map *map; lxc_list_for_each(it, &conf->id_map) { map = it->elem; - if (map->idtype != ID_TYPE_UID) + if (map->idtype != idtype) continue; if (id >= map->hostid && id < map->hostid + map->range) return (id - map->hostid) + map->nsid; @@ -3191,15 +3191,15 @@ int mapped_hostid(int id, struct lxc_conf *conf) return -1; } -int find_unmapped_nsuid(struct lxc_conf *conf) +int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype) { struct lxc_list *it; struct id_map *map; - uid_t freeid = 0; + unsigned int freeid = 0; again: lxc_list_for_each(it, &conf->id_map) { map = it->elem; - if (map->idtype != ID_TYPE_UID) + if (map->idtype != idtype) continue; if (freeid >= map->nsid && freeid < map->nsid + map->range) { freeid = map->nsid + map->range; @@ -3992,7 +3992,7 @@ static int run_userns_fn(void *data) */ static struct lxc_list *idmap_add_id(struct lxc_conf *conf, uid_t uid) { - int hostid_mapped = mapped_hostid(uid, conf); + int hostid_mapped = mapped_hostid(uid, conf, ID_TYPE_UID); struct lxc_list *new = NULL, *tmp, *it, *next; struct id_map *entry; @@ -4004,7 +4004,7 @@ static struct lxc_list *idmap_add_id(struct lxc_conf *conf, uid_t uid) lxc_list_init(new); if (hostid_mapped < 0) { - hostid_mapped = find_unmapped_nsuid(conf); + hostid_mapped = find_unmapped_nsuid(conf, ID_TYPE_UID); if (hostid_mapped < 0) goto err; tmp = malloc(sizeof(*tmp)); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index e5a23ec44..16d712242 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -371,8 +371,8 @@ extern int lxc_setup(struct lxc_handler *handler); extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf); -extern int find_unmapped_nsuid(struct lxc_conf *conf); -extern int mapped_hostid(int id, struct lxc_conf *conf); +extern int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype); +extern int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype); extern int chown_mapped_root(char *path, struct lxc_conf *conf); extern int ttys_shift_ids(struct lxc_conf *c); extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data); diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 85c644afb..7d3ebdb28 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -977,6 +977,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet if (geteuid() != 0 && !lxc_list_empty(&conf->id_map)) { int n2args = 1; char txtuid[20]; + char txtgid[20]; char **n2 = malloc(n2args * sizeof(*n2)); struct lxc_list *it; struct id_map *map; @@ -1004,13 +1005,13 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet if (ret < 0 || ret >= 200) exit(1); } - int hostid_mapped = mapped_hostid(geteuid(), conf); + int hostid_mapped = mapped_hostid(geteuid(), conf, ID_TYPE_UID); int extraargs = hostid_mapped >= 0 ? 1 : 3; n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *)); if (!n2) exit(1); if (hostid_mapped < 0) { - hostid_mapped = find_unmapped_nsuid(conf); + hostid_mapped = find_unmapped_nsuid(conf, ID_TYPE_UID); n2[n2args++] = "-m"; if (hostid_mapped < 0) { ERROR("Could not find free uid to map"); @@ -1028,22 +1029,49 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet exit(1); } } + int hostgid_mapped = mapped_hostid(getegid(), conf, ID_TYPE_GID); + extraargs = hostgid_mapped >= 0 ? 1 : 3; + n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *)); + if (!n2) + exit(1); + if (hostgid_mapped < 0) { + hostgid_mapped = find_unmapped_nsuid(conf, ID_TYPE_GID); + n2[n2args++] = "-m"; + if (hostgid_mapped < 0) { + ERROR("Could not find free uid to map"); + exit(1); + } + n2[n2args++] = malloc(200); + if (!n2[n2args-1]) { + SYSERROR("out of memory"); + exit(1); + } + ret = snprintf(n2[n2args-1], 200, "g:%d:%d:1", + hostgid_mapped, getegid()); + if (ret < 0 || ret >= 200) { + ERROR("string too long"); + exit(1); + } + } n2[n2args++] = "--"; for (i = 0; i < nargs; i++) n2[i + n2args] = newargv[i]; n2args += nargs; // Finally add "--mapped-uid $uid" to tell template what to chown // cached images to - n2args += 2; + n2args += 4; n2 = realloc(n2, n2args * sizeof(char *)); if (!n2) { SYSERROR("out of memory"); exit(1); } // note n2[n2args-1] is NULL - n2[n2args-3] = "--mapped-uid"; + n2[n2args-5] = "--mapped-uid"; snprintf(txtuid, 20, "%d", hostid_mapped); - n2[n2args-2] = txtuid; + n2[n2args-4] = txtuid; + n2[n2args-3] = "--mapped-gid"; + snprintf(txtgid, 20, "%d", hostgid_mapped); + n2[n2args-2] = txtgid; n2[n2args-1] = NULL; free(newargv); newargv = n2; diff --git a/templates/lxc-download.in b/templates/lxc-download.in index 3ef9fba82..2a6e51d26 100644 --- a/templates/lxc-download.in +++ b/templates/lxc-download.in @@ -51,6 +51,7 @@ LXC_NAME= LXC_PATH= LXC_ROOTFS= LXC_MAPPED_UID= +LXC_MAPPED_GID= # Some useful functions cleanup() { @@ -175,14 +176,15 @@ LXC internal arguments (do not pass manually!): [ --name ]: The container name [ --path ]: The path to the container [ --rootfs ]: The path to the container's rootfs -[ --mapped-uid ]: A uid/gid map (user namespaces) +[ --mapped-uid ]: A uid map (user namespaces) +[ --mapped-gid ]: A gid map (user namespaces) EOF return 0 } options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\ server:,keyid:,no-validate,flush-cache,force-cache,name:,path:,\ -rootfs:,mapped-uid: -- "$@") +rootfs:,mapped-uid:,mapped-gid: -- "$@") if [ $? -ne 0 ]; then usage @@ -207,6 +209,7 @@ while :; do --path) LXC_PATH=$2; shift 2;; --rootfs) LXC_ROOTFS=$2; shift 2;; --mapped-uid) LXC_MAPPED_UID=$2; shift 2;; + --mapped-gid) LXC_MAPPED_GID=$2; shift 2;; *) break;; esac done @@ -434,6 +437,9 @@ if [ "$DOWNLOAD_USE_CACHE" = "false" ]; then if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then chown -R $LXC_MAPPED_UID $LXC_CACHE_BASE >/dev/null 2>&1 || true fi + if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then + chgrp -R $LXC_MAPPED_GID $LXC_CACHE_BASE >/dev/null 2>&1 || true + fi echo "The image cache is now ready" fi else @@ -527,6 +533,9 @@ done if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then chown $LXC_MAPPED_UID $LXC_PATH/config $LXC_PATH/fstab >/dev/null 2>&1 || true fi +if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then + chgrp $LXC_MAPPED_GID $LXC_PATH/config $LXC_PATH/fstab >/dev/null 2>&1 || true +fi if [ -e "$(relevant_file create-message)" ]; then echo "" diff --git a/templates/lxc-ubuntu-cloud.in b/templates/lxc-ubuntu-cloud.in index c0566e84d..07cb87d9b 100644 --- a/templates/lxc-ubuntu-cloud.in +++ b/templates/lxc-ubuntu-cloud.in @@ -147,7 +147,7 @@ EOF return 0 } -options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,mapped-uid: -- "$@") +options=$(getopt -o a:hp:r:n:Fi:CLS:T:ds:u: -l arch:,help,rootfs:,path:,release:,name:,flush-cache,hostid:,auth-key:,cloud,no_locales,tarball:,debug,stream:,userdata:,mapped-uid:,mapped-gid: -- "$@") if [ $? -ne 0 ]; then usage $(basename $0) exit 1 @@ -155,6 +155,7 @@ fi eval set -- "$options" mapped_uid=-1 +mapped_gid=-1 # default release is precise, or the systems release if recognized release=precise if [ -f /etc/lsb-release ]; then @@ -216,12 +217,12 @@ do -C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;; -S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;; --mapped-uid) mapped_uid=$2; shift 2;; + --mapped-gid) mapped_gid=$2; shift 2;; --) shift 1; break ;; *) break ;; esac done -echo "mapped_uid is .$mapped_uid." cloneargs=( "--name=$name" "${cloneargs[@]}" ) if [ $debug -eq 1 ]; then @@ -390,6 +391,11 @@ if [ $mapped_uid -ne -1 ]; then chown -R $mapped_uid $STATE_DIR chown -R $mapped_uid $cache fi +if [ $mapped_gid -ne -1 ]; then + chgrp $mapped_gid $path/config + chgrp -R $mapped_gid $STATE_DIR + chgrp -R $mapped_gid $cache +fi echo "Container $name created." exit 0