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.hal...@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);
                                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@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to