[lxc-devel] [RFC 1/2] create_run_template: tell the template what caller's uid was mapped to
Serge Hallyn
serge.hallyn at ubuntu.com
Tue Nov 5 20:58:27 UTC 2013
Quoting Stéphane Graber (stgraber at ubuntu.com):
> On Tue, Nov 05, 2013 at 02:14:33PM -0600, Serge Hallyn wrote:
> > conf.c/conf.h: have replaced bool hostid_is_mapped() with int mapped_hostid()
> > which returns the mapped uid for the caller's uid on the host, or -1 if
> > none
> >
> > create_run_template: pass caller's uid into template.
> >
> > lxc-ubuntu-cloud:
> > 1. accept --mapped-uid argument
> > 2. don't write to devices cgroup - not allowed.
> > 3. if running in userns, use $HOME/.cache
> > 4. chown cached files to the uid to which our caller was
> > mapped
> > 5. ignore /dev when extracting rootfs in a userns
> >
> > Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
>
> There is just one info statement that looks a bit off a bit below, but
> with that one dropped or properly indented:
>
> Acked-by: Stéphane Graber <stgraber at ubuntu.com>
>
> > ---
> > src/lxc/conf.c | 6 +++---
> > src/lxc/conf.h | 2 +-
> > src/lxc/lxccontainer.c | 38 ++++++++++++++++++++++++++++++--------
> > templates/lxc-ubuntu-cloud.in | 25 +++++++++++++++++++++++--
> > 4 files changed, 57 insertions(+), 14 deletions(-)
> >
> > diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> > index 2a47e77..afdaa14 100644
> > --- a/src/lxc/conf.c
> > +++ b/src/lxc/conf.c
> > @@ -2912,7 +2912,7 @@ uid_t get_mapped_rootid(struct lxc_conf *conf)
> > return (uid_t)-1;
> > }
> >
> > -bool hostid_is_mapped(int id, struct lxc_conf *conf)
> > +int mapped_hostid(int id, struct lxc_conf *conf)
> > {
> > struct lxc_list *it;
> > struct id_map *map;
> > @@ -2921,9 +2921,9 @@ bool hostid_is_mapped(int id, struct lxc_conf *conf)
> > if (map->idtype != ID_TYPE_UID)
> > continue;
> > if (id >= map->hostid && id < map->hostid + map->range)
> > - return true;
> > + return (id - map->hostid) + map->nsid;
> > }
> > - return false;
> > + return -1;
> > }
> >
> > int find_unmapped_nsuid(struct lxc_conf *conf)
> > diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> > index 71399b9..940d493 100644
> > --- a/src/lxc/conf.h
> > +++ b/src/lxc/conf.h
> > @@ -362,7 +362,7 @@ extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf);
> >
> > extern uid_t get_mapped_rootid(struct lxc_conf *conf);
> > extern int find_unmapped_nsuid(struct lxc_conf *conf);
> > -extern bool hostid_is_mapped(int id, struct lxc_conf *conf);
> > +extern int mapped_hostid(int id, struct lxc_conf *conf);
> > extern int chown_mapped_root(char *path, struct lxc_conf *conf);
> > extern int ttys_shift_ids(struct lxc_conf *c);
> > #endif
> > diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> > index 946133d..594a96d 100644
> > --- a/src/lxc/lxccontainer.c
> > +++ b/src/lxc/lxccontainer.c
> > @@ -916,20 +916,28 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> > * If we're running the template in a mapped userns, then
> > * we prepend the template command with:
> > * lxc-usernsexec <-m map1> ... <-m mapn> --
> > + * and we append "--mapped-uid x", where x is the mapped uid
> > + * for our geteuid()
> > */
> > if (geteuid() != 0 && !lxc_list_empty(&conf->id_map)) {
> > int n2args = 1;
> > + char txtuid[20];
> > char **n2 = malloc(n2args * sizeof(*n2));
> > struct lxc_list *it;
> > struct id_map *map;
> >
> > + if (!n2) {
> > + SYSERROR("out of memory");
> > + exit(1);
> > + }
> > newargv[0] = tpath;
> > tpath = "lxc-usernsexec";
> > n2[0] = "lxc-usernsexec";
> > lxc_list_for_each(it, &conf->id_map) {
> > map = it->elem;
> > n2args += 2;
> > - n2 = realloc(n2, n2args * sizeof(*n2));
> > + n2 = realloc(n2, n2args * sizeof(char *));
> > +INFO("allocated %d items to n2", n2args);
>
> ^ what happened with indentation here?
Good question. That was for debugging - I'll dd it, thanks.
> > if (!n2)
> > exit(1);
> > n2[n2args-2] = "-m";
> > @@ -942,15 +950,15 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> > if (ret < 0 || ret >= 200)
> > exit(1);
> > }
> > - bool hostid_mapped = hostid_is_mapped(geteuid(), conf);
> > - int extraargs = hostid_mapped ? 1 : 3;
> > - n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(*n2));
> > + int hostid_mapped = mapped_hostid(geteuid(), conf);
> > + int extraargs = hostid_mapped >= 0 ? 1 : 3;
> > + n2 = realloc(n2, (nargs + n2args + extraargs) * sizeof(char *));
> > if (!n2)
> > exit(1);
> > - if (!hostid_mapped) {
> > - int free_id = find_unmapped_nsuid(conf);
> > + if (hostid_mapped < 0) {
> > + hostid_mapped = find_unmapped_nsuid(conf);
> > n2[n2args++] = "-m";
> > - if (free_id < 0) {
> > + if (hostid_mapped < 0) {
> > ERROR("Could not find free uid to map");
> > exit(1);
> > }
> > @@ -960,7 +968,7 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> > exit(1);
> > }
> > ret = snprintf(n2[n2args-1], 200, "u:%d:%d:1",
> > - free_id, geteuid());
> > + hostid_mapped, geteuid());
> > if (ret < 0 || ret >= 200) {
> > ERROR("string too long");
> > exit(1);
> > @@ -969,6 +977,20 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
> > 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;
> > + 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";
> > + snprintf(txtuid, 20, "%d", hostid_mapped);
> > + n2[n2args-2] = txtuid;
> > + n2[n2args-1] = NULL;
> > free(newargv);
> > newargv = n2;
> > }
> > diff --git a/templates/lxc-ubuntu-cloud.in b/templates/lxc-ubuntu-cloud.in
> > index 82a7f74..41f1c70 100644
> > --- a/templates/lxc-ubuntu-cloud.in
> > +++ b/templates/lxc-ubuntu-cloud.in
> > @@ -80,7 +80,11 @@ lxc.cap.drop = sys_module mac_admin mac_override sys_time
> > #lxc.hook.mount = /usr/share/lxc/hooks/mountcgroups
> >
> > lxc.hook.clone = ${CLONE_HOOK_FN}
> > +EOF
> >
> > + # can't write to devices.deny without CAP_SYS_ADMIN in init-user-ns
> > + if [ $in_userns -ne 1 ]; then
> > + cat <<EOF >> $path/config
> > lxc.cgroup.devices.deny = a
> > # Allow any mknod (but not using the node)
> > lxc.cgroup.devices.allow = c *:* m
> > @@ -109,6 +113,7 @@ lxc.cgroup.devices.allow = c 10:228 rwm
> > # kvm
> > lxc.cgroup.devices.allow = c 10:232 rwm
> > EOF
> > + fi
> >
> > cat <<EOF > $path/fstab
> > proc proc proc nodev,noexec,nosuid 0 0
> > @@ -123,6 +128,7 @@ EOF
> > # that in the kernel, but not right now. So let's just bind
> > # mount the files from the host.
> > if [ $in_userns -eq 1 ]; then
> > + mkdir -p $rootfs/dev/pts
> > for dev in null tty urandom console; do
> > touch $rootfs/dev/$dev
> > echo "/dev/$dev dev/$dev none bind 0 0" >> $path/fstab
> > @@ -161,13 +167,14 @@ 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: -- "$@")
> > +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: -- "$@")
> > if [ $? -ne 0 ]; then
> > usage $(basename $0)
> > exit 1
> > fi
> > eval set -- "$options"
> >
> > +mapped_uid=-1
> > # default release is precise, or the systems release if recognized
> > release=precise
> > if [ -f /etc/lsb-release ]; then
> > @@ -224,11 +231,13 @@ do
> > -u|--userdata) cloneargs[${#cloneargs[@]}]="--userdata=$2"; shift 2;;
> > -C|--cloud) cloneargs[${#cloneargs[@]}]="--cloud"; shift 1;;
> > -S|--auth-key) cloneargs[${#cloneargs[@]}]="--auth-key=$2"; shift 2;;
> > + --mapped-uid) mapped_uid=$2; shift 2;;
> > --) shift 1; break ;;
> > *) break ;;
> > esac
> > done
> >
> > +echo "mapped_uid is .$mapped_uid."
> > cloneargs=( "--name=$name" "${cloneargs[@]}" )
> >
> > if [ $debug -eq 1 ]; then
> > @@ -296,6 +305,8 @@ type wget
> > # determine the url, tarball, and directory names
> > # download if needed
> > cache="$STATE_DIR/cache/lxc/cloud-$release"
> > +STATE_DIR="$HOME/.cache/lxc/"
> > +cache="$HOME/.cache/lxc/cloud-$release"
> >
> > mkdir -p $cache
> >
> > @@ -371,7 +382,11 @@ do_extract_rootfs() {
> > echo "Extracting container rootfs"
> > mkdir -p $rootfs
> > cd $rootfs
> > - tar --numeric-owner -xpzf "$cache/$filename"
> > + if [ $in_userns -eq 1 ]; then
> > + tar --anchored --exclude="dev/*" --numeric-owner -xpzf "$cache/$filename"
> > + else
> > + tar --numeric-owner -xpzf "$cache/$filename"
> > + fi
> > }
> >
> > if [ -n "$tarball" ]; then
> > @@ -388,6 +403,12 @@ copy_configuration $path $rootfs $name $arch $release
> >
> > "$CLONE_HOOK_FN" "${cloneargs[@]}" "$rootfs"
> >
> > +if [ $mapped_uid -ne -1 ]; then
> > + chown $mapped_uid $path/config
> > + chown -R $mapped_uid $STATE_DIR
> > + chown -R $mapped_uid $cache
> > +fi
> > +
> > echo "Container $name created."
> > exit 0
> >
> > --
> > 1.8.4.2
> >
> >
> > ------------------------------------------------------------------------------
> > November Webinars for C, C++, Fortran Developers
> > Accelerate application performance with scalable programming models. Explore
> > techniques for threading, error checking, porting, and tuning. Get the most
> > from the latest Intel processors and coprocessors. See abstracts and register
> > http://pubads.g.doubleclick.net/gampad/clk?id=60136231&iu=/4140/ostg.clktrk
> > _______________________________________________
> > Lxc-devel mailing list
> > Lxc-devel at lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/lxc-devel
>
> --
> Stéphane Graber
> Ubuntu developer
> http://www.ubuntu.com
More information about the lxc-devel
mailing list