[lxc-devel] [PATCH] lxc-cirros: support creating+running unprivileged

Serge Hallyn serge.hallyn at ubuntu.com
Fri Oct 31 02:42:31 UTC 2014


Support creation and use of lxc-cirros by unprivileged users.

If we detect we are an unprivileged user, then insist that we
be in a userns with a id mapping.

If we are in a userns, then don't extract /dev when extracting
the rootfs.

If we are not root, then save the tarball to ~/.cache/lxc/cirros
instead of /var/cache/lxc/cirros.

If we are not roo, then include entries to auto-mount proc and sys,
as well as bind-mount devices.

Cc: smoser at ubuntu.com
Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 templates/lxc-cirros.in | 62 +++++++++++++++++++++++++++++--------------------
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/templates/lxc-cirros.in b/templates/lxc-cirros.in
index 24b9210..c8a8b36 100644
--- a/templates/lxc-cirros.in
+++ b/templates/lxc-cirros.in
@@ -22,27 +22,21 @@
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 # Detect use under userns (unsupported)
-for arg in "$@"; do
-    [ "$arg" = "--" ] && break
-    if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then
-        echo "This template can't be used for unprivileged containers." 1>&2
-        echo "You may want to try the \"download\" template instead." 1>&2
-        exit 1
-    fi
-done
-
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 
 VERBOSITY=0
 DOWNLOAD_URL="http://download.cirros-cloud.net/"
-CACHE_D="@LOCALSTATEDIR@/cache/lxc/cirros"
 
 UNAME_M=$(uname -m)
 ARCHES=( i386 x86_64 amd64 arm )
 STREAMS=( released devel )
 SOURCES=( nocloud none )
 BUILD="standard"
+LXC_TEMPLATE_CONFIG="@LXCTEMPLATECONFIG@"
+
+LXC_MAPPED_GID=
+LXC_MAPPED_UID=
 
 DEF_VERSION="released"
 DEF_SOURCE="nocloud"
@@ -53,6 +47,23 @@ case "${UNAME_M}" in
     *) DEF_ARCH="i386";;
 esac
 
+am_in_userns() {
+    [ -e /proc/self/uid_map ] || { echo no; return; }
+    [ "$(wc -l /proc/self/uid_map | awk '{ print $1 }')" -eq 1 ] || { echo yes; return; }
+    line=$(awk '{ print $1 " " $2 " " $3 }' /proc/self/uid_map)
+    [ "$line" = "0 0 4294967295" ] && { echo no; return; }
+    echo yes
+}
+
+in_userns=0
+[ $(am_in_userns) = "yes" ] && in_userns=1
+
+if [ $(id -u) -eq 0 ]; then
+    CACHE_D="@LOCALSTATEDIR@/cache/lxc/cirros"
+else
+    CACHE_D="$HOME/.cache/lxc/cirros"
+fi
+
 error() { echo "$@" 1>&2; }
 inargs() {
     local needle="$1" x=""
@@ -151,6 +162,12 @@ lxc.cgroup.devices.allow = c 10:228 rwm
 # kvm
 lxc.cgroup.devices.allow = c 10:232 rwm
 EOF
+
+    if [ $in_userns -eq 1 ] && [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu-cloud.userns.conf" ]; then
+        echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.userns.conf" >> $path/config
+        echo "lxc.mount.auto = cgroup:mixed proc:mixed sys:ro" >> $path/config
+    fi
+
 }
 
 insert_ds_nocloud() {
@@ -187,8 +204,13 @@ extract_rootfs() {
     mkdir -p "${rootfs_d}" ||
         { error "failed to make rootfs dir ${rootfs_d}"; return 1; }
 
-    tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
-        { error "failed to populate ${rootfs_d}"; return 1; }
+    if [ $in_userns -eq 1 ]; then
+        tar -C "${rootfs_d}" --anchored --exclude="dev/*" -Sxzf "${tarball}" ||
+            { error "failed to populate ${rootfs_d}"; return 1; }
+    else
+        tar -C "${rootfs_d}" -Sxzf "${tarball}" ||
+            { error "failed to populate ${rootfs_d}"; return 1; }
+    fi
     return 0
 }
 
@@ -218,7 +240,7 @@ download_tarball() {
 
 create_main() {
     local short_opts="a:hn:p:S:uvV"
-    local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:"
+    local long_opts="arch:,auth-key:,name:,path:,tarball:,userdata:,verbose,version:,rootfs:,mapped-uid:,mapped-gid:"
     local getopt_out=""
     getopt_out=$(getopt --name "${0##*/}" \
         --options "${short_opts}" --long "${long_opts}" -- "$@") &&
@@ -244,6 +266,8 @@ create_main() {
                --tarball) tarball="$next"; shift;;
                --source) dsource="$next"; shift;;
                --rootfs) rootfs_d="$next"; shift;;
+            --mapped-uid) LXC_MAPPED_UID=$next; shift;;
+            --mapped-gid) LXC_MAPPED_GID=$next; shift;;
             --) shift; break;;
         esac
         shift;
@@ -300,18 +324,6 @@ create_main() {
 
     extract_rootfs "${tarball}" "${rootfs_d}" || return
 
-    # cirros 0.3.1 was broken for /dev/random and /dev/urandom
-    if [ -b "$rootfs_d/dev/random" ]; then
-        rm -f "$rootfs_d/dev/random" &&
-            mknod --mode=666 "$rootfs_d/dev/random" c 1 8 ||
-           { error "failed to fix /dev/random"; return 1; }
-    fi
-    if [ -b "$rootfs_d/dev/urandom" ]; then
-        rm -f "$rootfs_d/dev/urandom" &&
-        mknod --mode=666 "$rootfs_d/dev/urandom" c 1 9 ||
-           { error "failed to fix /dev/urandom"; return 1; }
-    fi
-
     if [ "$version" = "0.3.2~pre1" ]; then
         debug 1 "fixing console for lxc and '$version'"
         sed -i 's,^\(#console.* 115200 \)# /dev/console,\1 console,g' \
-- 
2.1.0



More information about the lxc-devel mailing list