[lxc-devel] [lxc/master] Fix issues with lxc-download

wget on Github lxc-bot at linuxcontainers.org
Wed May 3 10:25:14 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 520 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170503/7afa7436/attachment.bin>
-------------- next part --------------
From 7fc9e36a2fc6329a5ea91706a557207a8d3bb24c Mon Sep 17 00:00:00 2001
From: William Gathoye <william at gathoye.be>
Date: Wed, 3 May 2017 11:59:18 +0200
Subject: [PATCH 1/2] Sanitize lxc-download script with shellcheck

---
 templates/lxc-download.in | 320 +++++++++++++++++++++++++---------------------
 1 file changed, 172 insertions(+), 148 deletions(-)

diff --git a/templates/lxc-download.in b/templates/lxc-download.in
index 0298300..2942004 100644
--- a/templates/lxc-download.in
+++ b/templates/lxc-download.in
@@ -68,23 +68,25 @@ export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
 # Some useful functions
 cleanup() {
     if [ -d "$DOWNLOAD_TEMP" ]; then
-        rm -Rf $DOWNLOAD_TEMP
+        rm -Rf "$DOWNLOAD_TEMP"
     fi
 }
 
 wget_wrapper() {
-    for i in $(seq 3); do
-        if wget $@; then
+    : $((i=0))
+    while [ "$((i < 3))" -ne 0 ]; do
+        if wget "$@"; then
             return 0
         fi
+        : $((i=i+1))
     done
 
     return 1
 }
 
 download_file() {
-    if ! wget_wrapper -T 30 -q https://${DOWNLOAD_SERVER}/$1 -O $2 >/dev/null 2>&1; then
-        if ! wget_wrapper -T 30 -q http://${DOWNLOAD_SERVER}/$1 -O $2 >/dev/null 2>&1; then
+    if ! wget_wrapper -T 30 -q "https://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then
+        if ! wget_wrapper -T 30 -q "http://${DOWNLOAD_SERVER}/$1" -O "$2" >/dev/null 2>&1; then
             if [ "$3" = "noexit" ]; then
                 return 1
             else
@@ -94,14 +96,14 @@ download_file() {
         elif [ "$DOWNLOAD_SHOW_HTTP_WARNING" = "true" ]; then
             DOWNLOAD_SHOW_HTTP_WARNING="false"
             echo "WARNING: Failed to download the file over HTTPs." 1>&2
-            echo -n "         The file was instead download over HTTP. " 1>&2
+            echo "         The file was instead download over HTTP. " 1>&2
             echo "A server replay attack may be possible!" 1>&2
         fi
     fi
 }
 
 download_sig() {
-    if ! download_file $1 $2 noexit; then
+    if ! download_file "$1" "$2" noexit; then
         if [ "$DOWNLOAD_VALIDATE" = "true" ]; then
             if [ "$3" = "normal" ]; then
                 echo "ERROR: Failed to download http://${DOWNLOAD_SERVER}/$1" 1>&2
@@ -131,12 +133,14 @@ gpg_setup() {
     export GNUPGHOME="$DOWNLOAD_TEMP/gpg"
 
     success=
-    for i in $(seq 3); do
-        if gpg --keyserver $DOWNLOAD_KEYSERVER \
-            --recv-keys ${DOWNLOAD_KEYID} >/dev/null 2>&1; then
+    : $((i=0))
+    while [ "$((i < 3))" -ne 0 ]; do
+        if gpg --keyserver "$DOWNLOAD_KEYSERVER" \
+            --recv-keys "${DOWNLOAD_KEYID}" >/dev/null 2>&1; then
             success=1
             break
         fi
+        : $((i=i+1))
     done
 
     if [ -z "$success" ]; then
@@ -156,7 +160,7 @@ gpg_validate() {
         return 0
     fi
 
-    if ! gpg --verify $1 >/dev/zero 2>&1; then
+    if ! gpg --verify "$1" >/dev/null 2>&1; then
         echo "ERROR: Invalid signature for $1" 1>&2
         exit 1
     fi
@@ -164,10 +168,16 @@ gpg_validate() {
 
 in_userns() {
     [ -e /proc/self/uid_map ] || { echo no; return; }
-    while read line; do
-        fields=$(echo $line | awk '{ print $1 " " $2 " " $3 }')
-        [ "$fields" = "0 0 4294967295" ] && { echo no; return; } || true
-        echo $fields | grep -q " 0 1$" && { echo userns-root; return; } || true
+    while read -r line; do
+        fields="$(echo "$line" | awk '{ print $1 " " $2 " " $3 }')"
+        if [ "$fields" = "0 0 4294967295" ]; then
+            echo no;
+            return;
+        fi
+        if echo "$fields" | grep -q " 0 1$"; then
+            echo userns-root;
+            return;
+        fi
     done < /proc/self/uid_map
 
     [ "$(cat /proc/self/uid_map)" = "$(cat /proc/1/uid_map)" ] && \
@@ -184,7 +194,7 @@ relevant_file() {
         FILE_PATH="${FILE_PATH}.${DOWNLOAD_COMPAT_LEVEL}"
     fi
 
-    echo $FILE_PATH
+    echo "$FILE_PATH"
 }
 
 usage() {
@@ -224,11 +234,9 @@ EOF
     return 0
 }
 
-options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\
+if ! options=$(getopt -o d:r:a:hl -l dist:,release:,arch:,help,list,variant:,\
 server:,keyid:,keyserver:,no-validate,flush-cache,force-cache,name:,path:,\
-rootfs:,mapped-uid:,mapped-gid: -- "$@")
-
-if [ $? -ne 0 ]; then
+rootfs:,mapped-uid:,mapped-gid: -- "$@"); then
     usage
     exit 1
 fi
@@ -238,28 +246,28 @@ while :; do
     case "$1" in
         -h|--help)          usage && exit 1;;
         -l|--list)          DOWNLOAD_LIST_IMAGES="true"; shift 1;;
-        -d|--dist)          DOWNLOAD_DIST=$2; shift 2;;
-        -r|--release)       DOWNLOAD_RELEASE=$2; shift 2;;
-        -a|--arch)          DOWNLOAD_ARCH=$2; shift 2;;
-        --variant)          DOWNLOAD_VARIANT=$2; shift 2;;
-        --server)           DOWNLOAD_SERVER=$2; shift 2;;
-        --keyid)            DOWNLOAD_KEYID=$2; shift 2;;
-        --keyserver)        DOWNLOAD_KEYSERVER=$2; shift 2;;
+        -d|--dist)          DOWNLOAD_DIST="$2"; shift 2;;
+        -r|--release)       DOWNLOAD_RELEASE="$2"; shift 2;;
+        -a|--arch)          DOWNLOAD_ARCH="$2"; shift 2;;
+        --variant)          DOWNLOAD_VARIANT="$2"; shift 2;;
+        --server)           DOWNLOAD_SERVER="$2"; shift 2;;
+        --keyid)            DOWNLOAD_KEYID="$2"; shift 2;;
+        --keyserver)        DOWNLOAD_KEYSERVER="$2"; shift 2;;
         --no-validate)      DOWNLOAD_VALIDATE="false"; shift 1;;
         --flush-cache)      DOWNLOAD_FLUSH_CACHE="true"; shift 1;;
         --force-cache)      DOWNLOAD_FORCE_CACHE="true"; shift 1;;
-        --name)             LXC_NAME=$2; shift 2;;
-        --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;;
+        --name)             LXC_NAME="$2"; shift 2;;
+        --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
 
 # Check for required binaries
 for bin in tar xz wget; do
-    if ! type $bin >/dev/null 2>&1; then
+    if ! command -V "$bin" >/dev/null 2>&1; then
         echo "ERROR: Missing required tool: $bin" 1>&2
         exit 1
     fi
@@ -267,7 +275,7 @@ done
 
 # Check for GPG
 if [ "$DOWNLOAD_VALIDATE" = "true" ]; then
-    if ! type gpg >/dev/null 2>&1; then
+    if ! command -V gpg >/dev/null 2>&1; then
         echo "ERROR: Missing recommended tool: gpg" 1>&2
         echo "You can workaround this by using --no-validate." 1>&2
         exit 1
@@ -306,9 +314,9 @@ fi
 # Trap all exit signals
 trap cleanup EXIT HUP INT TERM
 
-if ! type mktemp >/dev/null 2>&1; then
+if ! command -V mktemp >/dev/null 2>&1; then
     DOWNLOAD_TEMP=/tmp/lxc-download.$$
-    mkdir -p $DOWNLOAD_TEMP
+    mkdir -p "$DOWNLOAD_TEMP"
 else
     DOWNLOAD_TEMP=$(mktemp -d)
 fi
@@ -320,40 +328,40 @@ if [ "$DOWNLOAD_LIST_IMAGES" = "true" ] || \
     gpg_setup
 
     # Grab the index
-    DOWNLOAD_INDEX_PATH=/meta/1.0/index-${DOWNLOAD_MODE}
+    DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}"
 
     echo "Downloading the image index"
-    if ! download_file ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL} \
-         ${DOWNLOAD_TEMP}/index noexit ||
-       ! download_sig ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc \
-            ${DOWNLOAD_TEMP}/index.asc noexit; then
-        download_file ${DOWNLOAD_INDEX_PATH} ${DOWNLOAD_TEMP}/index normal
-        download_sig  ${DOWNLOAD_INDEX_PATH}.asc \
-            ${DOWNLOAD_TEMP}/index.asc normal
+    if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" \
+         "${DOWNLOAD_TEMP}/index" noexit ||
+       ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" \
+            "${DOWNLOAD_TEMP}/index.asc" noexit; then
+        download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal
+        download_sig "${DOWNLOAD_INDEX_PATH}.asc" \
+            "${DOWNLOAD_TEMP}/index.asc" normal
     fi
 
-    gpg_validate ${DOWNLOAD_TEMP}/index.asc
+    gpg_validate "${DOWNLOAD_TEMP}/index.asc"
 
     # Parse it
     echo ""
     echo "---"
     printf "DIST\tRELEASE\tARCH\tVARIANT\tBUILD\n"
     echo "---"
-    while read line; do
+    while IFS=';' read -r f1 f2 f3 f4 f5 f6; do
         # Basic CSV parser
-        OLD_IFS=$IFS
-        IFS=";"
-        set -- $line
-        IFS=$OLD_IFS
-
-        [ -n "$DOWNLOAD_DIST" ] && [ "$1" != "$DOWNLOAD_DIST" ] && continue
-        [ -n "$DOWNLOAD_RELEASE" ] && [ "$2" != "$DOWNLOAD_RELEASE" ] && continue
-        [ -n "$DOWNLOAD_ARCH" ] && [ "$3" != "$DOWNLOAD_ARCH" ] && continue
-        [ -n "$DOWNLOAD_VARIANT" ] && [ "$4" != "$DOWNLOAD_VARIANT" ] && continue
-        [ -z "$5" ] || [ -z "$6" ] && continue
-
-        printf "$1\t$2\t$3\t$4\t$5\n"
-    done < ${DOWNLOAD_TEMP}/index
+        # IFS=";"
+        # set -- "$line"
+        # IFS=$OLD_IFS
+
+        [ -n "$DOWNLOAD_DIST" ] && [ "$f1" != "$DOWNLOAD_DIST" ] && continue
+        [ -n "$DOWNLOAD_RELEASE" ] && [ "$f2" != "$DOWNLOAD_RELEASE" ] && continue
+        [ -n "$DOWNLOAD_ARCH" ] && [ "$f3" != "$DOWNLOAD_ARCH" ] && continue
+        [ -n "$DOWNLOAD_VARIANT" ] && [ "$f4" != "$DOWNLOAD_VARIANT" ] && continue
+        [ -z "$f5" ] || [ -z "$f6" ] && continue
+
+        printf "%s\t%s\t%s\t%s\t%s\n" "$f1" "$f2" "$f3" "$f4" "$f5"
+        unset f1 f2 f3 f4 f5 f6
+    done < "${DOWNLOAD_TEMP}/index"
     echo "---"
 
     if [ "$DOWNLOAD_LIST_IMAGES" = "true" ]; then
@@ -364,18 +372,18 @@ if [ "$DOWNLOAD_LIST_IMAGES" = "true" ] || \
     echo ""
 
     if [ -z "$DOWNLOAD_DIST" ]; then
-        echo -n "Distribution: "
-        read DOWNLOAD_DIST
+        echo "Distribution: "
+        read -r DOWNLOAD_DIST
     fi
 
     if [ -z "$DOWNLOAD_RELEASE" ]; then
-        echo -n "Release: "
-        read DOWNLOAD_RELEASE
+        echo "Release: "
+        read -r DOWNLOAD_RELEASE
     fi
 
     if [ -z "$DOWNLOAD_ARCH" ]; then
-        echo -n "Architecture: "
-        read DOWNLOAD_ARCH
+        echo "Architecture: "
+        read -r DOWNLOAD_ARCH
     fi
 
     echo ""
@@ -389,21 +397,21 @@ else
 fi
 
 # Allow the setting of the LXC_CACHE_PATH with the usage of environment variables.
-LXC_CACHE_PATH=${LXC_CACHE_PATH:-"$LXC_CACHE_BASE"}
-LXC_CACHE_PATH=$LXC_CACHE_PATH/download/$DOWNLOAD_DIST
+LXC_CACHE_PATH="${LXC_CACHE_PATH:-"$LXC_CACHE_BASE"}"
+LXC_CACHE_PATH="$LXC_CACHE_PATH/download/$DOWNLOAD_DIST"
 LXC_CACHE_PATH="$LXC_CACHE_PATH/$DOWNLOAD_RELEASE/$DOWNLOAD_ARCH/"
 LXC_CACHE_PATH="$LXC_CACHE_PATH/$DOWNLOAD_VARIANT"
 
 if [ -d "$LXC_CACHE_PATH" ]; then
     if [ "$DOWNLOAD_FLUSH_CACHE" = "true" ]; then
         echo "Flushing the cache..."
-        rm -Rf $LXC_CACHE_PATH
+        rm -Rf "$LXC_CACHE_PATH"
     elif [ "$DOWNLOAD_FORCE_CACHE" = "true" ]; then
         DOWNLOAD_USE_CACHE="true"
     else
         DOWNLOAD_USE_CACHE="true"
         if [ -e "$(relevant_file expiry)" ]; then
-            if [ "$(cat $(relevant_file expiry))" -lt $(date +%s) ]; then
+            if [ "$(cat "$(relevant_file expiry)")" -lt "$(date +%s)" ]; then
                 echo "The cached copy has expired, re-downloading..."
                 DOWNLOAD_USE_CACHE="false"
             fi
@@ -417,40 +425,42 @@ if [ "$DOWNLOAD_USE_CACHE" = "false" ]; then
     gpg_setup
 
     # Grab the index
-    DOWNLOAD_INDEX_PATH=/meta/1.0/index-${DOWNLOAD_MODE}
+    DOWNLOAD_INDEX_PATH="/meta/1.0/index-${DOWNLOAD_MODE}"
 
     echo "Downloading the image index"
-    if ! download_file ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL} \
-         ${DOWNLOAD_TEMP}/index noexit ||
-       ! download_sig ${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc \
-            ${DOWNLOAD_TEMP}/index.asc noexit; then
-        download_file ${DOWNLOAD_INDEX_PATH} ${DOWNLOAD_TEMP}/index normal
-        download_sig  ${DOWNLOAD_INDEX_PATH}.asc \
-            ${DOWNLOAD_TEMP}/index.asc normal
+    if ! download_file "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}" \
+         "${DOWNLOAD_TEMP}/index" noexit ||
+       ! download_sig "${DOWNLOAD_INDEX_PATH}.${DOWNLOAD_COMPAT_LEVEL}.asc" \
+            "${DOWNLOAD_TEMP}/index.asc" noexit; then
+        download_file "${DOWNLOAD_INDEX_PATH}" "${DOWNLOAD_TEMP}/index" normal
+        download_sig "${DOWNLOAD_INDEX_PATH}.asc" \
+            "${DOWNLOAD_TEMP}/index.asc" normal
     fi
 
-    gpg_validate ${DOWNLOAD_TEMP}/index.asc
+    gpg_validate "${DOWNLOAD_TEMP}/index.asc"
 
     # Parse it
-    while read line; do
+    while IFS=';' read -r f1 f2 f3 f4 f5 f6; do
         # Basic CSV parser
-        OLD_IFS=$IFS
-        IFS=";"
-        set -- $line
-        IFS=$OLD_IFS
-
-        if [ "$1" != "$DOWNLOAD_DIST" ] || \
-           [ "$2" != "$DOWNLOAD_RELEASE" ] || \
-           [ "$3" != "$DOWNLOAD_ARCH" ] || \
-           [ "$4" != "$DOWNLOAD_VARIANT" ] || \
-           [ -z "$6" ]; then
+        # OLD_IFS=$IFS
+        # IFS=";"
+        # set -- "$line"
+        # IFS=$OLD_IFS
+
+        if [ "$f1" != "$DOWNLOAD_DIST" ] || \
+           [ "$f2" != "$DOWNLOAD_RELEASE" ] || \
+           [ "$f3" != "$DOWNLOAD_ARCH" ] || \
+           [ "$f4" != "$DOWNLOAD_VARIANT" ] || \
+           [ -z "$f6" ]; then
             continue
         fi
 
-        DOWNLOAD_BUILD=$5
-        DOWNLOAD_URL=$6
+        DOWNLOAD_BUILD=$f5
+        DOWNLOAD_URL=$f6
+
+        unset f1 f2 f3 f4 f5 f6
         break
-    done < ${DOWNLOAD_TEMP}/index
+    done < "${DOWNLOAD_TEMP}/index"
 
     if [ -z "$DOWNLOAD_URL" ]; then
         echo "ERROR: Couldn't find a matching image." 1>&1
@@ -458,42 +468,45 @@ if [ "$DOWNLOAD_USE_CACHE" = "false" ]; then
     fi
 
     if [ -d "$LXC_CACHE_PATH" ] && [ -f "$LXC_CACHE_PATH/build_id" ] && \
-       [ "$(cat $LXC_CACHE_PATH/build_id)" = "$DOWNLOAD_BUILD" ]; then
+       [ "$(cat "$LXC_CACHE_PATH/build_id")" = "$DOWNLOAD_BUILD" ]; then
         echo "The cache is already up to date."
         echo "Using image from local cache"
     else
         # Download the actual files
         echo "Downloading the rootfs"
-        download_file $DOWNLOAD_URL/rootfs.tar.xz \
-            ${DOWNLOAD_TEMP}/rootfs.tar.xz normal
-        download_sig  $DOWNLOAD_URL/rootfs.tar.xz.asc \
-             ${DOWNLOAD_TEMP}/rootfs.tar.xz.asc normal
-        gpg_validate ${DOWNLOAD_TEMP}/rootfs.tar.xz.asc
+        download_file "$DOWNLOAD_URL/rootfs.tar.xz" \
+            "${DOWNLOAD_TEMP}/rootfs.tar.xz" normal
+        download_sig "$DOWNLOAD_URL/rootfs.tar.xz.asc" \
+             "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc" normal
+        gpg_validate "${DOWNLOAD_TEMP}/rootfs.tar.xz.asc"
 
         echo "Downloading the metadata"
-        download_file $DOWNLOAD_URL/meta.tar.xz \
-            ${DOWNLOAD_TEMP}/meta.tar.xz normal
-        download_sig  $DOWNLOAD_URL/meta.tar.xz.asc \
-            ${DOWNLOAD_TEMP}/meta.tar.xz.asc normal
-        gpg_validate ${DOWNLOAD_TEMP}/meta.tar.xz.asc
-
-        if [ -d $LXC_CACHE_PATH ]; then
-            rm -Rf $LXC_CACHE_PATH
+        download_file "$DOWNLOAD_URL/meta.tar.xz" \
+            "${DOWNLOAD_TEMP}/meta.tar.xz" normal
+        download_sig "$DOWNLOAD_URL/meta.tar.xz.asc" \
+            "${DOWNLOAD_TEMP}/meta.tar.xz.asc" normal
+        gpg_validate "${DOWNLOAD_TEMP}/meta.tar.xz.asc"
+
+        if [ -d "$LXC_CACHE_PATH" ]; then
+            rm -Rf "$LXC_CACHE_PATH"
         fi
-        mkdir -p $LXC_CACHE_PATH
-        mv ${DOWNLOAD_TEMP}/rootfs.tar.xz $LXC_CACHE_PATH
-        if ! tar Jxf ${DOWNLOAD_TEMP}/meta.tar.xz -C $LXC_CACHE_PATH; then
+        mkdir -p "$LXC_CACHE_PATH"
+        mv "${DOWNLOAD_TEMP}/rootfs.tar.xz" "$LXC_CACHE_PATH"
+        if ! tar Jxf "${DOWNLOAD_TEMP}/meta.tar.xz" -C "$LXC_CACHE_PATH"; then
             echo "ERROR: Invalid rootfs tarball." 2>&1
             exit 1
         fi
 
-        echo $DOWNLOAD_BUILD > $LXC_CACHE_PATH/build_id
+        echo "$DOWNLOAD_BUILD" > "$LXC_CACHE_PATH/build_id"
 
         if [ -n "$LXC_MAPPED_UID" ] && [ "$LXC_MAPPED_UID" != "-1" ]; then
-            chown -R $LXC_MAPPED_UID $LXC_CACHE_BASE >/dev/null 2>&1 || true
+            # As the script is run in strict mode (set -eu), all commands
+            # exiting with non 0 would make the script stop.
+            # || true or || : (more portable) prevents that.
+            chown -R "$LXC_MAPPED_UID" "$LXC_CACHE_BASE" >/dev/null 2>&1 || :
         fi
         if [ -n "$LXC_MAPPED_GID" ] && [ "$LXC_MAPPED_GID" != "-1" ]; then
-            chgrp -R $LXC_MAPPED_GID $LXC_CACHE_BASE >/dev/null 2>&1 || true
+            chgrp -R "$LXC_MAPPED_GID" "$LXC_CACHE_BASE" >/dev/null 2>&1 || :
         fi
         echo "The image cache is now ready"
     fi
@@ -507,94 +520,105 @@ echo "Unpacking the rootfs"
 EXCLUDES=""
 excludelist=$(relevant_file excludes)
 if [ -f "${excludelist}" ]; then
-    while read line; do
+    while read -r line; do
         EXCLUDES="$EXCLUDES --exclude=$line"
-    done < $excludelist
+    done < "$excludelist"
 fi
 
+# Do not surround ${EXCLUDES} by quotes. This does not work. The solution could
+# be using, but this is not POSIX compliant. The only solution is to use
+# a function wrapper, but can't be used here as the args are dynamic. We need
+# to ignore the warning.
+# shellcheck disable=SC2086
 tar  --anchored ${EXCLUDES} --numeric-owner -xpJf \
-    ${LXC_CACHE_PATH}/rootfs.tar.xz -C ${LXC_ROOTFS}
+    "${LXC_CACHE_PATH}/rootfs.tar.xz" -C "${LXC_ROOTFS}"
 
-mkdir -p ${LXC_ROOTFS}/dev/pts/
+mkdir -p "${LXC_ROOTFS}/dev/pts/"
 
 # Setup the configuration
-configfile=$(relevant_file config)
-fstab=$(relevant_file fstab)
-if [ ! -e $configfile ]; then
+configfile="$(relevant_file config)"
+fstab="$(relevant_file fstab)"
+if [ ! -e "$configfile" ]; then
     echo "ERROR: meta tarball is missing the configuration file" 1>&2
     exit 1
 fi
 
 ## Extract all the network config entries
 sed -i -e "/lxc.network/{w ${LXC_PATH}/config-network" -e "d}" \
-    ${LXC_PATH}/config
+    "${LXC_PATH}/config"
 
 ## Extract any other config entry
-sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" ${LXC_PATH}/config
+sed -i -e "/lxc./{w ${LXC_PATH}/config-auto" -e "d}" "${LXC_PATH}/config"
 
 ## Append the defaults
-echo "" >> ${LXC_PATH}/config
-echo "# Distribution configuration" >> ${LXC_PATH}/config
-cat $configfile >> ${LXC_PATH}/config
+{
+    echo ""
+    echo "# Distribution configuration"
+    cat "$configfile"
+} >> "${LXC_PATH}/config"
 
 ## Add the container-specific config
-echo "" >> ${LXC_PATH}/config
-echo "# Container specific configuration" >> ${LXC_PATH}/config
+{
+    echo ""
+    echo "# Container specific configuration"
+} >> "${LXC_PATH}/config"
 if [ -e "${LXC_PATH}/config-auto" ]; then
-    cat ${LXC_PATH}/config-auto >> ${LXC_PATH}/config
-    rm ${LXC_PATH}/config-auto
+    cat "${LXC_PATH}/config-auto" >> "${LXC_PATH}/config"
+    rm "${LXC_PATH}/config-auto"
 fi
 if [ -e "$fstab" ]; then
-    echo "lxc.mount = ${LXC_PATH}/fstab" >> ${LXC_PATH}/config
+    echo "lxc.mount = ${LXC_PATH}/fstab" >> "${LXC_PATH}/config"
 fi
-echo "lxc.utsname = ${LXC_NAME}" >> ${LXC_PATH}/config
+echo "lxc.utsname = ${LXC_NAME}" >> "${LXC_PATH}/config"
 
 ## Re-add the previously removed network config
 if [ -e "${LXC_PATH}/config-network" ]; then
-    echo "" >> ${LXC_PATH}/config
-    echo "# Network configuration" >> ${LXC_PATH}/config
-    cat ${LXC_PATH}/config-network >> ${LXC_PATH}/config
-    rm ${LXC_PATH}/config-network
+    {
+        echo ""
+        echo "# Network configuration"
+        cat "${LXC_PATH}/config-network"
+    } >> "${LXC_PATH}/config"
+    rm "${LXC_PATH}/config-network"
 fi
 
 TEMPLATE_FILES="${LXC_PATH}/config"
 
 # Setup the fstab
-if [ -e $fstab ]; then
-    cp ${fstab} ${LXC_PATH}/fstab
+if [ -e "$fstab" ]; then
+    cp "$fstab}" "${LXC_PATH}/fstab"
     TEMPLATE_FILES="$TEMPLATE_FILES ${LXC_PATH}/fstab"
 fi
 
 # Look for extra templates
 if [ -e "$(relevant_file templates)" ]; then
-    while read line; do
-        fullpath=${LXC_ROOTFS}/$line
+    while read -r line; do
+        fullpath="${LXC_ROOTFS}/$line"
         [ ! -e "$fullpath" ] && continue
         TEMPLATE_FILES="$TEMPLATE_FILES $fullpath"
-    done < $(relevant_file templates)
+    done < "$(relevant_file templates)"
 fi
 
 # Replace variables in all templates
 for file in $TEMPLATE_FILES; do
     [ ! -f "$file" ] && continue
 
-    sed -i "s#LXC_NAME#$LXC_NAME#g" $file
-    sed -i "s#LXC_PATH#$LXC_PATH#g" $file
-    sed -i "s#LXC_ROOTFS#$LXC_ROOTFS#g" $file
-    sed -i "s#LXC_TEMPLATE_CONFIG#$LXC_TEMPLATE_CONFIG#g" $file
-    sed -i "s#LXC_HOOK_DIR#$LXC_HOOK_DIR#g" $file
+    sed -i "s#LXC_NAME#$LXC_NAME#g" "$file"
+    sed -i "s#LXC_PATH#$LXC_PATH#g" "$file"
+    sed -i "s#LXC_ROOTFS#$LXC_ROOTFS#g" "$file"
+    sed -i "s#LXC_TEMPLATE_CONFIG#$LXC_TEMPLATE_CONFIG#g" "$file"
+    sed -i "s#LXC_HOOK_DIR#$LXC_HOOK_DIR#g" "$file"
 done
 
 # prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle
-if [ -f ${LXC_ROOTFS}/etc/init/tty.conf ]; then
-    sed -i 's|mingetty|mingetty --nohangup|' ${LXC_ROOTFS}/etc/init/tty.conf
+if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then
+    sed -i 's|mingetty|mingetty --nohangup|' "${LXC_ROOTFS}/etc/init/tty.conf"
 fi
 
 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
+    chown "$LXC_MAPPED_UID" "$LXC_PATH/config" "$LXC_PATH/fstab" >/dev/null 2>&1 || :
 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
+    chgrp "$LXC_MAPPED_GID" "$LXC_PATH/config" "$LXC_PATH/fstab" >/dev/null 2>&1 || :
 fi
 
 if [ -e "$(relevant_file create-message)" ]; then

From 8741bda322b33351ed8e56028c55b5ff475a5806 Mon Sep 17 00:00:00 2001
From: William Gathoye <william at gathoye.be>
Date: Wed, 3 May 2017 12:21:49 +0200
Subject: [PATCH 2/2] Fix potential CVE when using spaces in LXC names

---
 templates/lxc-download.in | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/templates/lxc-download.in b/templates/lxc-download.in
index 2942004..13cc33c 100644
--- a/templates/lxc-download.in
+++ b/templates/lxc-download.in
@@ -586,7 +586,7 @@ TEMPLATE_FILES="${LXC_PATH}/config"
 # Setup the fstab
 if [ -e "$fstab" ]; then
     cp "$fstab}" "${LXC_PATH}/fstab"
-    TEMPLATE_FILES="$TEMPLATE_FILES ${LXC_PATH}/fstab"
+    TEMPLATE_FILES="$TEMPLATE_FILES;${LXC_PATH}/fstab"
 fi
 
 # Look for extra templates
@@ -594,11 +594,13 @@ if [ -e "$(relevant_file templates)" ]; then
     while read -r line; do
         fullpath="${LXC_ROOTFS}/$line"
         [ ! -e "$fullpath" ] && continue
-        TEMPLATE_FILES="$TEMPLATE_FILES $fullpath"
+        TEMPLATE_FILES="$TEMPLATE_FILES;$fullpath"
     done < "$(relevant_file templates)"
 fi
 
 # Replace variables in all templates
+OLD_IFS=$IFS
+IFS=";"
 for file in $TEMPLATE_FILES; do
     [ ! -f "$file" ] && continue
 
@@ -608,6 +610,7 @@ for file in $TEMPLATE_FILES; do
     sed -i "s#LXC_TEMPLATE_CONFIG#$LXC_TEMPLATE_CONFIG#g" "$file"
     sed -i "s#LXC_HOOK_DIR#$LXC_HOOK_DIR#g" "$file"
 done
+IFS=$OLD_IFS
 
 # prevent mingetty from calling vhangup(2) since it fails with userns on CentOS / Oracle
 if [ -f "${LXC_ROOTFS}/etc/init/tty.conf" ]; then


More information about the lxc-devel mailing list