Imported Upstream version 1.1.3 upstream/1.1.3
authorDariusz Michaluk <d.michaluk@samsung.com>
Fri, 28 Aug 2015 15:11:21 +0000 (17:11 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Fri, 28 Aug 2015 15:11:21 +0000 (17:11 +0200)
75 files changed:
CONTRIBUTING
config/bash/lxc
config/bash/lxc.in
config/init/common/lxc-containers.in
config/init/common/lxc-net.in
config/init/systemd/lxc-apparmor-load
config/init/systemd/lxc.service.in
config/init/upstart/Makefile.in
config/init/upstart/lxc.conf
config/templates/centos.common.conf.in
config/templates/gentoo.moresecure.conf.in
configure
configure.ac
doc/common_options.sgml.in
doc/ja/common_options.sgml.in
doc/ja/lxc-autostart.sgml.in
doc/ja/lxc-config.sgml.in
doc/ja/lxc-destroy.sgml.in
doc/ja/lxc-ls.sgml.in
doc/ja/lxc-snapshot.sgml.in
doc/ja/lxc-user-nic.sgml.in
doc/ja/lxc-usernet.sgml.in
doc/ja/lxc-usernsexec.sgml.in
doc/ja/lxc.conf.sgml.in
doc/ja/lxc.container.conf.sgml.in
doc/ja/lxc.system.conf.sgml.in
doc/lxc-autostart.sgml.in
doc/lxc-ls.sgml.in
doc/lxc-user-nic.sgml.in
lxc.spec
src/config.h.in
src/lua-lxc/core.c
src/lxc/Makefile.am
src/lxc/Makefile.in
src/lxc/attach.c
src/lxc/bdev.c
src/lxc/bdev.h
src/lxc/cgfs.c
src/lxc/cgmanager.c
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/criu.c [new file with mode: 0644]
src/lxc/criu.h [new file with mode: 0644]
src/lxc/execute.c
src/lxc/initutils.c [new file with mode: 0644]
src/lxc/initutils.h [new file with mode: 0644]
src/lxc/log.c
src/lxc/lxc-checkconfig.in
src/lxc/lxc-restore-net [deleted file]
src/lxc/lxc-start-ephemeral.in
src/lxc/lxc.h
src/lxc/lxc_autostart.c
src/lxc/lxc_execute.c
src/lxc/lxc_init.c
src/lxc/lxc_monitor.c
src/lxc/lxccontainer.c
src/lxc/lxccontainer.h
src/lxc/lxclock.c
src/lxc/monitor.c
src/lxc/monitor.h
src/lxc/seccomp.c
src/lxc/start.c
src/lxc/start.h
src/lxc/utils.c
src/lxc/utils.h
src/lxc/version.h
src/tests/locktests.c
src/tests/lxc-test-checkpoint-restore
templates/lxc-alpine.in
templates/lxc-centos.in
templates/lxc-debian.in
templates/lxc-fedora.in
templates/lxc-opensuse.in
templates/lxc-oracle.in

index afdffa1..d3c343c 100644 (file)
@@ -5,7 +5,8 @@ This project accepts contributions. In order to contribute, you should
 pay attention to a few things:
 
     1 - your code must follow the coding style rules
-    2 - the format of the submission must be email patches
+    2 - the format of the submission must be email patches or github
+    pull requests
     3 - your work must be signed
 
 
@@ -24,15 +25,15 @@ http://lxr.linux.no/linux+v2.6.27/Documentation/CodingStyle
 Submitting Modifications:
 -------------------------
 
-The contributions should be email patches. The guidelines are the same
-as the patch submission for the Linux kernel except for the DCO which
-is defined below. The guidelines are defined in the
+The contributions should be email patches or github pull requests.
+The guidelines are the same as the patch submission for the Linux kernel
+except for the DCO which is defined below. The guidelines are defined in the
 'SubmittingPatches' file, available in the directory 'Documentation'
 of the Linux kernel source tree.
 
 It can be accessed online too:
 
-http://lxr.linux.no/linux+v2.6.27/Documentation/SubmittingPatches
+https://www.kernel.org/doc/Documentation/SubmittingPatches
 
 You can submit your patches to the lxc-devel@lists.linuxcontainers.org mailing
 list. Use http://lists.linuxcontainers.org/listinfo/lxc-devel to subscribe
@@ -105,4 +106,8 @@ then you just add a line saying
 
     Signed-off-by: Random J Developer <random@developer.org>
 
+You can do it by using option -s or --signoff when you commit
+
+    git commit --signoff ...
+
 using your real name (sorry, no pseudonyms or anonymous contributions.)
index 5c1c623..ac367e1 100644 (file)
@@ -11,7 +11,7 @@ have lxc-start && {
         COMPREPLY=( $( compgen -W "$(ls /usr/local/share/lxc/templates/ | sed -e 's|^lxc-||' )" "$cur" ) )
     }
 
-    _lxc-generic-n() {
+    _lxc_generic_n() {
         local cur prev
 
         COMPREPLY=()
@@ -27,7 +27,7 @@ have lxc-start && {
         return 1
     }
 
-    _lxc-generic-ns() {
+    _lxc_generic_ns() {
         local cur prev
 
         COMPREPLY=()
@@ -48,7 +48,7 @@ have lxc-start && {
         return 1
     }
 
-    _lxc-generic-t() {
+    _lxc_generic_t() {
         local cur prev
 
         COMPREPLY=()
@@ -64,7 +64,7 @@ have lxc-start && {
         return 1
     }
 
-    _lxc-generic-o() {
+    _lxc_generic_o() {
         local cur prev
 
         COMPREPLY=()
@@ -80,24 +80,24 @@ have lxc-start && {
         return 1
     }
 
-    complete -o default -F _lxc-generic-n lxc-attach
-    complete -o default -F _lxc-generic-n lxc-cgroup
-    complete -o default -F _lxc-generic-n lxc-console
-    complete -o default -F _lxc-generic-n lxc-destroy
-    complete -o default -F _lxc-generic-n lxc-device
-    complete -o default -F _lxc-generic-n lxc-execute
-    complete -o default -F _lxc-generic-n lxc-freeze
-    complete -o default -F _lxc-generic-n lxc-info
-    complete -o default -F _lxc-generic-n lxc-monitor
-    complete -o default -F _lxc-generic-n lxc-snapshot
-    complete -o default -F _lxc-generic-n lxc-start
-    complete -o default -F _lxc-generic-n lxc-stop
-    complete -o default -F _lxc-generic-n lxc-unfreeze
-
-    complete -o default -F _lxc-generic-ns lxc-wait
-
-    complete -o default -F _lxc-generic-t lxc-create
-
-    complete -o default -F _lxc-generic-o lxc-clone
-    complete -o default -F _lxc-generic-o lxc-start-ephemeral
+    complete -o default -F _lxc_generic_n lxc-attach
+    complete -o default -F _lxc_generic_n lxc-cgroup
+    complete -o default -F _lxc_generic_n lxc-console
+    complete -o default -F _lxc_generic_n lxc-destroy
+    complete -o default -F _lxc_generic_n lxc-device
+    complete -o default -F _lxc_generic_n lxc-execute
+    complete -o default -F _lxc_generic_n lxc-freeze
+    complete -o default -F _lxc_generic_n lxc-info
+    complete -o default -F _lxc_generic_n lxc-monitor
+    complete -o default -F _lxc_generic_n lxc-snapshot
+    complete -o default -F _lxc_generic_n lxc-start
+    complete -o default -F _lxc_generic_n lxc-stop
+    complete -o default -F _lxc_generic_n lxc-unfreeze
+
+    complete -o default -F _lxc_generic_ns lxc-wait
+
+    complete -o default -F _lxc_generic_t lxc-create
+
+    complete -o default -F _lxc_generic_o lxc-clone
+    complete -o default -F _lxc_generic_o lxc-start-ephemeral
 }
index 18fd48f..cbd1b79 100644 (file)
@@ -11,7 +11,7 @@ have lxc-start && {
         COMPREPLY=( $( compgen -W "$(ls @LXCTEMPLATEDIR@/ | sed -e 's|^lxc-||' )" "$cur" ) )
     }
 
-    _lxc-generic-n() {
+    _lxc_generic_n() {
         local cur prev
 
         COMPREPLY=()
@@ -27,7 +27,7 @@ have lxc-start && {
         return 1
     }
 
-    _lxc-generic-ns() {
+    _lxc_generic_ns() {
         local cur prev
 
         COMPREPLY=()
@@ -48,7 +48,7 @@ have lxc-start && {
         return 1
     }
 
-    _lxc-generic-t() {
+    _lxc_generic_t() {
         local cur prev
 
         COMPREPLY=()
@@ -64,7 +64,7 @@ have lxc-start && {
         return 1
     }
 
-    _lxc-generic-o() {
+    _lxc_generic_o() {
         local cur prev
 
         COMPREPLY=()
@@ -80,24 +80,24 @@ have lxc-start && {
         return 1
     }
 
-    complete -o default -F _lxc-generic-n lxc-attach
-    complete -o default -F _lxc-generic-n lxc-cgroup
-    complete -o default -F _lxc-generic-n lxc-console
-    complete -o default -F _lxc-generic-n lxc-destroy
-    complete -o default -F _lxc-generic-n lxc-device
-    complete -o default -F _lxc-generic-n lxc-execute
-    complete -o default -F _lxc-generic-n lxc-freeze
-    complete -o default -F _lxc-generic-n lxc-info
-    complete -o default -F _lxc-generic-n lxc-monitor
-    complete -o default -F _lxc-generic-n lxc-snapshot
-    complete -o default -F _lxc-generic-n lxc-start
-    complete -o default -F _lxc-generic-n lxc-stop
-    complete -o default -F _lxc-generic-n lxc-unfreeze
-
-    complete -o default -F _lxc-generic-ns lxc-wait
-
-    complete -o default -F _lxc-generic-t lxc-create
-
-    complete -o default -F _lxc-generic-o lxc-clone
-    complete -o default -F _lxc-generic-o lxc-start-ephemeral
+    complete -o default -F _lxc_generic_n lxc-attach
+    complete -o default -F _lxc_generic_n lxc-cgroup
+    complete -o default -F _lxc_generic_n lxc-console
+    complete -o default -F _lxc_generic_n lxc-destroy
+    complete -o default -F _lxc_generic_n lxc-device
+    complete -o default -F _lxc_generic_n lxc-execute
+    complete -o default -F _lxc_generic_n lxc-freeze
+    complete -o default -F _lxc_generic_n lxc-info
+    complete -o default -F _lxc_generic_n lxc-monitor
+    complete -o default -F _lxc_generic_n lxc-snapshot
+    complete -o default -F _lxc_generic_n lxc-start
+    complete -o default -F _lxc_generic_n lxc-stop
+    complete -o default -F _lxc_generic_n lxc-unfreeze
+
+    complete -o default -F _lxc_generic_ns lxc-wait
+
+    complete -o default -F _lxc_generic_t lxc-create
+
+    complete -o default -F _lxc_generic_o lxc-clone
+    complete -o default -F _lxc_generic_o lxc-start-ephemeral
 }
index 73ccdba..ebce36e 100644 (file)
@@ -78,13 +78,13 @@ case "$1" in
         if [ -n "$BOOTGROUPS" ]; then
             BOOTGROUPS="-g $BOOTGROUPS"
         fi
-
+        touch "$lockdir"/lxc
         # Start containers
         wait_for_bridge
 
         # Start autoboot containers first then the NULL group "onboot,".
         "$bindir"/lxc-autostart $OPTIONS $BOOTGROUPS
-        touch "$lockdir"/lxc
+        rm -f "$lockdir"/lxc
     ;;
 
     stop)
@@ -96,7 +96,6 @@ case "$1" in
         # delaying the system shutdown / reboot as much as we can since it's not
         # parallelized...  Even 5 second timout may be too long.
         "$bindir"/lxc-autostart $STOPOPTS $SHUTDOWNDELAY
-        rm -f "$lockdir"/lxc
     ;;
 
     restart|reload|force-reload)
index 988d2f9..efe64c1 100644 (file)
@@ -1,8 +1,8 @@
 #!/bin/sh -
 
 distrosysconfdir="@LXC_DISTRO_SYSCONF@"
-localstatedir="@LOCALSTATEDIR@"
 varrun="@RUNTIME_PATH@/lxc"
+varlib="@LOCALSTATEDIR@/lib"
 
 # These can be overridden in @LXC_DISTRO_SYSCONF@/lxc
 #   or in @LXC_DISTRO_SYSCONF@/lxc-net
@@ -17,13 +17,15 @@ LXC_DHCP_MAX="253"
 LXC_DHCP_CONFILE=""
 LXC_DOMAIN=""
 
+LXC_IPV6_ADDR=""
+LXC_IPV6_MASK=""
+LXC_IPV6_NETWORK=""
+LXC_IPV6_NAT="false"
+
 [ ! -f $distrosysconfdir/lxc ] || . $distrosysconfdir/lxc
 
-if [ -d "$localstatedir"/lock/subsys ]; then
-    lockdir="$localstatedir"/lock/subsys
-else
-    lockdir="$localstatedir"/lock
-fi
+use_iptables_lock="-w"
+iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
 
 _netmask2cidr ()
 {
@@ -35,75 +37,66 @@ _netmask2cidr ()
 }
 
 ifdown() {
-    which ip >/dev/null 2>&1
-    if [ $? = 0 ]; then
-        ip link set dev $1 down
-        return
-    fi
-    which ifconfig >/dev/null 2>&1
-    if [ $? = 0 ]; then
-        ifconfig $1 down
-        return
-    fi
+    ip addr flush dev $1
+    ip link set dev $1 down
 }
 
 ifup() {
-    which ip >/dev/null 2>&1
-    if [ $? = 0 ]; then
-        MASK=`_netmask2cidr ${LXC_NETMASK}`
-        CIDR_ADDR="${LXC_ADDR}/${MASK}"
-        ip addr add ${CIDR_ADDR} dev $1
-        ip link set dev $1 up
-        return
-    fi
-    which ifconfig >/dev/null 2>&1
-    if [ $? = 0 ]; then
-        ifconfig $1 $2 netmask $3 up
-        return
-    fi
+    MASK=`_netmask2cidr ${LXC_NETMASK}`
+    CIDR_ADDR="${LXC_ADDR}/${MASK}"
+    ip addr add ${CIDR_ADDR} dev $1
+    ip link set dev $1 up
 }
 
 start() {
-    [ ! -f "${lockdir}"/lxc-net ] || { exit 0; }
-
     [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; }
 
-    use_iptables_lock="-w"
-    iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
-    cleanup() {
-        # dnsmasq failed to start, clean up the bridge
-        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
-        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
-        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
-        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
-        iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
-        iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
-        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
-        iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
-        ifdown ${LXC_BRIDGE}
-        brctl delbr ${LXC_BRIDGE} || true
-    }
+    [ ! -f "${varrun}/network_up" ] || { echo "lxc-net is already running"; exit 1; }
 
     if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
-        exit 0;
+        stop force || true
     fi
 
+    FAILED=1
+
+    cleanup() {
+        set +e
+        if [ "$FAILED" = "1" ]; then
+            echo "Failed to setup lxc-net." >&2
+            stop force
+        fi
+    }
+
+    trap cleanup EXIT HUP INT TERM
+    set -e
+
     # set up the lxc network
-    brctl addbr ${LXC_BRIDGE} || { echo "Missing bridge support in kernel"; stop; exit 0; }
+    [ ! -d /sys/class/net/${LXC_BRIDGE} ] && ip link add dev ${LXC_BRIDGE} type bridge
     echo 1 > /proc/sys/net/ipv4/ip_forward
+    echo 0 > /proc/sys/net/ipv6/conf/${LXC_BRIDGE}/accept_dad || true
 
     # if we are run from systemd on a system with selinux enabled,
     # the mkdir will create /run/lxc as init_var_run_t which dnsmasq
     # can't write its pid into, so we restorecon it (to var_run_t)
     if [ ! -d "${varrun}" ]; then
         mkdir -p "${varrun}"
-        which restorecon >/dev/null 2>&1
-        if [ $? = 0 ]; then
+        if which restorecon >/dev/null 2>&1; then
             restorecon "${varrun}"
         fi
     fi
 
     ifup ${LXC_BRIDGE} ${LXC_ADDR} ${LXC_NETMASK}
+
+    LXC_IPV6_ARG=""
+    if [ -n "$LXC_IPV6_ADDR" ] && [ -n "$LXC_IPV6_MASK" ] && [ -n "$LXC_IPV6_NETWORK" ]; then
+        echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
+        echo 0 > /proc/sys/net/ipv6/conf/${LXC_BRIDGE}/autoconf
+        ip -6 addr add dev ${LXC_BRIDGE} ${LXC_IPV6_ADDR}/${LXC_IPV6_MASK}
+        if [ "$LXC_IPV6_NAT" = "true" ]; then
+            ip6tables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE
+        fi
+        LXC_IPV6_ARG="--dhcp-range=${LXC_IPV6_ADDR},ra-only --listen-address ${LXC_IPV6_ADDR}"
+    fi
     iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
     iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
     iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
@@ -118,6 +111,11 @@ start() {
         LXC_DOMAIN_ARG="-s $LXC_DOMAIN -S /$LXC_DOMAIN/"
     fi
 
+    LXD_DHCP_CONFILE_ARG=""
+    if [ -n "$LXC_DHCP_CONFILE" ]; then
+        LXC_DHCP_CONFILE_ARG="--conf-file=${LXC_DHCP_CONFILE}"
+    fi
+
     # https://lists.linuxcontainers.org/pipermail/lxc-devel/2014-October/010561.html
     for DNSMASQ_USER in lxc-dnsmasq dnsmasq nobody
     do
@@ -125,21 +123,19 @@ start() {
             break
         fi
     done
-    dnsmasq $LXC_DOMAIN_ARG -u ${DNSMASQ_USER} --strict-order --bind-interfaces --pid-file="${varrun}"/dnsmasq.pid --conf-file=${LXC_DHCP_CONFILE} --listen-address ${LXC_ADDR} --dhcp-range ${LXC_DHCP_RANGE} --dhcp-lease-max=${LXC_DHCP_MAX} --dhcp-no-override --except-interface=lo --interface=${LXC_BRIDGE} --dhcp-leasefile=/var/lib/misc/dnsmasq.${LXC_BRIDGE}.leases --dhcp-authoritative || cleanup
+
+    dnsmasq $LXC_DHCP_CONFILE_ARG $LXC_DOMAIN_ARG -u ${DNSMASQ_USER} --strict-order --bind-interfaces --pid-file="${varrun}"/dnsmasq.pid --listen-address ${LXC_ADDR} --dhcp-range ${LXC_DHCP_RANGE} --dhcp-lease-max=${LXC_DHCP_MAX} --dhcp-no-override --except-interface=lo --interface=${LXC_BRIDGE} --dhcp-leasefile="${varlib}"/misc/dnsmasq.${LXC_BRIDGE}.leases --dhcp-authoritative $LXC_IPV6_ARG || cleanup
+
     touch "${varrun}"/network_up
-    touch "${lockdir}"/lxc-net
+    FAILED=0
 }
 
 stop() {
     [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { exit 0; }
 
-    [ -f "${varrun}/network_up" ] || { exit 0; }
-    # if $LXC_BRIDGE has attached interfaces, don't shut it down
-    ls /sys/class/net/${LXC_BRIDGE}/brif/* > /dev/null 2>&1 && exit 0;
+    [ -f "${varrun}/network_up" ] || [ "$1" = "force" ] || { echo "lxc-net isn't running"; exit 1; }
 
     if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
-        use_iptables_lock="-w"
-        iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
         ifdown ${LXC_BRIDGE}
         iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
         iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
@@ -147,14 +143,20 @@ stop() {
         iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
         iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
         iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
-        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
+        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
         iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
-        pid=`cat "${varrun}"/dnsmasq.pid 2>/dev/null` && kill -9 $pid || true
+
+        if [ "$LXC_IPV6_NAT" = "true" ]; then
+            ip6tables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_IPV6_NETWORK} ! -d ${LXC_IPV6_NETWORK} -j MASQUERADE
+        fi
+
+        pid=`cat "${varrun}"/dnsmasq.pid 2>/dev/null` && kill -9 $pid
         rm -f "${varrun}"/dnsmasq.pid
-        brctl delbr ${LXC_BRIDGE}
+        # if $LXC_BRIDGE has attached interfaces, don't destroy the bridge
+        ls /sys/class/net/${LXC_BRIDGE}/brif/* > /dev/null 2>&1 || ip link delete ${LXC_BRIDGE}
     fi
+
     rm -f "${varrun}"/network_up
-    rm -f "${lockdir}"/lxc-net
 }
 
 # See how we were called.
index 4ac9496..619cd53 100755 (executable)
@@ -6,9 +6,9 @@ set -eu
 # don't load profiles if mount mediation is not supported
 SYSF=/sys/kernel/security/apparmor/features/mount/mask
 if [ -f $SYSF ]; then
-       if [ -x /lib/init/apparmor-profile-load ]; then
-               /lib/init/apparmor-profile-load usr.bin.lxc-start
-               /lib/init/apparmor-profile-load lxc-containers
+       if [ -x /lib/apparmor/profile-load ]; then
+               /lib/apparmor/profile-load usr.bin.lxc-start
+               /lib/apparmor/profile-load lxc-containers
        fi
 fi
 
index a256141..3b49c75 100644 (file)
@@ -1,6 +1,6 @@
 [Unit]
 Description=LXC Container Initialization and Autoboot Code
-After=syslog.target network.target
+After=syslog.target network.target lxc-net.service
 Wants=lxc-net.service
 
 [Service]
index 3b31bbe..7ae2569 100644 (file)
@@ -380,8 +380,8 @@ distclean-generic:
 maintainer-clean-generic:
        @echo "This command is intended for maintainers to use"
        @echo "it deletes files that may require special tools to rebuild."
-@INIT_SCRIPT_UPSTART_FALSE@install-data-local:
 @INIT_SCRIPT_UPSTART_FALSE@uninstall-local:
+@INIT_SCRIPT_UPSTART_FALSE@install-data-local:
 clean: clean-am
 
 clean-am: clean-generic mostlyclean-am
index ab79aab..ff21137 100644 (file)
@@ -36,9 +36,9 @@ pre-start script
        # don't load profiles if mount mediation is not supported
        SYSF=/sys/kernel/security/apparmor/features/mount/mask
        if [ -f $SYSF ]; then
-               if [ -x /lib/init/apparmor-profile-load ]; then
-                       /lib/init/apparmor-profile-load usr.bin.lxc-start
-                       /lib/init/apparmor-profile-load lxc-containers
+               if [ -x /lib/apparmor/profile-load ]; then
+                       /lib/apparmor/profile-load usr.bin.lxc-start
+                       /lib/apparmor/profile-load lxc-containers
                fi
        fi
 
index ee2e9e1..8a72ad0 100644 (file)
@@ -17,4 +17,4 @@ lxc.include = @LXCTEMPLATECONFIG@/common.conf
 # lxc.cap.drop = setuid           # breaks sshd,nfs statd
 # lxc.cap.drop = audit_control    # breaks sshd (set_loginuid failed)
 # lxc.cap.drop = audit_write
-lxc.cap.drop = setfcap setpcap sys_nice sys_pacct sys_rawio
+lxc.cap.drop = sys_nice sys_pacct sys_rawio
index 270e9df..6e9aa0d 100644 (file)
@@ -8,13 +8,30 @@ lxc.include = @LXCTEMPLATECONFIG@/common.conf
 # Container user ? see gentoo.common.conf
 
 # do not mount sysfs, see http://blog.bofh.it/debian/id_413
-lxc.mount.entry=mqueue dev/mqueue mqueue rw,nodev,noexec,nosuid 0 0
-lxc.mount.entry=shm dev/shm tmpfs rw,nosuid,nodev,noexec,relatime 0 0
+lxc.mount.entry=mqueue dev/mqueue mqueue rw,nodev,noexec,nosuid,create=dir 0 0
+lxc.mount.entry=shm dev/shm tmpfs rw,nosuid,nodev,noexec,relatime,create=dir 0 0
 lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0
 
-# this part is based on 'linux capabilities', see: man 7 capabilities
-#  eg: you may also wish to drop 'cap_net_raw' (though it breaks ping)
+# Capabilities
+# Uncomment these if you don't run anything that needs the capability, and
+# would like the container to run with less privilege.
 #
+# Dropping sys_admin disables container root from doing a lot of things
+# that could be bad like re-mounting lxc fstab entries rw for example,
+# but also disables some useful things like being able to nfs mount, and
+# things that are already namespaced with ns_capable() kernel checks, like
+# hostname(1).
+# lxc.cap.drop = sys_admin        # breaks systemd
+# lxc.cap.drop = net_raw          # breaks dhcp/ping
+# lxc.cap.drop = setgid           # breaks login (initgroups/setgroups)
+# lxc.cap.drop = dac_read_search  # breaks login (pam unix_chkpwd)
+# lxc.cap.drop = setuid           # breaks sshd,nfs statd
+# lxc.cap.drop = audit_control    # breaks sshd (set_loginuid failed)
+# lxc.cap.drop = audit_write
+# lxc.cap.drop = setpcap          # breaks journald
+# lxc.cap.drop = sys_resources    # breaks systemd
+lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap setpcap sys_admin sys_boot sys_nice sys_pacct sys_ptrace sys_rawio sys_resources sys_tty_config syslog
+
 # WARNING: the security vulnerability reported for 'cap_net_admin' at
 # http://mainisusuallyafunction.blogspot.com/2012/11/attacking-hardened-linux-systems-with.html
 # via JIT spraying (the BPF JIT module disabled on most systems was used
@@ -25,8 +42,3 @@ lxc.mount.entry=run run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0
 # including the kernel - and multiple layers of security on any system
 # where security is a priority.  note that not only LXC but PAX (and
 # others?) were vulnerable to this issue.
-#
-# conservative: lxc.cap.drop = sys_module mknod mac_override sys_boot
-# aggressive follows. (leaves open: chown dac_override fowner ipc_lock kill lease net_admin net_bind_service net_broadcast net_raw setgid setuid sys_chroot)
-
-lxc.cap.drop = audit_control audit_write dac_read_search fsetid ipc_owner linux_immutable mknod setfcap sys_admin sys_boot sys_pacct sys_ptrace sys_rawio sys_resource sys_tty_config syslog
index 83bcc30..590e7ad 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for lxc 1.1.2.
+# Generated by GNU Autoconf 2.69 for lxc 1.1.3.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='lxc'
 PACKAGE_TARNAME='lxc'
-PACKAGE_VERSION='1.1.2'
-PACKAGE_STRING='lxc 1.1.2'
+PACKAGE_VERSION='1.1.3'
+PACKAGE_STRING='lxc 1.1.3'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1435,7 +1435,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures lxc 1.1.2 to adapt to many kinds of systems.
+\`configure' configures lxc 1.1.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1505,7 +1505,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of lxc 1.1.2:";;
+     short | recursive ) echo "Configuration of lxc 1.1.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1665,7 +1665,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-lxc configure 1.1.2
+lxc configure 1.1.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2130,7 +2130,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by lxc $as_me 1.1.2, which was
+It was created by lxc $as_me 1.1.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2601,7 +2601,7 @@ $as_echo "no" >&6; }
        fi
 fi
 
-LXC_VERSION_BASE=1.1.2
+LXC_VERSION_BASE=1.1.3
 
 
 
@@ -2609,9 +2609,9 @@ LXC_VERSION_MAJOR=1
 
 LXC_VERSION_MINOR=1
 
-LXC_VERSION_MICRO=2
+LXC_VERSION_MICRO=3
 
-LXC_VERSION=1.1.2
+LXC_VERSION=1.1.3
 
 
 
@@ -3132,7 +3132,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='lxc'
- VERSION='1.1.2'
+ VERSION='1.1.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6380,6 +6380,79 @@ else
 $as_echo "no" >&6; }
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cgmanager_list_controllers" >&5
+$as_echo_n "checking for cgmanager_list_controllers... " >&6; }
+save_LIBS=$LIBS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cgmanager_list_controllers_sync" >&5
+$as_echo_n "checking for library containing cgmanager_list_controllers_sync... " >&6; }
+if ${ac_cv_search_cgmanager_list_controllers_sync+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char cgmanager_list_controllers_sync ();
+int
+main ()
+{
+return cgmanager_list_controllers_sync ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' cgmanager; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib -lnih -lnih-dbus -ldbus-1 $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_search_cgmanager_list_controllers_sync=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if ${ac_cv_search_cgmanager_list_controllers_sync+:} false; then :
+  break
+fi
+done
+if ${ac_cv_search_cgmanager_list_controllers_sync+:} false; then :
+
+else
+  ac_cv_search_cgmanager_list_controllers_sync=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cgmanager_list_controllers_sync" >&5
+$as_echo "$ac_cv_search_cgmanager_list_controllers_sync" >&6; }
+ac_res=$ac_cv_search_cgmanager_list_controllers_sync
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+  have_list_controllers=yes
+else
+  have_list_controllers=no
+fi
+
+LIBS=$save_LIBS
+if test "x$have_list_controllers" = "xyes"; then
+
+$as_echo "#define HAVE_CGMANAGER_LIST_CONTROLLERS 1" >>confdefs.h
+
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
 # Check for static libcap, make sure the function checked for differs from the
 # the one checked below so the cache doesn't give a wrong answer
 OLD_CFLAGS="$CFLAGS"
@@ -9874,7 +9947,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by lxc $as_me 1.1.2, which was
+This file was extended by lxc $as_me 1.1.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9944,7 +10017,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-lxc config.status 1.1.2
+lxc config.status 1.1.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 574b2cd..44a946f 100644 (file)
@@ -3,7 +3,7 @@
 
 m4_define([lxc_version_major], 1)
 m4_define([lxc_version_minor], 1)
-m4_define([lxc_version_micro], 2)
+m4_define([lxc_version_micro], 3)
 m4_define([lxc_version_beta], [])
 
 m4_define([lxc_version_base], [lxc_version_major.lxc_version_minor.lxc_version_micro])
@@ -284,6 +284,17 @@ else
        AC_MSG_RESULT([no])
 fi
 
+AC_MSG_CHECKING(for cgmanager_list_controllers)
+save_LIBS=$LIBS
+AC_SEARCH_LIBS([cgmanager_list_controllers_sync], [cgmanager], [have_list_controllers=yes], [have_list_controllers=no], [-lnih -lnih-dbus -ldbus-1])
+LIBS=$save_LIBS
+if test "x$have_list_controllers" = "xyes"; then
+       AC_DEFINE([HAVE_CGMANAGER_LIST_CONTROLLERS], 1, [Have cgmanager_list_controllers])
+       AC_MSG_RESULT([yes])
+else
+       AC_MSG_RESULT([no])
+fi
+
 # Check for static libcap, make sure the function checked for differs from the
 # the one checked below so the cache doesn't give a wrong answer
 OLD_CFLAGS="$CFLAGS"
index 929e4f7..38783dd 100644 (file)
@@ -105,6 +105,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
        </para>
       </listitem>
     </varlistentry>
+
+    <varlistentry>
+      <term><option>--version</option></term>
+      <listitem>
+        <para>
+          Show the version number.
+        </para>
+      </listitem>
+    </varlistentry>
   </variablelist>
 
 </refsect1>
index 8069ac6..912298f 100644 (file)
@@ -139,6 +139,18 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
        </para>
       </listitem>
     </varlistentry>
+
+    <varlistentry>
+      <term><option>--version</option></term>
+      <listitem>
+        <para>
+          <!--
+          Show the version number.
+          -->
+          バージョン番号を表示します。
+        </para>
+      </listitem>
+    </varlistentry>
   </variablelist>
 
 </refsect1>
index d141afb..69bea8f 100644 (file)
@@ -159,9 +159,9 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
                     <para>
                       <!--
                         Rather than performing the action, just print
-                        the container name.
+                        the container name and wait delays until starting the next container.
                         -->
-                      実際の動作は行わず、コンテナ名の表示だけを行います。
+                      å®\9fé\9a\9bã\81®å\8b\95ä½\9cã\81¯è¡\8cã\82\8fã\81\9aã\80\81ã\82³ã\83³ã\83\86ã\83\8aå\90\8dã\81¨æ¬¡ã\81®ã\82³ã\83³ã\83\86ã\83\8aã\82\92é\96\8bå§\8bã\81\99ã\82\8bã\81¾ã\81§ã\81®é\96\93é\9a\94ã\81®è¡¨ç¤ºã\81 ã\81\91ã\82\92è¡\8cã\81\84ã\81¾ã\81\99ã\80\82
                     </para>
                 </listitem>
             </varlistentry>
@@ -327,7 +327,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
     &seealso;
 
     <refsect1>
-        <title>Author</title>
+        <title><!-- Author -->作者</title>
         <para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
     </refsect1>
 </refentry>
index 9e1d1b6..92e776b 100644 (file)
@@ -106,7 +106,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
     &seealso;
 
     <refsect1>
-        <title>Author</title>
+        <title><!-- Author -->作者</title>
         <para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
     </refsect1>
 </refentry>
index 05519c2..5d5c5fa 100644 (file)
@@ -61,7 +61,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   </refsynopsisdiv>
 
   <refsect1>
-    <title>Description</title>
+    <title><!-- Description -->説明</title>
 
     <para>
       <!--
index bc3d6c6..1fb4b46 100644 (file)
@@ -55,6 +55,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
     <cmdsynopsis>
       <command>lxc-ls</command>
       <arg choice="opt">-1</arg>
+      <arg choice="opt">-P <replaceable>lxcpath</replaceable></arg>
       <arg choice="opt">--active</arg>
       <arg choice="opt">--frozen</arg>
       <arg choice="opt">--running</arg>
@@ -64,6 +65,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
       <arg choice="opt">-g <replaceable>groups</replaceable></arg>
       <arg choice="opt">--nesting</arg>
       <arg choice="opt">filter</arg>
+      <arg choice="opt">--version</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -96,6 +98,20 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
       </varlistentry>
 
       <varlistentry>
+        <term>
+          <option><optional>-P</optional></option>
+        </term>
+        <listitem>
+          <para>
+            <!--
+            Use an alternate container path. The default is @LXCPATH@.
+            -->
+            デフォルトと別のコンテナパスを使用します。デフォルトは @LXCPATH@ です。
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
        <term>
          <option><optional>--active</optional></option>
        </term>
@@ -225,6 +241,19 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>
+          <option><optional>--version</optional></option>
+        </term>
+        <listitem>
+          <para>
+            <!--
+            Show the version number.
+            -->
+            バージョン番号を表示します。
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
 
   </refsect1>
index 16e483f..673a806 100644 (file)
@@ -186,7 +186,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   &seealso;
 
   <refsect1>
-    <title>Author</title>
+    <title><!-- Author -->作者</title>
     <para>Serge Hallyn <email>serge.hallyn@ubuntu.com </email></para>
   </refsect1>
 
index 8626472..5e577ff 100644 (file)
@@ -166,8 +166,6 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
 
   </refsect1>
 
-  &commonoptions;
-
   <refsect1>
     <title>See Also</title>
 
@@ -190,7 +188,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
    </refsect1>
 
   <refsect1>
-    <title>Author</title>
+    <title><!-- Author -->作者</title>
     <para>Daniel Lezcano <email>daniel.lezcano@free.fr</email></para>
   </refsect1>
 
index 158861b..9d568be 100644 (file)
@@ -164,7 +164,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   </refsect1>
 
   <refsect1>
-    <title>Author</title>
+    <title><!-- Author -->作者</title>
     <para>Daniel Lezcano <email>daniel.lezcano@free.fr</email></para>
   </refsect1>
 
index ba231f0..4125ad3 100644 (file)
@@ -170,7 +170,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   &seealso;
 
   <refsect1>
-    <title>Author</title>
+    <title><!-- Author -->作者</title>
     <para>Serge Hallyn <email>serge.hallyn@ubuntu.com</email></para>
   </refsect1>
 
index 05f787c..4313b55 100644 (file)
@@ -170,7 +170,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   </refsect1>
 
   <refsect1>
-    <title>Author</title>
+    <title><!-- Author -->作者</title>
     <para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
   </refsect1>
 </refentry>
index 488b9dd..e11387a 100644 (file)
@@ -2151,7 +2151,7 @@ mknod errno 0
               containers.
               -->
               コンテナを追加したいコンテナグループ名を指定します。
-              (複数回使用される可能性のある) 複数の値を設定可能です。
+              複数の値を設定でき、複数回指定することもできます。
               設定されたグループは、関連する一連のコンテナを起動させるために使われます。
             </para>
           </listitem>
index c34af93..ae6a2f6 100644 (file)
@@ -220,7 +220,7 @@ by KATOH Yasufumi <karma at jazz.email.ne.jp>
   &seealso;
 
   <refsect1>
-    <title>Author</title>
+    <title><!-- Author -->作者</title>
     <para>Stéphane Graber <email>stgraber@ubuntu.com</email></para>
   </refsect1>
 </refentry>
index 3bbae61..5039c47 100644 (file)
@@ -132,7 +132,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
                 <listitem>
                     <para>
                         Rather than performing the action, just print
-                        the container name.
+                        the container name and wait delays until starting the next container.
                     </para>
                 </listitem>
             </varlistentry>
index b2125b9..fec7f38 100644 (file)
@@ -50,6 +50,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     <cmdsynopsis>
       <command>lxc-ls</command>
       <arg choice="opt">-1</arg>
+      <arg choice="opt">-P <replaceable>lxcpath</replaceable></arg>
       <arg choice="opt">--active</arg>
       <arg choice="opt">--frozen</arg>
       <arg choice="opt">--running</arg>
@@ -59,6 +60,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <arg choice="opt">-g <replaceable>groups</replaceable></arg>
       <arg choice="opt">--nesting</arg>
       <arg choice="opt">filter</arg>
+      <arg choice="opt">--version</arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
@@ -86,6 +88,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
       <varlistentry>
         <term>
+          <option><optional>-P</optional></option>
+        </term>
+        <listitem>
+          <para>
+            Use an alternate container path. The default is @LXCPATH@.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>
           <option><optional>--active</optional></option>
         </term>
         <listitem>
@@ -185,6 +198,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
           </para>
         </listitem>
       </varlistentry>
+
+      <varlistentry>
+        <term>
+          <option><optional>--version</optional></option>
+        </term>
+        <listitem>
+          <para>
+            Show the version number.
+          </para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index 07c5721..ac8af64 100644 (file)
@@ -136,8 +136,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
   </refsect1>
 
-  &commonoptions;
-
   <refsect1>
     <title>See Also</title>
 
index 75d2365..fcd9a86 100644 (file)
--- a/lxc.spec
+++ b/lxc.spec
@@ -60,7 +60,7 @@ BuildRequires: systemd
 %endif
 
 Name: lxc
-Version: 1.1.2
+Version: 1.1.3
 Release: %{?beta_rel:0.1.%{beta_rel}}%{?!beta_rel:%{norm_rel}}%{?dist}
 URL: http://linuxcontainers.org
 Source: http://linuxcontainers.org/downloads/%{name}-%{version}%{?beta_dot}.tar.gz
index 107600a..d49789d 100644 (file)
@@ -9,6 +9,9 @@
 /* Have cgmanager_get_pid_cgroup_abs_sync */
 #undef HAVE_CGMANAGER_GET_PID_CGROUP_ABS_SYNC
 
+/* Have cgmanager_list_controllers */
+#undef HAVE_CGMANAGER_LIST_CONTROLLERS
+
 /* Define to 1 if you have the `confstr' function. */
 #undef HAVE_CONFSTR
 
index 630a3e4..34180a7 100644 (file)
 #endif
 
 #if LUA_VERSION_NUM >= 503
+#ifndef luaL_checkunsigned
 #define luaL_checkunsigned(L,n) ((lua_Unsigned)luaL_checkinteger(L,n))
 #endif
+#endif
 
 #ifdef NO_CHECK_UDATA
 #define checkudata(L,i,tname)  lua_touserdata(L, i)
index 8b79c40..ce46495 100644 (file)
@@ -12,6 +12,7 @@ noinst_HEADERS = \
        conf.h \
        console.h \
        error.h \
+       initutils.h \
        list.h \
        log.h \
        lxc.h \
@@ -21,7 +22,8 @@ noinst_HEADERS = \
        namespace.h \
        start.h \
        state.h \
-       utils.h
+       utils.h \
+       criu.h
 
 if IS_BIONIC
 noinst_HEADERS += \
@@ -66,6 +68,7 @@ liblxc_so_SOURCES = \
        cgfs.c \
        cgroup.c cgroup.h \
        lxc.h \
+       initutils.c initutils.h \
        utils.c utils.h \
        sync.c sync.h \
        namespace.h namespace.c \
@@ -75,6 +78,7 @@ liblxc_so_SOURCES = \
        state.c state.h \
        log.c log.h \
        attach.c attach.h \
+       criu.c criu.h \
        \
        network.c network.h \
        nl.c nl.h \
@@ -164,7 +168,6 @@ bin_SCRIPTS = lxc-checkconfig
 
 EXTRA_DIST = \
        lxc-ls \
-       lxc-restore-net \
        lxc-top.lua
 
 if ENABLE_PYTHON
@@ -238,7 +241,7 @@ lxc_checkpoint_SOURCES = lxc_checkpoint.c
 if HAVE_STATIC_LIBCAP
 sbin_PROGRAMS += init.lxc.static
 
-init_lxc_static_SOURCES = lxc_init.c error.c log.c utils.c caps.c
+init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c
 
 if !HAVE_GETLINE
 if HAVE_FGETLN
@@ -262,8 +265,5 @@ install-exec-local: install-soPROGRAMS
 install-exec-hook:
        chmod u+s $(DESTDIR)$(libexecdir)/lxc/lxc-user-nic
 
-install-data-local:
-       install -c -m 755 lxc-restore-net $(DESTDIR)$(datadir)/lxc
-
 uninstall-local:
        $(RM) $(DESTDIR)$(libdir)/liblxc.so*
index c8ca0f0..4449452 100644 (file)
@@ -145,15 +145,15 @@ am_init_lxc_OBJECTS = lxc_init.$(OBJEXT)
 init_lxc_OBJECTS = $(am_init_lxc_OBJECTS)
 init_lxc_LDADD = $(LDADD)
 init_lxc_DEPENDENCIES = liblxc.so
-am__init_lxc_static_SOURCES_DIST = lxc_init.c error.c log.c utils.c \
-       caps.c ../include/getline.c
+am__init_lxc_static_SOURCES_DIST = lxc_init.c error.c log.c \
+       initutils.c caps.c ../include/getline.c
 am__dirstamp = $(am__leading_dot)dirstamp
 @HAVE_FGETLN_TRUE@@HAVE_GETLINE_FALSE@@HAVE_STATIC_LIBCAP_TRUE@am__objects_1 = ../include/init_lxc_static-getline.$(OBJEXT)
 @HAVE_STATIC_LIBCAP_TRUE@am_init_lxc_static_OBJECTS =  \
 @HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-lxc_init.$(OBJEXT) \
 @HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-error.$(OBJEXT) \
 @HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-log.$(OBJEXT) \
-@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-utils.$(OBJEXT) \
+@HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-initutils.$(OBJEXT) \
 @HAVE_STATIC_LIBCAP_TRUE@      init_lxc_static-caps.$(OBJEXT) \
 @HAVE_STATIC_LIBCAP_TRUE@      $(am__objects_1)
 init_lxc_static_OBJECTS = $(am_init_lxc_static_OBJECTS)
@@ -163,18 +163,18 @@ init_lxc_static_LINK = $(CCLD) $(init_lxc_static_CFLAGS) $(CFLAGS) \
 am__liblxc_so_SOURCES_DIST = arguments.c arguments.h bdev.c bdev.h \
        lxc-btrfs.h commands.c commands.h start.c start.h execute.c \
        monitor.c monitor.h console.c freezer.c error.h error.c \
-       parse.c parse.h cgfs.c cgroup.c cgroup.h lxc.h utils.c utils.h \
-       sync.c sync.h namespace.h namespace.c conf.c conf.h confile.c \
-       confile.h list.h state.c state.h log.c log.h attach.c attach.h \
-       network.c network.h nl.c nl.h rtnl.c rtnl.h genl.c genl.h \
-       caps.c caps.h lxcseccomp.h mainloop.c mainloop.h af_unix.c \
-       af_unix.h lxcutmp.c lxcutmp.h lxclock.h lxclock.c \
-       lxccontainer.c lxccontainer.h version.h lsm/nop.c lsm/lsm.h \
-       lsm/lsm.c lsm/apparmor.c lsm/selinux.c cgmanager.c \
-       ../include/ifaddrs.c ../include/ifaddrs.h ../include/openpty.c \
-       ../include/openpty.h ../include/lxcmntent.c \
-       ../include/lxcmntent.h ../include/getline.c \
-       ../include/getline.h seccomp.c
+       parse.c parse.h cgfs.c cgroup.c cgroup.h lxc.h initutils.c \
+       initutils.h utils.c utils.h sync.c sync.h namespace.h \
+       namespace.c conf.c conf.h confile.c confile.h list.h state.c \
+       state.h log.c log.h attach.c attach.h criu.c criu.h network.c \
+       network.h nl.c nl.h rtnl.c rtnl.h genl.c genl.h caps.c caps.h \
+       lxcseccomp.h mainloop.c mainloop.h af_unix.c af_unix.h \
+       lxcutmp.c lxcutmp.h lxclock.h lxclock.c lxccontainer.c \
+       lxccontainer.h version.h lsm/nop.c lsm/lsm.h lsm/lsm.c \
+       lsm/apparmor.c lsm/selinux.c cgmanager.c ../include/ifaddrs.c \
+       ../include/ifaddrs.h ../include/openpty.c ../include/openpty.h \
+       ../include/lxcmntent.c ../include/lxcmntent.h \
+       ../include/getline.c ../include/getline.h seccomp.c
 @ENABLE_APPARMOR_TRUE@am__objects_2 =  \
 @ENABLE_APPARMOR_TRUE@ lsm/liblxc_so-apparmor.$(OBJEXT)
 @ENABLE_SELINUX_TRUE@am__objects_3 = lsm/liblxc_so-selinux.$(OBJEXT)
@@ -193,11 +193,12 @@ am_liblxc_so_OBJECTS = liblxc_so-arguments.$(OBJEXT) \
        liblxc_so-monitor.$(OBJEXT) liblxc_so-console.$(OBJEXT) \
        liblxc_so-freezer.$(OBJEXT) liblxc_so-error.$(OBJEXT) \
        liblxc_so-parse.$(OBJEXT) liblxc_so-cgfs.$(OBJEXT) \
-       liblxc_so-cgroup.$(OBJEXT) liblxc_so-utils.$(OBJEXT) \
-       liblxc_so-sync.$(OBJEXT) liblxc_so-namespace.$(OBJEXT) \
-       liblxc_so-conf.$(OBJEXT) liblxc_so-confile.$(OBJEXT) \
-       liblxc_so-state.$(OBJEXT) liblxc_so-log.$(OBJEXT) \
-       liblxc_so-attach.$(OBJEXT) liblxc_so-network.$(OBJEXT) \
+       liblxc_so-cgroup.$(OBJEXT) liblxc_so-initutils.$(OBJEXT) \
+       liblxc_so-utils.$(OBJEXT) liblxc_so-sync.$(OBJEXT) \
+       liblxc_so-namespace.$(OBJEXT) liblxc_so-conf.$(OBJEXT) \
+       liblxc_so-confile.$(OBJEXT) liblxc_so-state.$(OBJEXT) \
+       liblxc_so-log.$(OBJEXT) liblxc_so-attach.$(OBJEXT) \
+       liblxc_so-criu.$(OBJEXT) liblxc_so-network.$(OBJEXT) \
        liblxc_so-nl.$(OBJEXT) liblxc_so-rtnl.$(OBJEXT) \
        liblxc_so-genl.$(OBJEXT) liblxc_so-caps.$(OBJEXT) \
        liblxc_so-mainloop.$(OBJEXT) liblxc_so-af_unix.$(OBJEXT) \
@@ -404,9 +405,9 @@ am__can_run_installinfo = \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
 am__noinst_HEADERS_DIST = arguments.h attach.h bdev.h caps.h cgroup.h \
-       conf.h console.h error.h list.h log.h lxc.h lxc-btrfs.h \
-       lxclock.h monitor.h namespace.h start.h state.h utils.h \
-       ../include/ifaddrs.h ../include/openpty.h \
+       conf.h console.h error.h initutils.h list.h log.h lxc.h \
+       lxc-btrfs.h lxclock.h monitor.h namespace.h start.h state.h \
+       utils.h criu.h ../include/ifaddrs.h ../include/openpty.h \
        ../include/lxcmntent.h ../include/getline.h
 HEADERS = $(noinst_HEADERS) $(pkginclude_HEADERS)
 am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
@@ -598,23 +599,24 @@ pkginclude_HEADERS = \
        version.h
 
 noinst_HEADERS = arguments.h attach.h bdev.h caps.h cgroup.h conf.h \
-       console.h error.h list.h log.h lxc.h lxc-btrfs.h lxclock.h \
-       monitor.h namespace.h start.h state.h utils.h $(am__append_1) \
-       $(am__append_2)
+       console.h error.h initutils.h list.h log.h lxc.h lxc-btrfs.h \
+       lxclock.h monitor.h namespace.h start.h state.h utils.h criu.h \
+       $(am__append_1) $(am__append_2)
 sodir = $(libdir)
 LSM_SOURCES = lsm/nop.c lsm/lsm.h lsm/lsm.c $(am__append_3) \
        $(am__append_4)
 liblxc_so_SOURCES = arguments.c arguments.h bdev.c bdev.h lxc-btrfs.h \
        commands.c commands.h start.c start.h execute.c monitor.c \
        monitor.h console.c freezer.c error.h error.c parse.c parse.h \
-       cgfs.c cgroup.c cgroup.h lxc.h utils.c utils.h sync.c sync.h \
-       namespace.h namespace.c conf.c conf.h confile.c confile.h \
-       list.h state.c state.h log.c log.h attach.c attach.h network.c \
-       network.h nl.c nl.h rtnl.c rtnl.h genl.c genl.h caps.c caps.h \
-       lxcseccomp.h mainloop.c mainloop.h af_unix.c af_unix.h \
-       lxcutmp.c lxcutmp.h lxclock.h lxclock.c lxccontainer.c \
-       lxccontainer.h version.h $(LSM_SOURCES) $(am__append_5) \
-       $(am__append_6) $(am__append_7) $(am__append_13)
+       cgfs.c cgroup.c cgroup.h lxc.h initutils.c initutils.h utils.c \
+       utils.h sync.c sync.h namespace.h namespace.c conf.c conf.h \
+       confile.c confile.h list.h state.c state.h log.c log.h \
+       attach.c attach.h criu.c criu.h network.c network.h nl.c nl.h \
+       rtnl.c rtnl.h genl.c genl.h caps.c caps.h lxcseccomp.h \
+       mainloop.c mainloop.h af_unix.c af_unix.h lxcutmp.c lxcutmp.h \
+       lxclock.h lxclock.c lxccontainer.c lxccontainer.h version.h \
+       $(LSM_SOURCES) $(am__append_5) $(am__append_6) $(am__append_7) \
+       $(am__append_13)
 AM_CFLAGS = -I$(top_srcdir)/src -DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
        -DLXCPATH=\"$(LXCPATH)\" \
        -DLXC_GLOBAL_CONF=\"$(LXC_GLOBAL_CONF)\" \
@@ -639,7 +641,6 @@ liblxc_so_LDADD = $(CAP_LIBS) $(APPARMOR_LIBS) $(SELINUX_LIBS) \
 bin_SCRIPTS = lxc-checkconfig $(am__append_16) $(am__append_17)
 EXTRA_DIST = \
        lxc-ls \
-       lxc-restore-net \
        lxc-top.lua
 
 AM_LDFLAGS = -Wl,-E $(am__append_18)
@@ -670,7 +671,8 @@ lxc_usernsexec_SOURCES = lxc_usernsexec.c
 lxc_user_nic_SOURCES = lxc_user_nic.c network.c network.h
 lxc_checkpoint_SOURCES = lxc_checkpoint.c
 @HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_SOURCES = lxc_init.c error.c \
-@HAVE_STATIC_LIBCAP_TRUE@      log.c utils.c caps.c $(am__append_20)
+@HAVE_STATIC_LIBCAP_TRUE@      log.c initutils.c caps.c \
+@HAVE_STATIC_LIBCAP_TRUE@      $(am__append_20)
 @HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_LDFLAGS = -static
 @HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_LDADD = @CAP_LIBS@
 @HAVE_STATIC_LIBCAP_TRUE@init_lxc_static_CFLAGS = $(AM_CFLAGS) -DNO_LXC_CONF
@@ -1076,9 +1078,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@../include/$(DEPDIR)/liblxc_so-openpty.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-caps.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-error.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-initutils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-log.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-lxc_init.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/init_lxc_static-utils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-af_unix.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-arguments.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-attach.Po@am__quote@
@@ -1091,10 +1093,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-conf.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-confile.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-console.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-criu.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-error.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-execute.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-freezer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-genl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-initutils.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-log.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-lxccontainer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liblxc_so-lxclock.Po@am__quote@
@@ -1200,19 +1204,19 @@ init_lxc_static-log.obj: log.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-log.obj `if test -f 'log.c'; then $(CYGPATH_W) 'log.c'; else $(CYGPATH_W) '$(srcdir)/log.c'; fi`
 
-init_lxc_static-utils.o: utils.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-utils.o -MD -MP -MF $(DEPDIR)/init_lxc_static-utils.Tpo -c -o init_lxc_static-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-utils.Tpo $(DEPDIR)/init_lxc_static-utils.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils.c' object='init_lxc_static-utils.o' libtool=no @AMDEPBACKSLASH@
+init_lxc_static-initutils.o: initutils.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-initutils.o -MD -MP -MF $(DEPDIR)/init_lxc_static-initutils.Tpo -c -o init_lxc_static-initutils.o `test -f 'initutils.c' || echo '$(srcdir)/'`initutils.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-initutils.Tpo $(DEPDIR)/init_lxc_static-initutils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='initutils.c' object='init_lxc_static-initutils.o' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-initutils.o `test -f 'initutils.c' || echo '$(srcdir)/'`initutils.c
 
-init_lxc_static-utils.obj: utils.c
-@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-utils.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-utils.Tpo -c -o init_lxc_static-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
-@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-utils.Tpo $(DEPDIR)/init_lxc_static-utils.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='utils.c' object='init_lxc_static-utils.obj' libtool=no @AMDEPBACKSLASH@
+init_lxc_static-initutils.obj: initutils.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-initutils.obj -MD -MP -MF $(DEPDIR)/init_lxc_static-initutils.Tpo -c -o init_lxc_static-initutils.obj `if test -f 'initutils.c'; then $(CYGPATH_W) 'initutils.c'; else $(CYGPATH_W) '$(srcdir)/initutils.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/init_lxc_static-initutils.Tpo $(DEPDIR)/init_lxc_static-initutils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='initutils.c' object='init_lxc_static-initutils.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-utils.obj `if test -f 'utils.c'; then $(CYGPATH_W) 'utils.c'; else $(CYGPATH_W) '$(srcdir)/utils.c'; fi`
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -c -o init_lxc_static-initutils.obj `if test -f 'initutils.c'; then $(CYGPATH_W) 'initutils.c'; else $(CYGPATH_W) '$(srcdir)/initutils.c'; fi`
 
 init_lxc_static-caps.o: caps.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(init_lxc_static_CFLAGS) $(CFLAGS) -MT init_lxc_static-caps.o -MD -MP -MF $(DEPDIR)/init_lxc_static-caps.Tpo -c -o init_lxc_static-caps.o `test -f 'caps.c' || echo '$(srcdir)/'`caps.c
@@ -1410,6 +1414,20 @@ liblxc_so-cgroup.obj: cgroup.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -c -o liblxc_so-cgroup.obj `if test -f 'cgroup.c'; then $(CYGPATH_W) 'cgroup.c'; else $(CYGPATH_W) '$(srcdir)/cgroup.c'; fi`
 
+liblxc_so-initutils.o: initutils.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-initutils.o -MD -MP -MF $(DEPDIR)/liblxc_so-initutils.Tpo -c -o liblxc_so-initutils.o `test -f 'initutils.c' || echo '$(srcdir)/'`initutils.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-initutils.Tpo $(DEPDIR)/liblxc_so-initutils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='initutils.c' object='liblxc_so-initutils.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -c -o liblxc_so-initutils.o `test -f 'initutils.c' || echo '$(srcdir)/'`initutils.c
+
+liblxc_so-initutils.obj: initutils.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-initutils.obj -MD -MP -MF $(DEPDIR)/liblxc_so-initutils.Tpo -c -o liblxc_so-initutils.obj `if test -f 'initutils.c'; then $(CYGPATH_W) 'initutils.c'; else $(CYGPATH_W) '$(srcdir)/initutils.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-initutils.Tpo $(DEPDIR)/liblxc_so-initutils.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='initutils.c' object='liblxc_so-initutils.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -c -o liblxc_so-initutils.obj `if test -f 'initutils.c'; then $(CYGPATH_W) 'initutils.c'; else $(CYGPATH_W) '$(srcdir)/initutils.c'; fi`
+
 liblxc_so-utils.o: utils.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-utils.o -MD -MP -MF $(DEPDIR)/liblxc_so-utils.Tpo -c -o liblxc_so-utils.o `test -f 'utils.c' || echo '$(srcdir)/'`utils.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-utils.Tpo $(DEPDIR)/liblxc_so-utils.Po
@@ -1522,6 +1540,20 @@ liblxc_so-attach.obj: attach.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -c -o liblxc_so-attach.obj `if test -f 'attach.c'; then $(CYGPATH_W) 'attach.c'; else $(CYGPATH_W) '$(srcdir)/attach.c'; fi`
 
+liblxc_so-criu.o: criu.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-criu.o -MD -MP -MF $(DEPDIR)/liblxc_so-criu.Tpo -c -o liblxc_so-criu.o `test -f 'criu.c' || echo '$(srcdir)/'`criu.c
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-criu.Tpo $(DEPDIR)/liblxc_so-criu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='criu.c' object='liblxc_so-criu.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -c -o liblxc_so-criu.o `test -f 'criu.c' || echo '$(srcdir)/'`criu.c
+
+liblxc_so-criu.obj: criu.c
+@am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-criu.obj -MD -MP -MF $(DEPDIR)/liblxc_so-criu.Tpo -c -o liblxc_so-criu.obj `if test -f 'criu.c'; then $(CYGPATH_W) 'criu.c'; else $(CYGPATH_W) '$(srcdir)/criu.c'; fi`
+@am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-criu.Tpo $(DEPDIR)/liblxc_so-criu.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='criu.c' object='liblxc_so-criu.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -c -o liblxc_so-criu.obj `if test -f 'criu.c'; then $(CYGPATH_W) 'criu.c'; else $(CYGPATH_W) '$(srcdir)/criu.c'; fi`
+
 liblxc_so-network.o: network.c
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liblxc_so_CFLAGS) $(CFLAGS) -MT liblxc_so-network.o -MD -MP -MF $(DEPDIR)/liblxc_so-network.Tpo -c -o liblxc_so-network.o `test -f 'network.c' || echo '$(srcdir)/'`network.c
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/liblxc_so-network.Tpo $(DEPDIR)/liblxc_so-network.Po
@@ -1969,8 +2001,7 @@ info: info-am
 
 info-am:
 
-install-data-am: install-data-local install-pkgincludeHEADERS \
-       install-soPROGRAMS
+install-data-am: install-pkgincludeHEADERS install-soPROGRAMS
 
 install-dvi: install-dvi-am
 
@@ -2031,8 +2062,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \
        ctags-am distclean distclean-compile distclean-generic \
        distclean-tags distdir dvi dvi-am html html-am info info-am \
        install install-am install-binPROGRAMS install-binSCRIPTS \
-       install-data install-data-am install-data-local install-dvi \
-       install-dvi-am install-exec install-exec-am install-exec-hook \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-exec-hook \
        install-exec-local install-html install-html-am install-info \
        install-info-am install-man install-pdf install-pdf-am \
        install-pkgincludeHEADERS install-pkglibexecPROGRAMS \
@@ -2057,9 +2088,6 @@ install-exec-local: install-soPROGRAMS
 install-exec-hook:
        chmod u+s $(DESTDIR)$(libexecdir)/lxc/lxc-user-nic
 
-install-data-local:
-       install -c -m 755 lxc-restore-net $(DESTDIR)$(datadir)/lxc
-
 uninstall-local:
        $(RM) $(DESTDIR)$(libdir)/liblxc.so*
 
index 69dafd4..436ae7a 100644 (file)
 
 lxc_log_define(lxc_attach, lxc);
 
+int lsm_set_label_at(int procfd, int on_exec, char* lsm_label) {
+       int labelfd = -1;
+       int ret = 0;
+       const char* name;
+       char* command = NULL;
+
+       name = lsm_name();
+
+       if (strcmp(name, "nop") == 0)
+               goto out;
+
+       if (strcmp(name, "none") == 0)
+               goto out;
+
+       /* We don't support on-exec with AppArmor */
+       if (strcmp(name, "AppArmor") == 0)
+               on_exec = 0;
+
+       if (on_exec) {
+               labelfd = openat(procfd, "self/attr/exec", O_RDWR);
+       }
+       else {
+               labelfd = openat(procfd, "self/attr/current", O_RDWR);
+       }
+
+       if (labelfd < 0) {
+               SYSERROR("Unable to open LSM label");
+               ret = -1;
+               goto out;
+       }
+
+       if (strcmp(name, "AppArmor") == 0) {
+               int size;
+
+               command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1);
+               if (!command) {
+                       SYSERROR("Failed to write apparmor profile");
+                       ret = -1;
+                       goto out;
+               }
+
+               size = sprintf(command, "changeprofile %s", lsm_label);
+               if (size < 0) {
+                       SYSERROR("Failed to write apparmor profile");
+                       ret = -1;
+                       goto out;
+               }
+
+               if (write(labelfd, command, size + 1) < 0) {
+                       SYSERROR("Unable to set LSM label");
+                       ret = -1;
+                       goto out;
+               }
+       }
+       else if (strcmp(name, "SELinux") == 0) {
+               if (write(labelfd, lsm_label, strlen(lsm_label) + 1) < 0) {
+                       SYSERROR("Unable to set LSM label");
+                       ret = -1;
+                       goto out;
+               }
+       }
+       else {
+               ERROR("Unable to restore label for unknown LSM: %s", name);
+               ret = -1;
+               goto out;
+       }
+
+out:
+       free(command);
+
+       if (labelfd != -1)
+               close(labelfd);
+
+       return ret;
+}
+
 static struct lxc_proc_context_info *lxc_proc_get_context_info(pid_t pid)
 {
        struct lxc_proc_context_info *info = calloc(1, sizeof(*info));
@@ -570,6 +646,7 @@ struct attach_clone_payload {
        struct lxc_proc_context_info* init_ctx;
        lxc_attach_exec_t exec_function;
        void* exec_payload;
+       int procfd;
 };
 
 static int attach_child_main(void* data);
@@ -622,6 +699,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
        char* cwd;
        char* new_cwd;
        int ipc_sockets[2];
+       int procfd;
        signed long personality;
 
        if (!options)
@@ -833,6 +911,13 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                rexit(-1);
        }
 
+       procfd = open("/proc", O_DIRECTORY | O_RDONLY);
+       if (procfd < 0) {
+               SYSERROR("Unable to open /proc");
+               shutdown(ipc_sockets[1], SHUT_RDWR);
+               rexit(-1);
+       }
+
        /* attach now, create another subprocess later, since pid namespaces
         * only really affect the children of the current process
         */
@@ -860,7 +945,8 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
                        .options = options,
                        .init_ctx = init_ctx,
                        .exec_function = exec_function,
-                       .exec_payload = exec_payload
+                       .exec_payload = exec_payload,
+                       .procfd = procfd
                };
                /* We use clone_parent here to make this subprocess a direct child of
                 * the initial process. Then this intermediate process can exit and
@@ -898,6 +984,7 @@ static int attach_child_main(void* data)
 {
        struct attach_clone_payload* payload = (struct attach_clone_payload*)data;
        int ipc_socket = payload->ipc_socket;
+       int procfd = payload->procfd;
        lxc_attach_options_t* options = payload->options;
        struct lxc_proc_context_info* init_ctx = payload->init_ctx;
 #if HAVE_SYS_PERSONALITY_H
@@ -1038,13 +1125,11 @@ static int attach_child_main(void* data)
        close(ipc_socket);
 
        /* set new apparmor profile/selinux context */
-       if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM)) {
+       if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
                int on_exec;
 
                on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
-               ret = lsm_process_label_set(init_ctx->lsm_label,
-                               init_ctx->container->lxc_conf, 0, on_exec);
-               if (ret < 0) {
+               if (lsm_set_label_at(procfd, on_exec, init_ctx->lsm_label) < 0) {
                        rexit(-1);
                }
        }
@@ -1095,6 +1180,9 @@ static int attach_child_main(void* data)
                }
        }
 
+       /* we don't need proc anymore */
+       close(procfd);
+
        /* we're done, so we can now do whatever the user intended us to do */
        rexit(payload->exec_function(payload->exec_payload));
 }
index cf7c043..ada3958 100644 (file)
 #define LO_FLAGS_AUTOCLEAR 4
 #endif
 
+#ifndef LOOP_CTL_GET_FREE
+#define LOOP_CTL_GET_FREE 0x4C82
+#endif
+
 #define DEFAULT_FS_SIZE 1073741824
 #define DEFAULT_FSTYPE "ext3"
 
@@ -94,7 +98,7 @@ static int do_rsync(const char *src, const char *dest)
        s[l-2] = '/';
        s[l-1] = '\0';
 
-       execlp("rsync", "rsync", "-a", s, dest, (char *)NULL);
+       execlp("rsync", "rsync", "-aHX", s, dest, (char *)NULL);
        exit(1);
 }
 
@@ -224,12 +228,8 @@ static int do_mkfs(const char *path, const char *fstype)
 
        // If the file is not a block device, we don't want mkfs to ask
        // us about whether to proceed.
-       close(0);
-       close(1);
-       close(2);
-       open("/dev/zero", O_RDONLY);
-       open("/dev/null", O_RDWR);
-       open("/dev/null", O_RDWR);
+       if (null_stdfds() < 0)
+               exit(1);
        execlp("mkfs", "mkfs", "-t", fstype, path, NULL);
        exit(1);
 }
@@ -1253,7 +1253,7 @@ int btrfs_list_get_path_rootid(int fd, u64 *treeid)
        return 0;
 }
 
-static bool is_btrfs_fs(const char *path)
+bool is_btrfs_fs(const char *path)
 {
        int fd, ret;
        struct btrfs_ioctl_space_args sargs;
@@ -1531,7 +1531,7 @@ static int btrfs_do_destroy_subvol(const char *path)
 
        fd = open(newfull, O_RDONLY);
        if (fd < 0) {
-               ERROR("Error opening %s", newfull);
+               SYSERROR("Error opening %s", newfull);
                free(newfull);
                return -1;
        }
@@ -1829,6 +1829,13 @@ ignore_search:
        return btrfs_do_destroy_subvol(path);
 }
 
+bool btrfs_try_remove_subvol(const char *path)
+{
+       if (!btrfs_detect(path))
+               return false;
+       return btrfs_recursive_destroy(path) == 0;
+}
+
 static int btrfs_destroy(struct bdev *orig)
 {
        return btrfs_recursive_destroy(orig->src);
@@ -1865,7 +1872,7 @@ static int loop_detect(const char *path)
        return 0;
 }
 
-static int find_free_loopdev(int *retfd, char *namep)
+static int find_free_loopdev_no_control(int *retfd, char *namep)
 {
        struct dirent dirent, *direntp;
        struct loop_info64 lo;
@@ -1905,6 +1912,26 @@ static int find_free_loopdev(int *retfd, char *namep)
        return 0;
 }
 
+static int find_free_loopdev(int *retfd, char *namep)
+{
+       int rc, fd = -1;
+       int ctl = open("/dev/loop-control", O_RDWR);
+       if (ctl < 0)
+               return find_free_loopdev_no_control(retfd, namep);
+       rc = ioctl(ctl, LOOP_CTL_GET_FREE);
+       if (rc >= 0) {
+               snprintf(namep, 100, "/dev/loop%d", rc);
+               fd = open(namep, O_RDWR);
+       }
+       close(ctl);
+       if (fd == -1) {
+               ERROR("No loop device found");
+               return -1;
+       }
+       *retfd = fd;
+       return 0;
+}
+
 static int loop_mount(struct bdev *bdev)
 {
        int lfd, ffd = -1, ret = -1;
@@ -2210,6 +2237,11 @@ static int overlayfs_mount(struct bdev *bdev)
                return -22;
        }
 
+       if (mkdir_p(work, 0755) < 0 && errno != EEXIST) {
+               free(mntdata);
+               return -22;
+       }
+
        // TODO We should check whether bdev->src is a blockdev, and if so
        // but for now, only support overlays of a basic directory
 
@@ -2552,12 +2584,12 @@ static int aufs_detect(const char *path)
 //
 static int aufs_mount(struct bdev *bdev)
 {
-       char *options, *dup, *lower, *upper, *rundir;
+       char *options, *dup, *lower, *upper;
        int len;
        unsigned long mntflags;
        char *mntdata;
-       char *runpath;
        int ret;
+       const char *xinopath = "/dev/shm/aufs.xino";
 
        if (strcmp(bdev->type, "aufs"))
                return -22;
@@ -2583,41 +2615,24 @@ static int aufs_mount(struct bdev *bdev)
        // TODO We should check whether bdev->src is a blockdev, and if so
        // but for now, only support aufs of a basic directory
 
-       rundir = get_rundir();
-       if (!rundir)
-               return -1;
-
-       len = strlen(rundir) + strlen("/lxc") + 1;
-       runpath = alloca(len);
-       ret = snprintf(runpath, len, "%s/lxc", rundir);
-       if (ret < 0 || ret >= len) {
-               free(mntdata);
-               free(rundir);
-               return -1;
-       }
-       if (mkdir_p(runpath, 0755) < 0) {
-               free(mntdata);
-               free(rundir);
-               return -1;
-       }
-
        // AUFS does not work on top of certain filesystems like (XFS or Btrfs)
-       // so add xino=RUNDIR/lxc/aufs.xino parameter to mount options
+       // so add xino=/dev/shm/aufs.xino parameter to mount options.
+       // The same xino option can be specified to multiple aufs mounts, and
+       // a xino file is not shared among multiple aufs mounts.
        //
        // see http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg02587.html
+       //     http://www.mail-archive.com/aufs-users@lists.sourceforge.net/msg05126.html
        if (mntdata) {
-               len = strlen(lower) + strlen(upper) + strlen(runpath) + strlen("br==rw:=ro,,xino=/aufs.xino") + strlen(mntdata) + 1;
+               len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,,xino=") + strlen(mntdata) + 1;
                options = alloca(len);
-               ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s/aufs.xino", upper, lower, mntdata, runpath);
+               ret = snprintf(options, len, "br=%s=rw:%s=ro,%s,xino=%s", upper, lower, mntdata, xinopath);
        }
        else {
-               len = strlen(lower) + strlen(upper) + strlen(runpath) + strlen("br==rw:=ro,xino=/aufs.xino") + 1;
+               len = strlen(lower) + strlen(upper) + strlen(xinopath) + strlen("br==rw:=ro,xino=") + 1;
                options = alloca(len);
-               ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s/aufs.xino", upper, lower, runpath);
+               ret = snprintf(options, len, "br=%s=rw:%s=ro,xino=%s", upper, lower, xinopath);
        }
 
-       free(rundir);
-
        if (ret < 0 || ret >= len) {
                free(mntdata);
                return -1;
@@ -2660,6 +2675,9 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
        if (mkdir_p(new->dest, 0755) < 0)
                return -1;
 
+       if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0)
+               WARN("Failed to update ownership of %s", new->dest);
+
        if (strcmp(orig->type, "dir") == 0) {
                char *delta, *lastslash;
                int ret, len, lastslashidx;
@@ -2684,6 +2702,8 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
                        free(delta);
                        return -1;
                }
+               if (am_unpriv() && chown_mapped_root(delta, conf) < 0)
+                       WARN("Failed to update ownership of %s", delta);
 
                // the src will be 'aufs:lowerdir:upperdir'
                len = strlen(delta) + strlen(orig->src) + 12;
@@ -2717,7 +2737,23 @@ static int aufs_clonepaths(struct bdev *orig, struct bdev *new, const char *oldn
                        free(osrc);
                        return -ENOMEM;
                }
-               if (do_rsync(odelta, ndelta) < 0) {
+               if ((ret = mkdir(ndelta, 0755)) < 0 && errno != EEXIST) {
+                       SYSERROR("error: mkdir %s", ndelta);
+                       free(osrc);
+                       free(ndelta);
+                       return -1;
+               }
+               if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
+                       WARN("Failed to update ownership of %s", ndelta);
+
+               struct rsync_data_char rdata;
+               rdata.src = odelta;
+               rdata.dest = ndelta;
+               if (am_unpriv())
+                       ret = userns_exec_1(conf, rsync_delta_wrapper, &rdata);
+               else
+                       ret = rsync_delta(&rdata);
+               if (ret) {
                        free(osrc);
                        free(ndelta);
                        ERROR("copying aufs delta");
@@ -3306,6 +3342,7 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
                // (unless snap && b->type == dir, in which case it will be
                // overlayfs -- which is also allowed)
                if (strcmp(b->type, "dir") == 0 ||
+                               strcmp(b->type, "aufs") == 0 ||
                                strcmp(b->type, "overlayfs") == 0 ||
                                strcmp(b->type, "btrfs") == 0 ||
                                strcmp(b->type, "loop") == 0)
@@ -3315,8 +3352,11 @@ static bool unpriv_snap_allowed(struct bdev *b, const char *t, bool snap,
 
        // unprivileged users can copy and snapshot dir, overlayfs,
        // and loop.  In particular, not zfs, btrfs, or lvm.
-       if (strcmp(t, "dir") == 0 || strcmp(t, "overlayfs") == 0 ||
-                       strcmp(t, "btrfs") == 0 || strcmp(t, "loop") == 0)
+       if (strcmp(t, "dir") == 0 ||
+               strcmp(t, "aufs") == 0 ||
+               strcmp(t, "overlayfs") == 0 ||
+               strcmp(t, "btrfs") == 0 ||
+               strcmp(t, "loop") == 0)
                return true;
        return false;
 }
index d97b9df..428b3b7 100644 (file)
 #include "config.h"
 #include <stdint.h>
 #include <lxc/lxccontainer.h>
+#include <sys/mount.h>
+
+
+/* define constants if the kernel/glibc headers don't define them */
+#ifndef MS_DIRSYNC
+#define MS_DIRSYNC 128
+#endif
+
+#ifndef MS_REC
+#define MS_REC 16384
+#endif
+
+#ifndef MNT_DETACH
+#define MNT_DETACH 2
+#endif
+
+#ifndef MS_SLAVE
+#define MS_SLAVE (1<<19)
+#endif
+
+#ifndef MS_RELATIME
+#define MS_RELATIME (1 << 21)
+#endif
+
+#ifndef MS_STRICTATIME
+#define MS_STRICTATIME (1 << 24)
+#endif
 
 struct bdev;
 
@@ -105,30 +132,4 @@ bool attach_block_device(struct lxc_conf *conf);
 void detach_block_device(struct lxc_conf *conf);
 
 bool rootfs_is_blockdev(struct lxc_conf *conf);
-
-/* define constants if the kernel/glibc headers don't define them */
-#ifndef MS_DIRSYNC
-#define MS_DIRSYNC  128
-#endif
-
-#ifndef MS_REC
-#define MS_REC 16384
-#endif
-
-#ifndef MNT_DETACH
-#define MNT_DETACH 2
-#endif
-
-#ifndef MS_SLAVE
-#define MS_SLAVE (1<<19)
-#endif
-
-#ifndef MS_RELATIME
-#define MS_RELATIME (1 << 21)
-#endif
-
-#ifndef MS_STRICTATIME
-#define MS_STRICTATIME (1 << 24)
-#endif
-
 #endif
index 11a5925..fcb3cde 100644 (file)
@@ -1886,14 +1886,19 @@ static int do_cgroup_set(const char *cgroup_path, const char *sub_filename,
 static int do_setup_cgroup_limits(struct cgfs_data *d,
                           struct lxc_list *cgroup_settings, bool do_devices)
 {
-       struct lxc_list *iterator;
+       struct lxc_list *iterator, *sorted_cgroup_settings, *next;
        struct lxc_cgroup *cg;
        int ret = -1;
 
        if (lxc_list_empty(cgroup_settings))
                return 0;
 
-       lxc_list_for_each(iterator, cgroup_settings) {
+       sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings);
+       if (!sorted_cgroup_settings) {
+               return -1;
+       }
+
+       lxc_list_for_each(iterator, sorted_cgroup_settings) {
                cg = iterator->elem;
 
                if (do_devices == !strncmp("devices", cg->subsystem, 7)) {
@@ -1916,6 +1921,11 @@ static int do_setup_cgroup_limits(struct cgfs_data *d,
        ret = 0;
        INFO("cgroup has been setup");
 out:
+       lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) {
+               lxc_list_del(iterator);
+               free(iterator);
+       }
+       free(sorted_cgroup_settings);
        return ret;
 }
 
index fe8913e..c143bea 100644 (file)
@@ -39,6 +39,7 @@
 #include <sys/mount.h>
 #include <netinet/in.h>
 #include <net/if.h>
+#include <poll.h>
 
 #include "error.h"
 #include "commands.h"
@@ -347,6 +348,7 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
 {
        int sv[2] = {-1, -1}, optval = 1, ret = -1;
        char buf[1];
+       struct pollfd fds;
 
        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
                SYSERROR("Error creating socketpair");
@@ -370,10 +372,10 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
        }
        /* now send credentials */
 
-       fd_set rfds;
-       FD_ZERO(&rfds);
-       FD_SET(sv[0], &rfds);
-       if (select(sv[0]+1, &rfds, NULL, NULL, NULL) < 0) {
+       fds.fd = sv[0];
+       fds.events = POLLIN;
+       fds.revents = 0;
+       if (poll(&fds, 1, -1) <= 0) {
                ERROR("Error getting go-ahead from server: %s", strerror(errno));
                goto out;
        }
@@ -385,9 +387,10 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
                SYSERROR("%s: Error sending pid over SCM_CREDENTIAL", __func__);
                goto out;
        }
-       FD_ZERO(&rfds);
-       FD_SET(sv[0], &rfds);
-       if (select(sv[0]+1, &rfds, NULL, NULL, NULL) < 0) {
+       fds.fd = sv[0];
+       fds.events = POLLIN;
+       fds.revents = 0;
+       if (poll(&fds, 1, -1) <= 0) {
                ERROR("Error getting go-ahead from server: %s", strerror(errno));
                goto out;
        }
@@ -399,9 +402,10 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
                SYSERROR("%s: Error sending pid over SCM_CREDENTIAL", __func__);
                goto out;
        }
-       FD_ZERO(&rfds);
-       FD_SET(sv[0], &rfds);
-       if (select(sv[0]+1, &rfds, NULL, NULL, NULL) < 0) {
+       fds.fd = sv[0];
+       fds.events = POLLIN;
+       fds.revents = 0;
+       if (poll(&fds, 1, -1) <= 0) {
                ERROR("Error getting go-ahead from server: %s", strerror(errno));
                goto out;
        }
@@ -814,6 +818,32 @@ out:
        return pids_len;
 }
 
+#if HAVE_CGMANAGER_LIST_CONTROLLERS
+static bool lxc_list_controllers(char ***list)
+{
+       if (!cgm_dbus_connect()) {
+               ERROR("Error connecting to cgroup manager");
+               return false;
+       }
+       if (cgmanager_list_controllers_sync(NULL, cgroup_manager, list) != 0) {
+               NihError *nerr;
+               nerr = nih_error_get();
+               ERROR("call to cgmanager_list_controllers_sync failed: %s", nerr->message);
+               nih_free(nerr);
+               cgm_dbus_disconnect();
+               return false;
+       }
+
+       cgm_dbus_disconnect();
+       return true;
+}
+#else
+static bool lxc_list_controllers(char ***list)
+{
+       return false;
+}
+#endif
+
 static inline void free_abs_cgroup(char *cgroup)
 {
        if (!cgroup)
@@ -1089,11 +1119,82 @@ static void cull_user_controllers(void)
        }
 }
 
+static bool in_comma_list(const char *inword, const char *cgroup_use)
+{
+       char *e;
+       size_t inlen = strlen(inword), len;
+
+       do {
+               e = strchr(cgroup_use, ',');
+               len = e ? e - cgroup_use : strlen(cgroup_use);
+               if (len == inlen && strncmp(inword, cgroup_use, len) == 0)
+                       return true;
+               cgroup_use = e + 1;
+       } while (e);
+
+       return false;
+}
+
+static bool in_subsystem_list(const char *c)
+{
+       int i;
+
+       for (i = 0; i < nr_subsystems; i++) {
+               if (strcmp(c, subsystems[i]) == 0)
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * If /etc/lxc/lxc.conf specifies lxc.cgroup.use = "freezer,memory",
+ * then clear out any other subsystems, and make sure that freezer
+ * and memory are both enabled
+ */
+static bool verify_and_prune(const char *cgroup_use)
+{
+       const char *p;
+       char *e;
+       int i, j;
+
+       for (p = cgroup_use; p && *p; p = e + 1) {
+               e = strchr(p, ',');
+               if (e)
+                       *e = '\0';
+
+               if (!in_subsystem_list(p)) {
+                       ERROR("Controller %s required by lxc.cgroup.use but not available\n", p);
+                       return false;
+               }
+
+               if (e)
+                       *e = ',';
+               if (!e)
+                       break;
+       }
+
+       for (i = 0; i < nr_subsystems;) {
+               if (in_comma_list(subsystems[i], cgroup_use)) {
+                       i++;
+                       continue;
+               }
+               free(subsystems[i]);
+               for (j = i;  j < nr_subsystems-1; j++)
+                       subsystems[j] = subsystems[j+1];
+               subsystems[nr_subsystems-1] = NULL;
+               nr_subsystems--;
+       }
+
+       return true;
+}
+
 static bool collect_subsytems(void)
 {
        char *line = NULL;
+       nih_local char **cgm_subsys_list = NULL;
        size_t sz = 0;
-       FILE *f;
+       FILE *f = NULL;
 
        if (subsystems) // already initialized
                return true;
@@ -1104,6 +1205,20 @@ static bool collect_subsytems(void)
        subsystems_inone[0] = "all";
        subsystems_inone[1] = NULL;
 
+       if (lxc_list_controllers(&cgm_subsys_list)) {
+               while (cgm_subsys_list[nr_subsystems]) {
+                       char **tmp = NIH_MUST( realloc(subsystems,
+                                               (nr_subsystems+2)*sizeof(char *)) );
+                       tmp[nr_subsystems] = NIH_MUST(
+                                       strdup(cgm_subsys_list[nr_subsystems++]) );
+                       subsystems = tmp;
+               }
+               if (nr_subsystems)
+                       subsystems[nr_subsystems] = NULL;
+               goto collected;
+       }
+
+       INFO("cgmanager_list_controllers failed, falling back to /proc/self/cgroups");
        f = fopen_cloexec("/proc/self/cgroup", "r");
        if (!f) {
                f = fopen_cloexec("/proc/1/cgroup", "r");
@@ -1143,18 +1258,37 @@ static bool collect_subsytems(void)
                }
        }
        fclose(f);
+       f = NULL;
 
        free(line);
+       line = NULL;
+
+collected:
        if (!nr_subsystems) {
                ERROR("No cgroup subsystems found");
                return false;
        }
 
+       /* make sure that cgroup.use can be and is honored */
+       const char *cgroup_use = lxc_global_config_value("lxc.cgroup.use");
+       if (!cgroup_use && errno != 0)
+               goto out_good;
+       if (cgroup_use) {
+               if (!verify_and_prune(cgroup_use)) {
+                       free_subsystems();
+                       return false;
+               }
+               subsystems_inone[0] = NIH_MUST( strdup(cgroup_use) );
+               cgm_all_controllers_same = false;
+       }
+
+out_good:
        return true;
 
 out_free:
        free(line);
-       fclose(f);
+       if (f)
+               fclose(f);
        free_subsystems();
        return false;
 }
@@ -1214,7 +1348,7 @@ static bool cgm_unfreeze(void *hdata)
 static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool do_devices)
 {
        struct cgm_data *d = hdata;
-       struct lxc_list *iterator;
+       struct lxc_list *iterator, *sorted_cgroup_settings, *next;
        struct lxc_cgroup *cg;
        bool ret = false;
 
@@ -1229,7 +1363,12 @@ static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool
                return false;
        }
 
-       lxc_list_for_each(iterator, cgroup_settings) {
+       sorted_cgroup_settings = sort_cgroup_settings(cgroup_settings);
+       if (!sorted_cgroup_settings) {
+               return false;
+       }
+
+       lxc_list_for_each(iterator, sorted_cgroup_settings) {
                char controller[100], *p;
                cg = iterator->elem;
                if (do_devices != !strncmp("devices", cg->subsystem, 7))
@@ -1257,6 +1396,11 @@ static bool cgm_setup_limits(void *hdata, struct lxc_list *cgroup_settings, bool
        ret = true;
        INFO("cgroup limits have been setup");
 out:
+       lxc_list_for_each_safe(iterator, sorted_cgroup_settings, next) {
+               lxc_list_del(iterator);
+               free(iterator);
+       }
+       free(sorted_cgroup_settings);
        cgm_dbus_disconnect();
        return ret;
 }
@@ -1297,16 +1441,8 @@ static bool cgm_attach(const char *name, const char *lxcpath, pid_t pid)
                return false;
        }
 
-       check_supports_multiple_controllers(pid);
-
-       if (cgm_all_controllers_same)
-               slist = subsystems_inone;
-
        for (i = 0; slist[i]; i++) {
-               if (slist == subsystems_inone)
-                       cgroup = try_get_abs_cgroup(name, lxcpath, subsystems[0]);
-               else
-                       cgroup = try_get_abs_cgroup(name, lxcpath, slist[i]);
+               cgroup = try_get_abs_cgroup(name, lxcpath, slist[i]);
                if (!cgroup) {
                        ERROR("Failed to get cgroup for controller %s", slist[i]);
                        cgm_dbus_disconnect();
index 4249c6c..d37112b 100644 (file)
@@ -1368,10 +1368,8 @@ int prepare_ramfs_root(char *root)
                        break;
        }
 
-       if (umount2("./proc", MNT_DETACH)) {
-               SYSERROR("Unable to umount /proc");
-               return -1;
-       }
+       /* This also can be skipped if a container uses unserns */
+       umount2("./proc", MNT_DETACH);
 
        /* It is weird, but chdir("..") moves us in a new root */
        if (chdir("..") == -1) {
@@ -2613,9 +2611,11 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
        char veth2buf[IFNAMSIZ], *veth2;
        int err;
 
-       if (netdev->priv.veth_attr.pair)
+       if (netdev->priv.veth_attr.pair) {
                veth1 = netdev->priv.veth_attr.pair;
-       else {
+               if (handler->conf->reboot)
+                       lxc_netdev_delete_by_name(veth1);
+       } else {
                err = snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
                if (err >= sizeof(veth1buf)) { /* can't *really* happen, but... */
                        ERROR("veth1 name too long");
@@ -3545,48 +3545,6 @@ int ttys_shift_ids(struct lxc_conf *c)
        return 0;
 }
 
-/*
- * _do_tmp_proc_mount: Mount /proc inside container if not already
- * mounted
- *
- * @rootfs : the rootfs where proc should be mounted
- *
- * Returns < 0 on failure, 0 if the correct proc was already mounted
- * and 1 if a new proc was mounted.
- */
-static int do_tmp_proc_mount(const char *rootfs)
-{
-       char path[MAXPATHLEN];
-       char link[20];
-       int linklen, ret;
-
-       ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs);
-       if (ret < 0 || ret >= MAXPATHLEN) {
-               SYSERROR("proc path name too long");
-               return -1;
-       }
-       memset(link, 0, 20);
-       linklen = readlink(path, link, 20);
-       INFO("I am %d, /proc/self points to '%s'", getpid(), link);
-       ret = snprintf(path, MAXPATHLEN, "%s/proc", rootfs);
-       if (linklen < 0) /* /proc not mounted */
-               goto domount;
-       /* can't be longer than rootfs/proc/1 */
-       if (strncmp(link, "1", linklen) != 0) {
-               /* wrong /procs mounted */
-               umount2(path, MNT_DETACH); /* ignore failure */
-               goto domount;
-       }
-       /* the right proc is already mounted */
-       return 0;
-
-domount:
-       if (mount("proc", path, "proc", 0, NULL))
-               return -1;
-       INFO("Mounted /proc in container for security transition");
-       return 1;
-}
-
 int tmp_proc_mount(struct lxc_conf *lxc_conf)
 {
        int mounted;
@@ -3598,7 +3556,7 @@ int tmp_proc_mount(struct lxc_conf *lxc_conf)
                } else
                        mounted = 1;
        } else
-               mounted = do_tmp_proc_mount(lxc_conf->rootfs.mount);
+               mounted = mount_proc_if_needed(lxc_conf->rootfs.mount);
        if (mounted == -1) {
                SYSERROR("failed to mount /proc in the container.");
                return -1;
@@ -4245,6 +4203,8 @@ void lxc_conf_free(struct lxc_conf *conf)
 {
        if (!conf)
                return;
+       if (current_config == conf)
+               current_config = NULL;
        free(conf->console.log_path);
        free(conf->console.path);
        free(conf->rootfs.mount);
@@ -4555,3 +4515,58 @@ void suggest_default_idmap(void)
        free(gname);
        free(uname);
 }
+
+static void free_cgroup_settings(struct lxc_list *result)
+{
+       struct lxc_list *iterator, *next;
+
+       lxc_list_for_each_safe(iterator, result, next) {
+               lxc_list_del(iterator);
+               free(iterator);
+       }
+       free(result);
+}
+
+/*
+ * Return the list of cgroup_settings sorted according to the following rules
+ * 1. Put memory.limit_in_bytes before memory.memsw.limit_in_bytes
+ */
+struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings)
+{
+       struct lxc_list *result;
+       struct lxc_list *memsw_limit = NULL;
+       struct lxc_list *it = NULL;
+       struct lxc_cgroup *cg = NULL;
+       struct lxc_list *item = NULL;
+
+       result = malloc(sizeof(*result));
+       if (!result) {
+               ERROR("failed to allocate memory to sort cgroup settings");
+               return NULL;
+       }
+       lxc_list_init(result);
+
+       /*Iterate over the cgroup settings and copy them to the output list*/
+       lxc_list_for_each(it, cgroup_settings) {
+               item = malloc(sizeof(*item));
+               if (!item) {
+                       ERROR("failed to allocate memory to sort cgroup settings");
+                       free_cgroup_settings(result);
+                       return NULL;
+               }
+               item->elem = it->elem;
+               cg = it->elem;
+               if (strcmp(cg->subsystem, "memory.memsw.limit_in_bytes") == 0) {
+                       /* Store the memsw_limit location */
+                       memsw_limit = item;
+               } else if (strcmp(cg->subsystem, "memory.limit_in_bytes") == 0 && memsw_limit != NULL) {
+                       /* lxc.cgroup.memory.memsw.limit_in_bytes is found before 
+                        * lxc.cgroup.memory.limit_in_bytes, swap these two items */
+                       item->elem = memsw_limit->elem;
+                       memsw_limit->elem = it->elem;
+               }
+               lxc_list_add_tail(result, item);
+       }
+
+       return result;
+}
index f3f8fd5..c01e1a4 100644 (file)
@@ -430,4 +430,5 @@ extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
 void remount_all_slave(void);
 extern void suggest_default_idmap(void);
 FILE *write_mount_file(struct lxc_list *mount);
+struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings);
 #endif
index 8189351..dcfeac9 100644 (file)
@@ -192,6 +192,63 @@ static const struct signame signames[] = {
        { SIGTSTP,   "TSTP" },
        { SIGTTIN,   "TTIN" },
        { SIGTTOU,   "TTOU" },
+#ifdef SIGTRAP
+       { SIGTRAP,   "TRAP" },
+#endif
+#ifdef SIGIOT
+       { SIGIOT,    "IOT" },
+#endif
+#ifdef SIGEMT
+       { SIGEMT,    "EMT" },
+#endif
+#ifdef SIGBUS
+       { SIGBUS,    "BUS" },
+#endif
+#ifdef SIGSTKFLT
+       { SIGSTKFLT, "STKFLT" },
+#endif
+#ifdef SIGCLD
+       { SIGCLD,    "CLD" },
+#endif
+#ifdef SIGURG
+       { SIGURG,    "URG" },
+#endif
+#ifdef SIGXCPU
+       { SIGXCPU,   "XCPU" },
+#endif
+#ifdef SIGXFSZ
+       { SIGXFSZ,   "XFSZ" },
+#endif
+#ifdef SIGVTALRM
+       { SIGVTALRM, "VTALRM" },
+#endif
+#ifdef SIGPROF
+       { SIGPROF,   "PROF" },
+#endif
+#ifdef SIGWINCH
+       { SIGWINCH,  "WINCH" },
+#endif
+#ifdef SIGIO
+       { SIGIO,     "IO" },
+#endif
+#ifdef SIGPOLL
+       { SIGPOLL,   "POLL" },
+#endif
+#ifdef SIGINFO
+       { SIGINFO,   "INFO" },
+#endif
+#ifdef SIGLOST
+       { SIGLOST,   "LOST" },
+#endif
+#ifdef SIGPWR
+       { SIGPWR,    "PWR" },
+#endif
+#ifdef SIGUNUSED
+       { SIGUNUSED, "UNUSED" },
+#endif
+#ifdef SIGSYS
+       { SIGSYS,    "SYS" },
+#endif
 };
 
 static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
new file mode 100644 (file)
index 0000000..798036a
--- /dev/null
@@ -0,0 +1,541 @@
+/*
+ * lxc: linux Container library
+ *
+ * Copyright © 2014-2015 Canonical Ltd.
+ *
+ * Authors:
+ * Tycho Andersen <tycho.andersen@canonical.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#define _GNU_SOURCE
+#include <assert.h>
+#include <linux/limits.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "config.h"
+
+#include "bdev.h"
+#include "cgroup.h"
+#include "conf.h"
+#include "criu.h"
+#include "log.h"
+#include "lxc.h"
+#include "lxclock.h"
+#include "network.h"
+#include "utils.h"
+
+lxc_log_define(lxc_criu, lxc);
+
+void exec_criu(struct criu_opts *opts)
+{
+       char **argv, log[PATH_MAX];
+       int static_args = 22, argc = 0, i, ret;
+       int netnr = 0;
+       struct lxc_list *it;
+
+       char buf[4096];
+
+       /* The command line always looks like:
+        * criu $(action) --tcp-established --file-locks --link-remap --force-irmap \
+        * --manage-cgroups action-script foo.sh -D $(directory) \
+        * -o $(directory)/$(action).log --ext-mount-map auto
+        * --enable-external-sharing --enable-external-masters
+        * --enable-fs hugetlbfs --enable-fs tracefs
+        * +1 for final NULL */
+
+       if (strcmp(opts->action, "dump") == 0) {
+               /* -t pid */
+               static_args += 2;
+
+               /* --leave-running */
+               if (!opts->stop)
+                       static_args++;
+       } else if (strcmp(opts->action, "restore") == 0) {
+               /* --root $(lxc_mount_point) --restore-detached
+                * --restore-sibling --pidfile $foo --cgroup-root $foo */
+               static_args += 8;
+       } else {
+               return;
+       }
+
+       if (opts->verbose)
+               static_args++;
+
+       ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->directory, opts->action);
+       if (ret < 0 || ret >= PATH_MAX) {
+               ERROR("logfile name too long\n");
+               return;
+       }
+
+       argv = malloc(static_args * sizeof(*argv));
+       if (!argv)
+               return;
+
+       memset(argv, 0, static_args * sizeof(*argv));
+
+#define DECLARE_ARG(arg)                                       \
+       do {                                                    \
+               if (arg == NULL) {                              \
+                       ERROR("Got NULL argument for criu");    \
+                       goto err;                               \
+               }                                               \
+               argv[argc++] = strdup(arg);                     \
+               if (!argv[argc-1])                              \
+                       goto err;                               \
+       } while (0)
+
+       argv[argc++] = on_path("criu", NULL);
+       if (!argv[argc-1]) {
+               ERROR("Couldn't find criu binary\n");
+               goto err;
+       }
+
+       DECLARE_ARG(opts->action);
+       DECLARE_ARG("--tcp-established");
+       DECLARE_ARG("--file-locks");
+       DECLARE_ARG("--link-remap");
+       DECLARE_ARG("--force-irmap");
+       DECLARE_ARG("--manage-cgroups");
+       DECLARE_ARG("--ext-mount-map");
+       DECLARE_ARG("auto");
+       DECLARE_ARG("--enable-external-sharing");
+       DECLARE_ARG("--enable-external-masters");
+       DECLARE_ARG("--enable-fs");
+       DECLARE_ARG("hugetlbfs");
+       DECLARE_ARG("--enable-fs");
+       DECLARE_ARG("tracefs");
+       DECLARE_ARG("-D");
+       DECLARE_ARG(opts->directory);
+       DECLARE_ARG("-o");
+       DECLARE_ARG(log);
+
+       if (opts->verbose)
+               DECLARE_ARG("-vvvvvv");
+
+       if (strcmp(opts->action, "dump") == 0) {
+               char pid[32];
+
+               if (sprintf(pid, "%d", opts->c->init_pid(opts->c)) < 0)
+                       goto err;
+
+               DECLARE_ARG("-t");
+               DECLARE_ARG(pid);
+               if (!opts->stop)
+                       DECLARE_ARG("--leave-running");
+       } else if (strcmp(opts->action, "restore") == 0) {
+               void *m;
+               int additional;
+
+               DECLARE_ARG("--root");
+               DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
+               DECLARE_ARG("--restore-detached");
+               DECLARE_ARG("--restore-sibling");
+               DECLARE_ARG("--pidfile");
+               DECLARE_ARG(opts->pidfile);
+               DECLARE_ARG("--cgroup-root");
+               DECLARE_ARG(opts->cgroup_path);
+
+               additional = lxc_list_len(&opts->c->lxc_conf->network) * 2;
+
+               m = realloc(argv, (argc + additional + 1) * sizeof(*argv));     \
+               if (!m)                                                         \
+                       goto err;                                               \
+               argv = m;
+
+               lxc_list_for_each(it, &opts->c->lxc_conf->network) {
+                       char eth[128], *veth;
+                       struct lxc_netdev *n = it->elem;
+
+                       if (n->type != LXC_NET_VETH)
+                               continue;
+
+                       if (n->name) {
+                               if (strlen(n->name) >= sizeof(eth))
+                                       goto err;
+                               strncpy(eth, n->name, sizeof(eth));
+                       } else
+                               sprintf(eth, "eth%d", netnr);
+
+                       veth = n->priv.veth_attr.pair;
+
+                       ret = snprintf(buf, sizeof(buf), "%s=%s@%s", eth, veth, n->link);
+                       if (ret < 0 || ret >= sizeof(buf))
+                               goto err;
+
+                       DECLARE_ARG("--veth-pair");
+                       DECLARE_ARG(buf);
+               }
+
+       }
+
+       argv[argc] = NULL;
+
+#undef DECLARE_ARG
+       execv(argv[0], argv);
+err:
+       for (i = 0; argv[i]; i++)
+               free(argv[i]);
+       free(argv);
+}
+
+/*
+ * Check to see if the criu version is recent enough for all the features we
+ * use. This version allows either CRIU_VERSION or (CRIU_GITID_VERSION and
+ * CRIU_GITID_PATCHLEVEL) to work, enabling users building from git to c/r
+ * things potentially before a version is released with a particular feature.
+ *
+ * The intent is that when criu development slows down, we can drop this, but
+ * for now we shouldn't attempt to c/r with versions that we know won't work.
+ */
+static bool criu_version_ok()
+{
+       int pipes[2];
+       pid_t pid;
+
+       if (pipe(pipes) < 0) {
+               SYSERROR("pipe() failed");
+               return false;
+       }
+
+       pid = fork();
+       if (pid < 0) {
+               SYSERROR("fork() failed");
+               return false;
+       }
+
+       if (pid == 0) {
+               char *args[] = { "criu", "--version", NULL };
+               char *path;
+               close(pipes[0]);
+
+               close(STDERR_FILENO);
+               if (dup2(pipes[1], STDOUT_FILENO) < 0)
+                       exit(1);
+
+               path = on_path("criu", NULL);
+               if (!path)
+                       exit(1);
+
+               execv(path, args);
+               exit(1);
+       } else {
+               FILE *f;
+               char version[1024];
+               int patch;
+
+               close(pipes[1]);
+               if (wait_for_pid(pid) < 0) {
+                       close(pipes[0]);
+                       SYSERROR("execing criu failed, is it installed?");
+                       return false;
+               }
+
+               f = fdopen(pipes[0], "r");
+               if (!f) {
+                       close(pipes[0]);
+                       return false;
+               }
+
+               if (fscanf(f, "Version: %1024[^\n]s", version) != 1)
+                       goto version_error;
+
+               if (fgetc(f) != '\n')
+                       goto version_error;
+
+               if (strcmp(version, CRIU_VERSION) >= 0)
+                       goto version_match;
+
+               if (fscanf(f, "GitID: v%1024[^-]s", version) != 1)
+                       goto version_error;
+
+               if (fgetc(f) != '-')
+                       goto version_error;
+
+               if (fscanf(f, "%d", &patch) != 1)
+                       goto version_error;
+
+               if (strcmp(version, CRIU_GITID_VERSION) < 0)
+                       goto version_error;
+
+               if (patch < CRIU_GITID_PATCHLEVEL)
+                       goto version_error;
+
+version_match:
+               fclose(f);
+               return true;
+
+version_error:
+               fclose(f);
+               ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore\n");
+               return false;
+       }
+}
+
+/* Check and make sure the container has a configuration that we know CRIU can
+ * dump. */
+bool criu_ok(struct lxc_container *c)
+{
+       struct lxc_list *it;
+       bool found_deny_rule = false;
+
+       if (!criu_version_ok())
+               return false;
+
+       if (geteuid()) {
+               ERROR("Must be root to checkpoint\n");
+               return false;
+       }
+
+       /* We only know how to restore containers with veth networks. */
+       lxc_list_for_each(it, &c->lxc_conf->network) {
+               struct lxc_netdev *n = it->elem;
+               switch(n->type) {
+               case LXC_NET_VETH:
+               case LXC_NET_NONE:
+               case LXC_NET_EMPTY:
+                       break;
+               default:
+                       ERROR("Found network that is not VETH or NONE\n");
+                       return false;
+               }
+       }
+
+       // These requirements come from http://criu.org/LXC
+       if (c->lxc_conf->console.path &&
+                       strcmp(c->lxc_conf->console.path, "none") != 0) {
+               ERROR("lxc.console must be none\n");
+               return false;
+       }
+
+       if (c->lxc_conf->tty != 0) {
+               ERROR("lxc.tty must be 0\n");
+               return false;
+       }
+
+       lxc_list_for_each(it, &c->lxc_conf->cgroup) {
+               struct lxc_cgroup *cg = it->elem;
+               if (strcmp(cg->subsystem, "devices.deny") == 0 &&
+                               strcmp(cg->value, "c 5:1 rwm") == 0) {
+
+                       found_deny_rule = true;
+                       break;
+               }
+       }
+
+       if (!found_deny_rule) {
+               ERROR("couldn't find devices.deny = c 5:1 rwm");
+               return false;
+       }
+
+       return true;
+}
+
+static bool restore_net_info(struct lxc_container *c)
+{
+       struct lxc_list *it;
+       bool has_error = true;
+
+       if (container_mem_lock(c))
+               return false;
+
+       lxc_list_for_each(it, &c->lxc_conf->network) {
+               struct lxc_netdev *netdev = it->elem;
+               char template[IFNAMSIZ];
+
+               if (netdev->type != LXC_NET_VETH)
+                       continue;
+
+               snprintf(template, sizeof(template), "vethXXXXXX");
+
+               if (!netdev->priv.veth_attr.pair)
+                       netdev->priv.veth_attr.pair = lxc_mkifname(template);
+
+               if (!netdev->priv.veth_attr.pair)
+                       goto out_unlock;
+       }
+
+       has_error = false;
+
+out_unlock:
+       container_mem_unlock(c);
+       return !has_error;
+}
+
+void do_restore(struct lxc_container *c, int pipe, char *directory, bool verbose)
+{
+       pid_t pid;
+       char pidfile[L_tmpnam];
+       struct lxc_handler *handler;
+       int status;
+
+       if (!tmpnam(pidfile))
+               goto out;
+
+       handler = lxc_init(c->name, c->lxc_conf, c->config_path);
+       if (!handler)
+               goto out;
+
+       if (!cgroup_init(handler)) {
+               ERROR("failed initing cgroups");
+               goto out_fini_handler;
+       }
+
+       if (!cgroup_create(handler)) {
+               ERROR("failed creating groups");
+               goto out_fini_handler;
+       }
+
+       if (!restore_net_info(c)) {
+               ERROR("failed restoring network info");
+               goto out_fini_handler;
+       }
+
+       resolve_clone_flags(handler);
+
+       pid = fork();
+       if (pid < 0)
+               goto out_fini_handler;
+
+       if (pid == 0) {
+               struct criu_opts os;
+               struct lxc_rootfs *rootfs;
+
+               close(pipe);
+               pipe = -1;
+
+               if (unshare(CLONE_NEWNS))
+                       goto out_fini_handler;
+
+               /* CRIU needs the lxc root bind mounted so that it is the root of some
+                * mount. */
+               rootfs = &c->lxc_conf->rootfs;
+
+               if (rootfs_is_blockdev(c->lxc_conf)) {
+                       if (do_rootfs_setup(c->lxc_conf, c->name, c->config_path) < 0)
+                               goto out_fini_handler;
+               } else {
+                       if (mkdir(rootfs->mount, 0755) < 0 && errno != EEXIST)
+                               goto out_fini_handler;
+
+                       if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) {
+                               SYSERROR("remount / to private failed");
+                               goto out_fini_handler;
+                       }
+
+                       if (mount(rootfs->path, rootfs->mount, NULL, MS_BIND, NULL) < 0) {
+                               rmdir(rootfs->mount);
+                               goto out_fini_handler;
+                       }
+               }
+
+               os.action = "restore";
+               os.directory = directory;
+               os.c = c;
+               os.pidfile = pidfile;
+               os.verbose = verbose;
+               os.cgroup_path = cgroup_canonical_path(handler);
+
+               /* exec_criu() returning is an error */
+               exec_criu(&os);
+               umount(rootfs->mount);
+               rmdir(rootfs->mount);
+               goto out_fini_handler;
+       } else {
+               int ret;
+               char title[2048];
+
+               pid_t w = waitpid(pid, &status, 0);
+               if (w == -1) {
+                       SYSERROR("waitpid");
+                       goto out_fini_handler;
+               }
+
+               ret = write(pipe, &status, sizeof(status));
+               close(pipe);
+               pipe = -1;
+
+               if (sizeof(status) != ret) {
+                       SYSERROR("failed to write all of status");
+                       goto out_fini_handler;
+               }
+
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status)) {
+                               goto out_fini_handler;
+                       } else {
+                               int ret;
+                               FILE *f = fopen(pidfile, "r");
+                               if (!f) {
+                                       SYSERROR("couldn't read restore's init pidfile %s\n", pidfile);
+                                       goto out_fini_handler;
+                               }
+
+                               ret = fscanf(f, "%d", (int*) &handler->pid);
+                               fclose(f);
+                               if (unlink(pidfile) < 0 && errno != ENOENT)
+                                       SYSERROR("unlinking pidfile failed");
+
+                               if (ret != 1) {
+                                       ERROR("reading restore pid failed");
+                                       goto out_fini_handler;
+                               }
+
+                               if (lxc_set_state(c->name, handler, RUNNING))
+                                       goto out_fini_handler;
+                       }
+               } else {
+                       ERROR("CRIU was killed with signal %d\n", WTERMSIG(status));
+                       goto out_fini_handler;
+               }
+
+               /*
+                * See comment in lxcapi_start; we don't care if these
+                * fail because it's just a beauty thing. We just
+                * assign the return here to silence potential.
+                */
+               ret = snprintf(title, sizeof(title), "[lxc monitor] %s %s", c->config_path, c->name);
+               ret = setproctitle(title);
+
+               ret = lxc_poll(c->name, handler);
+               if (ret)
+                       lxc_abort(c->name, handler);
+               lxc_fini(c->name, handler);
+               exit(ret);
+       }
+
+out_fini_handler:
+       lxc_fini(c->name, handler);
+       if (unlink(pidfile) < 0 && errno != ENOENT)
+               SYSERROR("unlinking pidfile failed");
+
+out:
+       if (pipe >= 0) {
+               status = 1;
+               if (write(pipe, &status, sizeof(status)) != sizeof(status)) {
+                       SYSERROR("writing status failed");
+               }
+               close(pipe);
+       }
+
+       exit(1);
+}
diff --git a/src/lxc/criu.h b/src/lxc/criu.h
new file mode 100644 (file)
index 0000000..df63625
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * lxc: linux Container library
+ *
+ * Copyright © 2014-2015 Canonical Ltd.
+ *
+ * Authors:
+ * Tycho Andersen <tycho.andersen@canonical.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __LXC_CRIU_H
+#define __LXC_CRIU_H
+
+#include <stdbool.h>
+
+#include <lxc/lxccontainer.h>
+
+// We require either the criu major/minor version, or the criu GITID if criu
+// was built from git.
+#define CRIU_VERSION           "1.6"
+
+#define CRIU_GITID_VERSION     "1.5"
+#define CRIU_GITID_PATCHLEVEL  133
+
+struct criu_opts {
+       /* The type of criu invocation, one of "dump" or "restore" */
+       char *action;
+
+       /* The directory to pass to criu */
+       char *directory;
+
+       /* The container to dump */
+       struct lxc_container *c;
+
+       /* Enable criu verbose mode? */
+       bool verbose;
+
+       /* dump: stop the container or not after dumping? */
+       bool stop;
+
+       /* restore: the file to write the init process' pid into */
+       char *pidfile;
+       const char *cgroup_path;
+};
+
+void exec_criu(struct criu_opts *opts);
+
+/* Check and make sure the container has a configuration that we know CRIU can
+ * dump. */
+bool criu_ok(struct lxc_container *c);
+
+// do_restore never returns, the calling process is used as the
+// monitor process. do_restore calls exit() if it fails.
+void do_restore(struct lxc_container *c, int pipe, char *directory, bool verbose);
+
+#endif
index a0f7ff1..cfc81a7 100644 (file)
@@ -64,7 +64,7 @@ static int execute_start(struct lxc_handler *handler, void* data)
 
        initpath = choose_init(NULL);
        if (!initpath) {
-               ERROR("Failed to find an lxc-init");
+               ERROR("Failed to find an lxc-init or init.lxc");
                goto out2;
        }
        argv[i++] = initpath;
@@ -111,7 +111,7 @@ static struct lxc_operations execute_start_ops = {
 };
 
 int lxc_execute(const char *name, char *const argv[], int quiet,
-               struct lxc_conf *conf, const char *lxcpath)
+               struct lxc_conf *conf, const char *lxcpath, bool backgrounded)
 {
        struct execute_args args = {
                .argv = argv,
@@ -122,5 +122,5 @@ int lxc_execute(const char *name, char *const argv[], int quiet,
                return -1;
 
        conf->is_execute = 1;
-       return __lxc_start(name, conf, &execute_start_ops, &args, lxcpath);
+       return __lxc_start(name, conf, &execute_start_ops, &args, lxcpath, backgrounded);
 }
diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c
new file mode 100644 (file)
index 0000000..dbb5d52
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <daniel.lezcano at free.fr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "initutils.h"
+#include "log.h"
+
+lxc_log_define(lxc_initutils, lxc);
+
+static int mount_fs(const char *source, const char *target, const char *type)
+{
+       /* the umount may fail */
+       if (umount(target))
+               WARN("failed to unmount %s : %s", target, strerror(errno));
+
+       if (mount(source, target, type, 0, NULL)) {
+               ERROR("failed to mount %s : %s", target, strerror(errno));
+               return -1;
+       }
+
+       DEBUG("'%s' mounted on '%s'", source, target);
+
+       return 0;
+}
+
+extern void lxc_setup_fs(void)
+{
+       if (mount_fs("proc", "/proc", "proc"))
+               INFO("failed to remount proc");
+
+       /* if we can't mount /dev/shm, continue anyway */
+       if (mount_fs("shmfs", "/dev/shm", "tmpfs"))
+               INFO("failed to mount /dev/shm");
+
+       /* If we were able to mount /dev/shm, then /dev exists */
+       /* Sure, but it's read-only per config :) */
+       if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) {
+               DEBUG("failed to create '/dev/mqueue'");
+               return;
+       }
+
+       /* continue even without posix message queue support */
+       if (mount_fs("mqueue", "/dev/mqueue", "mqueue"))
+               INFO("failed to mount /dev/mqueue");
+}
+
+static char *copy_global_config_value(char *p)
+{
+       int len = strlen(p);
+       char *retbuf;
+
+       if (len < 1)
+               return NULL;
+       if (p[len-1] == '\n') {
+               p[len-1] = '\0';
+               len--;
+       }
+       retbuf = malloc(len+1);
+       if (!retbuf)
+               return NULL;
+       strcpy(retbuf, p);
+       return retbuf;
+}
+
+const char *lxc_global_config_value(const char *option_name)
+{
+       static const char * const options[][2] = {
+               { "lxc.bdev.lvm.vg",        DEFAULT_VG      },
+               { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL },
+               { "lxc.bdev.zfs.root",      DEFAULT_ZFSROOT },
+               { "lxc.lxcpath",            NULL            },
+               { "lxc.default_config",     NULL            },
+               { "lxc.cgroup.pattern",     NULL            },
+               { "lxc.cgroup.use",         NULL            },
+               { NULL, NULL },
+       };
+
+       /* placed in the thread local storage pool for non-bionic targets */
+#ifdef HAVE_TLS
+       static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
+#else
+       static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
+#endif
+
+       /* user_config_path is freed as soon as it is used */
+       char *user_config_path = NULL;
+
+       /*
+        * The following variables are freed at bottom unconditionally.
+        * So NULL the value if it is to be returned to the caller
+        */
+       char *user_default_config_path = NULL;
+       char *user_lxc_path = NULL;
+       char *user_cgroup_pattern = NULL;
+
+       if (geteuid() > 0) {
+               const char *user_home = getenv("HOME");
+               if (!user_home)
+                       user_home = "/";
+
+               user_config_path = malloc(sizeof(char) * (22 + strlen(user_home)));
+               user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home)));
+               user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home)));
+
+               sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
+               sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
+               sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
+               user_cgroup_pattern = strdup("lxc/%n");
+       }
+       else {
+               user_config_path = strdup(LXC_GLOBAL_CONF);
+               user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
+               user_lxc_path = strdup(LXCPATH);
+               user_cgroup_pattern = strdup(DEFAULT_CGROUP_PATTERN);
+       }
+
+       const char * const (*ptr)[2];
+       size_t i;
+       char buf[1024], *p, *p2;
+       FILE *fin = NULL;
+
+       for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
+               if (!strcmp(option_name, (*ptr)[0]))
+                       break;
+       }
+       if (!(*ptr)[0]) {
+               free(user_config_path);
+               free(user_default_config_path);
+               free(user_lxc_path);
+               free(user_cgroup_pattern);
+               errno = EINVAL;
+               return NULL;
+       }
+
+       if (values[i]) {
+               free(user_config_path);
+               free(user_default_config_path);
+               free(user_lxc_path);
+               free(user_cgroup_pattern);
+               return values[i];
+       }
+
+       fin = fopen_cloexec(user_config_path, "r");
+       free(user_config_path);
+       if (fin) {
+               while (fgets(buf, 1024, fin)) {
+                       if (buf[0] == '#')
+                               continue;
+                       p = strstr(buf, option_name);
+                       if (!p)
+                               continue;
+                       /* see if there was just white space in front
+                        * of the option name
+                        */
+                       for (p2 = buf; p2 < p; p2++) {
+                               if (*p2 != ' ' && *p2 != '\t')
+                                       break;
+                       }
+                       if (p2 < p)
+                               continue;
+                       p = strchr(p, '=');
+                       if (!p)
+                               continue;
+                       /* see if there was just white space after
+                        * the option name
+                        */
+                       for (p2 += strlen(option_name); p2 < p; p2++) {
+                               if (*p2 != ' ' && *p2 != '\t')
+                                       break;
+                       }
+                       if (p2 < p)
+                               continue;
+                       p++;
+                       while (*p && (*p == ' ' || *p == '\t')) p++;
+                       if (!*p)
+                               continue;
+
+                       if (strcmp(option_name, "lxc.lxcpath") == 0) {
+                               free(user_lxc_path);
+                               user_lxc_path = copy_global_config_value(p);
+                               remove_trailing_slashes(user_lxc_path);
+                               values[i] = user_lxc_path;
+                               user_lxc_path = NULL;
+                               goto out;
+                       }
+
+                       values[i] = copy_global_config_value(p);
+                       goto out;
+               }
+       }
+       /* could not find value, use default */
+       if (strcmp(option_name, "lxc.lxcpath") == 0) {
+               remove_trailing_slashes(user_lxc_path);
+               values[i] = user_lxc_path;
+               user_lxc_path = NULL;
+       }
+       else if (strcmp(option_name, "lxc.default_config") == 0) {
+               values[i] = user_default_config_path;
+               user_default_config_path = NULL;
+       }
+       else if (strcmp(option_name, "lxc.cgroup.pattern") == 0) {
+               values[i] = user_cgroup_pattern;
+               user_cgroup_pattern = NULL;
+       }
+       else
+               values[i] = (*ptr)[1];
+
+       /* special case: if default value is NULL,
+        * and there is no config, don't view that
+        * as an error... */
+       if (!values[i])
+               errno = 0;
+
+out:
+       if (fin)
+               fclose(fin);
+
+       free(user_cgroup_pattern);
+       free(user_default_config_path);
+       free(user_lxc_path);
+
+       return values[i];
+}
+
+extern void remove_trailing_slashes(char *p)
+{
+       int l = strlen(p);
+       while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
+               p[l] = '\0';
+}
+
+FILE *fopen_cloexec(const char *path, const char *mode)
+{
+       int open_mode = 0;
+       int step = 0;
+       int fd;
+       int saved_errno = 0;
+       FILE *ret;
+
+       if (!strncmp(mode, "r+", 2)) {
+               open_mode = O_RDWR;
+               step = 2;
+       } else if (!strncmp(mode, "r", 1)) {
+               open_mode = O_RDONLY;
+               step = 1;
+       } else if (!strncmp(mode, "w+", 2)) {
+               open_mode = O_RDWR | O_TRUNC | O_CREAT;
+               step = 2;
+       } else if (!strncmp(mode, "w", 1)) {
+               open_mode = O_WRONLY | O_TRUNC | O_CREAT;
+               step = 1;
+       } else if (!strncmp(mode, "a+", 2)) {
+               open_mode = O_RDWR | O_CREAT | O_APPEND;
+               step = 2;
+       } else if (!strncmp(mode, "a", 1)) {
+               open_mode = O_WRONLY | O_CREAT | O_APPEND;
+               step = 1;
+       }
+       for (; mode[step]; step++)
+               if (mode[step] == 'x')
+                       open_mode |= O_EXCL;
+       open_mode |= O_CLOEXEC;
+
+       fd = open(path, open_mode, 0666);
+       if (fd < 0)
+               return NULL;
+
+       ret = fdopen(fd, mode);
+       saved_errno = errno;
+       if (!ret)
+               close(fd);
+       errno = saved_errno;
+       return ret;
+}
diff --git a/src/lxc/initutils.h b/src/lxc/initutils.h
new file mode 100644 (file)
index 0000000..b4f9e54
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2008
+ *
+ * Authors:
+ * Daniel Lezcano <daniel.lezcano at free.fr>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __LXC_INITUTILS_H
+#define __LXC_INITUTILS_H
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+
+#include "config.h"
+
+#define DEFAULT_VG "lxc"
+#define DEFAULT_THIN_POOL "lxc"
+#define DEFAULT_ZFSROOT "lxc"
+
+extern void lxc_setup_fs(void);
+extern const char *lxc_global_config_value(const char *option_name);
+
+/* open a file with O_CLOEXEC */
+extern void remove_trailing_slashes(char *p);
+FILE *fopen_cloexec(const char *path, const char *mode);
+
+#endif /* __LXC_INITUTILS_H */
index 04ba2cc..6726cf0 100644 (file)
 #define LXC_LOG_PREFIX_SIZE    32
 #define LXC_LOG_BUFFER_SIZE    512
 
-static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
-static void lock_mutex(pthread_mutex_t *l)
-{
-       int ret;
-
-       if ((ret = pthread_mutex_lock(l)) != 0) {
-               fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
-               exit(1);
-       }
-}
-
-static void unlock_mutex(pthread_mutex_t *l)
-{
-       int ret;
-
-       if ((ret = pthread_mutex_unlock(l)) != 0) {
-               fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
-               exit(1);
-       }
-}
-
-void log_lock(void)
-{
-       lock_mutex(&log_mutex);
-}
-
-void log_unlock(void)
-{
-       unlock_mutex(&log_mutex);
-}
-
 int lxc_log_fd = -1;
 int lxc_quiet_specified;
 int lxc_log_use_global_fd;
@@ -381,7 +350,7 @@ extern int lxc_log_init(const char *name, const char *file,
                        lxcpath = LOGPATH;
 
                /* try LOGPATH if lxcpath is the default for the privileged containers */
-               if (!geteuid() && strcmp(lxcpath, lxc_global_config_value("lxc.lxcpath")) == 0)
+               if (!geteuid() && strcmp(LXCPATH, lxcpath) == 0)
                        ret = _lxc_log_set_file(name, NULL, 0);
 
                /* try in lxcpath */
index 8e7d9f5..a4c3ecb 100644 (file)
@@ -24,7 +24,7 @@ is_enabled() {
     if [ $RES -eq 0 ]; then
         $SETCOLOR_SUCCESS && echo "enabled" && $SETCOLOR_NORMAL
     else
-        if [ ! -z "$mandatory" -a "$mandatory" = yes ]; then
+        if [ ! -z "$mandatory" ] && [ "$mandatory" = yes ]; then
             $SETCOLOR_FAILURE && echo "required" && $SETCOLOR_NORMAL
         else
             $SETCOLOR_WARNING && echo "missing" && $SETCOLOR_NORMAL
@@ -100,7 +100,7 @@ echo -n "Cgroup device: " && is_enabled CONFIG_CGROUP_DEVICE
 echo -n "Cgroup sched: " && is_enabled CONFIG_CGROUP_SCHED
 echo -n "Cgroup cpu account: " && is_enabled CONFIG_CGROUP_CPUACCT
 echo -n "Cgroup memory controller: "
-if [ $KVER_MAJOR -ge 3 -a $KVER_MINOR -ge 6 ]; then
+if ([ $KVER_MAJOR -ge 3 ] && [ $KVER_MINOR -ge 6 ]) || ([ $KVER_MAJOR -gt 3 ]); then
     is_enabled CONFIG_MEMCG
 else
     is_enabled CONFIG_CGROUP_MEM_RES_CTLR
diff --git a/src/lxc/lxc-restore-net b/src/lxc/lxc-restore-net
deleted file mode 100755 (executable)
index 6ae3c19..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-
-set -e
-
-i=0
-while true; do
-       eval "bridge=\$LXC_CRIU_BRIDGE$i"
-       eval "veth=\$LXC_CRIU_VETH$i"
-
-       if [ -z "$bridge" ] || [ -z "$veth" ]; then
-               exit 0
-       fi
-
-       if [ "$CRTOOLS_SCRIPT_ACTION" = "network-lock" ]; then
-               brctl delif $bridge $veth
-       fi
-
-       if [ "$CRTOOLS_SCRIPT_ACTION" = "network-unlock" ]; then
-               brctl addif $bridge $veth
-               ip link set dev $veth up
-       fi
-
-       i=$((i+1))
-done
-
-exit 1
index 7bf336e..ed2dfd1 100644 (file)
@@ -120,12 +120,6 @@ parser.add_argument("--version", action="version", version=lxc.version)
 
 args = parser.parse_args()
 
-# Basic requirements check
-## We only support privileged containers for now
-if os.geteuid() != 0 and args.union_type != "overlayfs":
-    parser.error(_("Unprivileged containers may only use "
-                   "overlayfs at this time."))
-
 ## Check that -d and CMD aren't used at the same time
 if args.command and args.daemon:
     parser.error(_("You can't use -d and a command at the same time."))
@@ -269,7 +263,7 @@ LXC_NAME="%s"
                              entry[0],
                              entry[1]))
         elif args.union_type == "aufs":
-            xino_path = "%s/lxc/aufs.xino" % get_rundir()
+            xino_path = "/dev/shm/aufs.xino"
             if not os.path.exists(os.path.basename(xino_path)):
                 os.makedirs(os.path.basename(xino_path))
 
index dd1048c..a9fa80e 100644 (file)
@@ -27,6 +27,7 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <sys/select.h>
 #include <sys/types.h>
@@ -44,62 +45,27 @@ struct lxc_arguments;
 
 /*
  * Start the specified command inside a system container
- * @name     : the name of the container
- * @argv     : an array of char * corresponding to the commande line
- * @conf     : configuration
+ * @name         : the name of the container
+ * @argv         : an array of char * corresponding to the commande line
+ * @conf         : configuration
+ * @backgrounded : whether or not the container is daemonized
  * Returns 0 on success, < 0 otherwise
  */
 extern int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf,
-                    const char *lxcpath);
+                    const char *lxcpath, bool backgrounded);
 
 /*
  * Start the specified command inside an application container
- * @name     : the name of the container
- * @argv     : an array of char * corresponding to the commande line
- * @quiet    : if != 0 then lxc-init won't produce any output
- * @conf     : configuration
+ * @name         : the name of the container
+ * @argv         : an array of char * corresponding to the commande line
+ * @quiet        : if != 0 then lxc-init won't produce any output
+ * @conf         : configuration
+ * @backgrounded : whether or not the container is daemonized
  * Returns 0 on success, < 0 otherwise
  */
 extern int lxc_execute(const char *name, char *const argv[], int quiet,
-                      struct lxc_conf *conf, const char *lxcpath);
-
-/*
- * Open the monitoring mechanism for a specific container
- * The function will return an fd corresponding to the events
- * Returns a file descriptor on success, < 0 otherwise
- */
-extern int lxc_monitor_open(const char *lxcpath);
-
-/*
- * Blocking read for the next container state change
- * @fd  : the file descriptor provided by lxc_monitor_open
- * @msg : the variable which will be filled with the state
- * Returns 0 if the monitored container has exited, > 0 if
- * data was read, < 0 otherwise
- */
-extern int lxc_monitor_read(int fd, struct lxc_msg *msg);
-
-/*
- * Blocking read for the next container state change with timeout
- * @fd      : the file descriptor provided by lxc_monitor_open
- * @msg     : the variable which will be filled with the state
- * @timeout : the timeout in seconds to wait for a state change
- * Returns 0 if the monitored container has exited, > 0 if
- * data was read, < 0 otherwise
- */
-extern int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout);
-
-/*
- * Blocking read from multiple monitors for the next container state
- * change with timeout
- * @rfds    : an fd_set of file descriptors provided by lxc_monitor_open
- * @nfds    : the maximum fd number in rfds + 1
- * @msg     : the variable which will be filled with the state
- * @timeout : the timeout in seconds to wait for a state change
- * Returns 0 if the monitored container has exited, > 0 if
- * data was read, < 0 otherwise
- */
-extern int lxc_monitor_read_fdset(fd_set *rfds, int nfds, struct lxc_msg *msg, int timeout);
+                      struct lxc_conf *conf, const char *lxcpath,
+                      bool backgrounded);
 
 /*
  * Close the fd associated with the monitoring
index f5b9e32..1e48f94 100644 (file)
@@ -177,8 +177,10 @@ static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc
                if ( list_contains_entry( workptr, workstr_list ) ) {
                        if ( *workptr ) {
                                fprintf(stderr, "Duplicate group \"%s\" in list - ignoring\n", workptr );
+                               fflush(stderr);
                        } else {
-                               fprintf(stderr, "Duilicate NULL group in list - ignoring\n" );
+                               fprintf(stderr, "Duplicate NULL group in list - ignoring\n" );
+                               fflush(stderr);
                        }
                } else {
                        worklist = malloc(sizeof(*worklist));
@@ -352,7 +354,8 @@ int main(int argc, char *argv[])
        qsort(&containers[0], count, sizeof(struct lxc_container *), cmporder);
 
        if (cmd_groups_list && my_args.all) {
-               fprintf(stderr, "Specifying -a (all) with -g (groups) doesn't make sense. All option overrides.");
+               fprintf(stderr, "Specifying -a (all) with -g (groups) doesn't make sense. All option overrides.\n");
+               fflush(stderr);
        }
 
        if (!cmd_groups_list) {
@@ -423,12 +426,15 @@ int main(int argc, char *argv[])
                        if (my_args.shutdown) {
                                /* Shutdown the container */
                                if (c->is_running(c)) {
-                                       if (my_args.list)
+                                       if (my_args.list) {
                                                printf("%s\n", c->name);
+                                               fflush(stdout);
+                                       }
                                        else {
                                                if (!c->shutdown(c, my_args.timeout)) {
                                                        if (!c->stop(c)) {
                                                                fprintf(stderr, "Error shutting down container: %s\n", c->name);
+                                                               fflush(stderr);
                                                        }
                                                }
                                        }
@@ -437,23 +443,31 @@ int main(int argc, char *argv[])
                        else if (my_args.hardstop) {
                                /* Kill the container */
                                if (c->is_running(c)) {
-                                       if (my_args.list)
+                                       if (my_args.list) {
                                                printf("%s\n", c->name);
+                                               fflush(stdout);
+                                       }
                                        else {
-                                               if (!c->stop(c))
+                                               if (!c->stop(c)) {
                                                        fprintf(stderr, "Error killing container: %s\n", c->name);
+                                                       fflush(stderr);
+                                               }
                                        }
                                }
                        }
                        else if (my_args.reboot) {
                                /* Reboot the container */
                                if (c->is_running(c)) {
-                                       if (my_args.list)
+                                       if (my_args.list) {
                                                printf("%s %d\n", c->name,
                                                       get_config_integer(c, "lxc.start.delay"));
+                                               fflush(stdout);
+                                       }
                                        else {
-                                               if (!c->reboot(c))
+                                               if (!c->reboot(c)) {
                                                        fprintf(stderr, "Error rebooting container: %s\n", c->name);
+                                                       fflush(stderr);
+                                               }
                                                else
                                                        sleep(get_config_integer(c, "lxc.start.delay"));
                                        }
@@ -462,12 +476,16 @@ int main(int argc, char *argv[])
                        else {
                                /* Start the container */
                                if (!c->is_running(c)) {
-                                       if (my_args.list)
+                                       if (my_args.list) {
                                                printf("%s %d\n", c->name,
                                                       get_config_integer(c, "lxc.start.delay"));
+                                               fflush(stdout);
+                                       }
                                        else {
-                                               if (!c->start(c, 0, NULL))
+                                               if (!c->start(c, 0, NULL)) {
                                                        fprintf(stderr, "Error starting container: %s\n", c->name);
+                                                       fflush(stderr);
+                                               }
                                                else
                                                        sleep(get_config_integer(c, "lxc.start.delay"));
                                        }
index b602793..4f1e1f6 100644 (file)
@@ -139,7 +139,7 @@ int main(int argc, char *argv[])
        if (lxc_config_define_load(&defines, conf))
                return 1;
 
-       ret = lxc_execute(my_args.name, my_args.argv, my_args.quiet, conf, my_args.lxcpath[0]);
+       ret = lxc_execute(my_args.name, my_args.argv, my_args.quiet, conf, my_args.lxcpath[0], false);
 
        lxc_conf_free(conf);
 
index 0778bfe..62ed4ad 100644 (file)
@@ -36,7 +36,7 @@
 #include "log.h"
 #include "caps.h"
 #include "error.h"
-#include "utils.h"
+#include "initutils.h"
 
 lxc_log_define(lxc_init, lxc);
 
index ede19ff..ac34b0e 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <errno.h>
+#include <poll.h>
 
 #include "lxc.h"
 #include "log.h"
@@ -70,13 +71,28 @@ Options :\n\
        .lxcpath_additional = -1,
 };
 
+static void close_fds(struct pollfd *fds, nfds_t nfds)
+{
+       nfds_t i;
+
+       if (nfds < 1)
+               return;
+
+       for (i = 0; i < nfds; ++i) {
+               close(fds[i].fd);
+       }
+}
+
 int main(int argc, char *argv[])
 {
        char *regexp;
        struct lxc_msg msg;
        regex_t preg;
-       fd_set rfds, rfds_save;
-       int len, rc, i, nfds = -1;
+       struct pollfd *fds;
+       nfds_t nfds;
+       int len, rc_main, rc_snp, i;
+
+       rc_main = 0;
 
        if (lxc_arguments_parse(&my_args, argc, argv))
                return 1;
@@ -117,51 +133,49 @@ int main(int argc, char *argv[])
                ERROR("failed to allocate memory");
                return 1;
        }
-       rc = snprintf(regexp, len, "^%s$", my_args.name);
-       if (rc < 0 || rc >= len) {
+       rc_snp = snprintf(regexp, len, "^%s$", my_args.name);
+       if (rc_snp < 0 || rc_snp >= len) {
                ERROR("Name too long");
-               free(regexp);
-               return 1;
+               rc_main = 1;
+               goto error;
        }
 
        if (regcomp(&preg, regexp, REG_NOSUB|REG_EXTENDED)) {
                ERROR("failed to compile the regex '%s'", my_args.name);
-               free(regexp);
-               return 1;
+               rc_main = 1;
+               goto error;
        }
-       free(regexp);
 
-       if (my_args.lxcpath_cnt > FD_SETSIZE) {
-               ERROR("too many paths requested, only the first %d will be monitored", FD_SETSIZE);
-               my_args.lxcpath_cnt = FD_SETSIZE;
+       fds = malloc(my_args.lxcpath_cnt * sizeof(struct pollfd));
+       if (!fds) {
+               SYSERROR("out of memory");
+               rc_main = -1;
+               goto cleanup;
        }
 
-       FD_ZERO(&rfds);
-       for (i = 0; i < my_args.lxcpath_cnt; i++) {
+       nfds = my_args.lxcpath_cnt;
+       for (i = 0; i < nfds; i++) {
                int fd;
 
                lxc_monitord_spawn(my_args.lxcpath[i]);
 
                fd = lxc_monitor_open(my_args.lxcpath[i]);
                if (fd < 0) {
-                       regfree(&preg);
-                       return 1;
+                       close_fds(fds, i);
+                       rc_main = 1;
+                       goto cleanup;
                }
-               FD_SET(fd, &rfds);
-               if (fd > nfds)
-                       nfds = fd;
+               fds[i].fd = fd;
+               fds[i].events = POLLIN;
+               fds[i].revents = 0;
        }
-       memcpy(&rfds_save, &rfds, sizeof(rfds_save));
-       nfds++;
 
        setlinebuf(stdout);
 
        for (;;) {
-               memcpy(&rfds, &rfds_save, sizeof(rfds));
-
-               if (lxc_monitor_read_fdset(&rfds, nfds, &msg, -1) < 0) {
-                       regfree(&preg);
-                       return 1;
+               if (lxc_monitor_read_fdset(fds, nfds, &msg, -1) < 0) {
+                       rc_main = 1;
+                       goto close_and_clean;
                }
 
                msg.name[sizeof(msg.name)-1] = '\0';
@@ -183,7 +197,15 @@ int main(int argc, char *argv[])
                }
        }
 
+close_and_clean:
+       close_fds(fds, nfds);
+
+cleanup:
        regfree(&preg);
+       free(fds);
 
-       return 0;
+error:
+       free(regexp);
+
+       return rc_main;
 }
index 522d652..09ff063 100644 (file)
@@ -50,6 +50,7 @@
 #include "console.h"
 #include "cgroup.h"
 #include "commands.h"
+#include "criu.h"
 #include "log.h"
 #include "bdev.h"
 #include "utils.h"
@@ -343,10 +344,9 @@ out:
 static rettype fnname(struct lxc_container *c)                         \
 {                                                                      \
        rettype ret;                                                    \
-       struct lxc_conf *old = current_config;                          \
        current_config = c ? c->lxc_conf : NULL;                        \
        ret = do_##fnname(c);                                           \
-       current_config = old;                                           \
+       current_config = NULL;                                          \
        return ret;                                                     \
 }
 
@@ -354,10 +354,9 @@ static rettype fnname(struct lxc_container *c)                             \
 static rettype fnname(struct lxc_container *c, t1 a1)                  \
 {                                                                      \
        rettype ret;                                                    \
-       struct lxc_conf *old = current_config;                          \
        current_config = c ? c->lxc_conf : NULL;                        \
        ret = do_##fnname(c, a1);                                       \
-       current_config = old;                                           \
+       current_config = NULL;                                          \
        return ret;                                                     \
 }
 
@@ -365,10 +364,9 @@ static rettype fnname(struct lxc_container *c, t1 a1)                      \
 static rettype fnname(struct lxc_container *c, t1 a1, t2 a2)           \
 {                                                                      \
        rettype ret;                                                    \
-       struct lxc_conf *old = current_config;                          \
        current_config = c ? c->lxc_conf : NULL;                        \
        ret = do_##fnname(c, a1, a2);                                   \
-       current_config = old;                                           \
+       current_config = NULL;                                          \
        return ret;                                                     \
 }
 
@@ -376,10 +374,9 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2)               \
 static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3)    \
 {                                                                      \
        rettype ret;                                                    \
-       struct lxc_conf *old = current_config;                          \
        current_config = c ? c->lxc_conf : NULL;                        \
        ret = do_##fnname(c, a1, a2, a3);                               \
-       current_config = old;                                           \
+       current_config = NULL;                                          \
        return ret;                                                     \
 }
 
@@ -462,10 +459,13 @@ static int lxcapi_console(struct lxc_container *c, int ttynum, int stdinfd,
                          int stdoutfd, int stderrfd, int escape)
 {
        int ret;
-       struct lxc_conf *old = current_config;
-       current_config = c ? c->lxc_conf : NULL;
+
+       if (!c)
+               return -1;
+
+       current_config = c->lxc_conf;
        ret = lxc_console(c, ttynum, stdinfd, stdoutfd, stderrfd, escape);
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
@@ -664,7 +664,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
        container_mem_unlock(c);
 
        if (useinit) {
-               ret = lxc_execute(c->name, argv, 1, conf, c->config_path);
+               ret = lxc_execute(c->name, argv, 1, conf, c->config_path, daemonize);
                return ret == 0 ? true : false;
        }
 
@@ -712,22 +712,20 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                pid = fork();
                if (pid < 0) {
                        SYSERROR("Error doing dual-fork");
-                       return false;
+                       exit(1);
                }
                if (pid != 0)
                        exit(0);
                /* like daemon(), chdir to / and redirect 0,1,2 to /dev/null */
                if (chdir("/")) {
                        SYSERROR("Error chdir()ing to /.");
-                       return false;
+                       exit(1);
                }
                lxc_check_inherited(conf, true, -1);
-               close(0);
-               close(1);
-               close(2);
-               open("/dev/zero", O_RDONLY);
-               open("/dev/null", O_RDWR);
-               open("/dev/null", O_RDWR);
+               if (null_stdfds() < 0) {
+                       ERROR("failed to close fds");
+                       exit(1);
+               }
                setsid();
        } else {
                if (!am_single_threaded()) {
@@ -744,6 +742,8 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                if (pid_fp == NULL) {
                        SYSERROR("Failed to create pidfile '%s' for '%s'",
                                 c->pidfile, c->name);
+                       if (daemonize)
+                               exit(1);
                        return false;
                }
 
@@ -751,6 +751,8 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                        SYSERROR("Failed to write '%s'", c->pidfile);
                        fclose(pid_fp);
                        pid_fp = NULL;
+                       if (daemonize)
+                               exit(1);
                        return false;
                }
 
@@ -758,21 +760,21 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
                pid_fp = NULL;
        }
 
-reboot:
        conf->reboot = 0;
 
+reboot:
        if (lxc_check_inherited(conf, daemonize, -1)) {
                ERROR("Inherited fds found");
                ret = 1;
                goto out;
        }
 
-       ret = lxc_start(c->name, argv, conf, c->config_path);
+       ret = lxc_start(c->name, argv, conf, c->config_path, daemonize);
        c->error_num = ret;
 
-       if (conf->reboot) {
+       if (conf->reboot == 1) {
                INFO("container requested reboot");
-               conf->reboot = 0;
+               conf->reboot = 2;
                goto reboot;
        }
 
@@ -792,10 +794,9 @@ out:
 static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv[])
 {
        bool ret;
-       struct lxc_conf *old = current_config;
        current_config = c ? c->lxc_conf : NULL;
        ret = do_lxcapi_start(c, useinit, argv);
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
@@ -812,7 +813,6 @@ static bool lxcapi_startl(struct lxc_container *c, int useinit, ...)
        if (!c)
                return false;
 
-       struct lxc_conf *old = current_config;
        current_config = c->lxc_conf;
 
        va_start(ap, useinit);
@@ -835,7 +835,7 @@ out:
                free(inargs);
        }
 
-       current_config = old;
+       current_config = NULL;
        return bret;
 }
 
@@ -958,7 +958,7 @@ static char *lxcbasename(char *path)
        return p;
 }
 
-static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet,
+static bool create_run_template(struct lxc_container *c, char *tpath, bool need_null_stdfds,
                                char *const argv[])
 {
        pid_t pid;
@@ -980,13 +980,8 @@ static bool create_run_template(struct lxc_container *c, char *tpath, bool quiet
                char **newargv;
                struct lxc_conf *conf = c->lxc_conf;
 
-               if (quiet) {
-                       close(0);
-                       close(1);
-                       close(2);
-                       open("/dev/zero", O_RDONLY);
-                       open("/dev/null", O_RDWR);
-                       open("/dev/null", O_RDWR);
+               if (need_null_stdfds && null_stdfds() < 0) {
+                       exit(1);
                }
 
                src = c->lxc_conf->rootfs.path;
@@ -1464,10 +1459,9 @@ static bool lxcapi_create(struct lxc_container *c, const char *t,
                char *const argv[])
 {
        bool ret;
-       struct lxc_conf *old = current_config;
        current_config = c ? c->lxc_conf : NULL;
        ret = do_lxcapi_create(c, t, bdevtype, specs, flags, argv);
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
@@ -1523,8 +1517,7 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
        if (!c)
                return false;
 
-       struct lxc_conf *old = current_config;
-       current_config = c ? c->lxc_conf : NULL;
+       current_config = c->lxc_conf;
 
        /*
         * since we're going to wait for create to finish, I don't think we
@@ -1542,7 +1535,7 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
 
 out:
        free(args);
-       current_config = old;
+       current_config = NULL;
        return bret;
 }
 
@@ -2174,6 +2167,14 @@ static bool container_destroy(struct lxc_container *c)
                goto out;
        }
 
+       if (current_config && c->lxc_conf == current_config) {
+               current_config = NULL;
+               if (c->lxc_conf->logfd != -1) {
+                       close(c->lxc_conf->logfd);
+                       c->lxc_conf->logfd = -1;
+               }
+       }
+
        if (c->lxc_conf && c->lxc_conf->rootfs.path && c->lxc_conf->rootfs.mount) {
                if (am_unpriv())
                        ret = userns_exec_1(c->lxc_conf, bdev_destroy_wrapper, c->lxc_conf);
@@ -2632,7 +2633,7 @@ static int copy_storage(struct lxc_container *c0, struct lxc_container *c,
        // We will simply append a new lxc.rootfs entry to the unexpanded config
        clear_unexp_config_line(c->lxc_conf, "lxc.rootfs", false);
        if (!do_append_unexp_config_line(c->lxc_conf, "lxc.rootfs", c->lxc_conf->rootfs.path)) {
-               ERROR("Error saving new rootfs to cloend config");
+               ERROR("Error saving new rootfs to cloned config");
                return -1;
        }
        if (flags & LXC_CLONE_SNAPSHOT)
@@ -2951,10 +2952,9 @@ static struct lxc_container *lxcapi_clone(struct lxc_container *c, const char *n
                char **hookargs)
 {
        struct lxc_container * ret;
-       struct lxc_conf *old = current_config;
        current_config = c ? c->lxc_conf : NULL;
        ret = do_lxcapi_clone(c, newname, lxcpath, flags, bdevtype, bdevdata, newsize, hookargs);
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
@@ -2997,7 +2997,6 @@ WRAP_API_1(bool, lxcapi_rename, const char *)
 
 static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process)
 {
-       struct lxc_conf *old = current_config;
        int ret;
 
        if (!c)
@@ -3006,7 +3005,7 @@ static int lxcapi_attach(struct lxc_container *c, lxc_attach_exec_t exec_functio
        current_config = c->lxc_conf;
 
        ret = lxc_attach(c->name, c->config_path, exec_function, exec_payload, options, attached_process);
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
@@ -3032,10 +3031,9 @@ static int do_lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options
 static int lxcapi_attach_run_wait(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char * const argv[])
 {
        int ret;
-       struct lxc_conf *old = current_config;
        current_config = c ? c->lxc_conf : NULL;
        ret = do_lxcapi_attach_run_wait(c, options, program, argv);
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
@@ -3681,370 +3679,11 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c, const char *ifna
 
 WRAP_API_2(bool, lxcapi_detach_interface, const char *, const char *)
 
-struct criu_opts {
-       /* The type of criu invocation, one of "dump" or "restore" */
-       char *action;
-
-       /* The directory to pass to criu */
-       char *directory;
-
-       /* The container to dump */
-       struct lxc_container *c;
-
-       /* Enable criu verbose mode? */
-       bool verbose;
-
-       /* dump: stop the container or not after dumping? */
-       bool stop;
-
-       /* restore: the file to write the init process' pid into */
-       char *pidfile;
-       const char *cgroup_path;
-};
-
-static void exec_criu(struct criu_opts *opts)
-{
-       char **argv, log[PATH_MAX];
-       int static_args = 14, argc = 0, i, ret;
-       int netnr = 0;
-       struct lxc_list *it;
-
-       struct mntent mntent;
-       char buf[4096];
-       FILE *mnts = NULL;
-
-       /* The command line always looks like:
-        * criu $(action) --tcp-established --file-locks --link-remap --force-irmap \
-        * --manage-cgroups action-script foo.sh -D $(directory) \
-        * -o $(directory)/$(action).log
-        * +1 for final NULL */
-
-       if (strcmp(opts->action, "dump") == 0) {
-               /* -t pid */
-               static_args += 2;
-
-               /* --leave-running */
-               if (!opts->stop)
-                       static_args++;
-       } else if (strcmp(opts->action, "restore") == 0) {
-               /* --root $(lxc_mount_point) --restore-detached
-                * --restore-sibling --pidfile $foo --cgroup-root $foo */
-               static_args += 8;
-       } else {
-               return;
-       }
-
-       if (opts->verbose)
-               static_args++;
-
-       ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->directory, opts->action);
-       if (ret < 0 || ret >= PATH_MAX) {
-               ERROR("logfile name too long\n");
-               return;
-       }
-
-       // We need to tell criu where cgmanager's socket is bind mounted from
-       // if it exists since it's external.
-       if (cgroup_driver() == CGMANAGER)
-               static_args+=2;
-
-       argv = malloc(static_args * sizeof(*argv));
-       if (!argv)
-               return;
-
-       memset(argv, 0, static_args * sizeof(*argv));
-
-#define DECLARE_ARG(arg)                                       \
-       do {                                                    \
-               if (arg == NULL) {                              \
-                       ERROR("Got NULL argument for criu");    \
-                       goto err;                               \
-               }                                               \
-               argv[argc++] = strdup(arg);                     \
-               if (!argv[argc-1])                              \
-                       goto err;                               \
-       } while (0)
-
-       argv[argc++] = on_path("criu", NULL);
-       if (!argv[argc-1]) {
-               ERROR("Couldn't find criu binary\n");
-               goto err;
-       }
-
-       DECLARE_ARG(opts->action);
-       DECLARE_ARG("--tcp-established");
-       DECLARE_ARG("--file-locks");
-       DECLARE_ARG("--link-remap");
-       DECLARE_ARG("--force-irmap");
-       DECLARE_ARG("--manage-cgroups");
-       DECLARE_ARG("--action-script");
-       DECLARE_ARG(DATADIR "/lxc/lxc-restore-net");
-       DECLARE_ARG("-D");
-       DECLARE_ARG(opts->directory);
-       DECLARE_ARG("-o");
-       DECLARE_ARG(log);
-
-       if (opts->verbose)
-               DECLARE_ARG("-vvvvvv");
-
-       /*
-        * Note: this macro is not intended to be called unless argc is equal
-        * to the length of the array; there is nothing that keeps track of the
-        * length of the array besides the location in the code that this is
-        * called. (Yes this is bad, and we should fix it.)
-        */
-#define RESIZE_ARGS(additional)                                                \
-       do {                                                                    \
-               void *m;                                                        \
-               if (additional < 0) {                                           \
-                       ERROR("resizing by negative amount");                   \
-                       goto err;                                               \
-               } else if (additional == 0)                                     \
-                       continue;                                               \
-                                                                               \
-               m = realloc(argv, (argc + additional + 1) * sizeof(*argv));     \
-               if (!m)                                                         \
-                       goto err;                                               \
-               argv = m;                                                       \
-       } while (0)
-
-       if (strcmp(opts->action, "dump") == 0) {
-               char pid[32];
-
-               if (cgroup_driver() == CGMANAGER) {
-                       DECLARE_ARG("--ext-mount-map");
-                       DECLARE_ARG("/sys/fs/cgroup/cgmanager:cgmanager");
-               }
-
-               if (sprintf(pid, "%d", lxcapi_init_pid(opts->c)) < 0)
-                       goto err;
-
-               DECLARE_ARG("-t");
-               DECLARE_ARG(pid);
-               if (!opts->stop)
-                       DECLARE_ARG("--leave-running");
-       } else if (strcmp(opts->action, "restore") == 0) {
-
-               if (cgroup_driver() == CGMANAGER) {
-                       DECLARE_ARG("--ext-mount-map");
-                       DECLARE_ARG("cgmanager:/sys/fs/cgroup/cgmanager");
-               }
-
-               DECLARE_ARG("--root");
-               DECLARE_ARG(opts->c->lxc_conf->rootfs.mount);
-               DECLARE_ARG("--restore-detached");
-               DECLARE_ARG("--restore-sibling");
-               DECLARE_ARG("--pidfile");
-               DECLARE_ARG(opts->pidfile);
-               DECLARE_ARG("--cgroup-root");
-               DECLARE_ARG(opts->cgroup_path);
-
-               RESIZE_ARGS(lxc_list_len(&opts->c->lxc_conf->network) * 2);
-
-               lxc_list_for_each(it, &opts->c->lxc_conf->network) {
-                       char eth[128], *veth;
-                       struct lxc_netdev *n = it->elem;
-
-                       if (n->name) {
-                               if (strlen(n->name) >= sizeof(eth))
-                                       goto err;
-                               strncpy(eth, n->name, sizeof(eth));
-                       } else
-                               sprintf(eth, "eth%d", netnr);
-
-                       veth = n->priv.veth_attr.pair;
-
-                       ret = snprintf(buf, sizeof(buf), "%s=%s", eth, veth);
-                       if (ret < 0 || ret >= sizeof(buf))
-                               goto err;
-
-                       DECLARE_ARG("--veth-pair");
-                       DECLARE_ARG(buf);
-               }
-       }
-
-       // CRIU wants to know about any external bind mounts the
-       // container has.
-       mnts = write_mount_file(&opts->c->lxc_conf->mount_list);
-       if (!mnts)
-               goto err;
-
-       RESIZE_ARGS(lxc_list_len(&opts->c->lxc_conf->mount_list) * 2);
-
-       while (getmntent_r(mnts, &mntent, buf, sizeof(buf))) {
-               char arg[2048], *key, *val;
-               int ret;
-
-               if (strcmp(opts->action, "dump") == 0) {
-                       key = mntent.mnt_fsname;
-                       val = mntent.mnt_dir;
-               } else {
-                       key = mntent.mnt_dir;
-                       val = mntent.mnt_fsname;
-               }
-
-               ret = snprintf(arg, sizeof(arg), "%s:%s", key, val);
-               if (ret < 0 || ret >= sizeof(arg)) {
-                       goto err;
-               }
-
-               DECLARE_ARG("--ext-mount-map");
-               DECLARE_ARG(arg);
-       }
-       fclose(mnts);
-
-       argv[argc] = NULL;
-
-       netnr = 0;
-       lxc_list_for_each(it, &opts->c->lxc_conf->network) {
-               struct lxc_netdev *n = it->elem;
-               char veth[128];
-
-               /*
-                * Here, we set some parameters that lxc-restore-net
-                * will examine to figure out the right network to
-                * restore.
-                */
-               snprintf(buf, sizeof(buf), "LXC_CRIU_BRIDGE%d", netnr);
-               if (setenv(buf, n->link, 1))
-                       goto err;
-
-               if (strcmp("restore", opts->action) == 0)
-                       strncpy(veth, n->priv.veth_attr.pair, sizeof(veth));
-               else {
-                       char *tmp;
-                       ret = snprintf(buf, sizeof(buf), "lxc.network.%d.veth.pair", netnr);
-                       if (ret < 0 || ret >= sizeof(buf))
-                               goto err;
-                       tmp = lxcapi_get_running_config_item(opts->c, buf);
-                       strncpy(veth, tmp, sizeof(veth));
-                       free(tmp);
-               }
-
-               snprintf(buf, sizeof(buf), "LXC_CRIU_VETH%d", netnr);
-               if (setenv(buf, veth, 1))
-                       goto err;
-
-               netnr++;
-       }
-
-#undef DECLARE_ARG
-#undef RESIZE_ARGS
-       execv(argv[0], argv);
-err:
-       if (mnts)
-               fclose(mnts);
-       for (i = 0; argv[i]; i++)
-               free(argv[i]);
-       free(argv);
-}
-
-/* Check and make sure the container has a configuration that we know CRIU can
- * dump. */
-static bool criu_ok(struct lxc_container *c)
-{
-       struct lxc_list *it;
-       bool found_deny_rule = false;
-
-       if (geteuid()) {
-               ERROR("Must be root to checkpoint\n");
-               return false;
-       }
-
-       /* We only know how to restore containers with veth networks. */
-       lxc_list_for_each(it, &c->lxc_conf->network) {
-               struct lxc_netdev *n = it->elem;
-               if (n->type != LXC_NET_VETH && n->type != LXC_NET_NONE) {
-                       ERROR("Found network that is not VETH or NONE\n");
-                       return false;
-               }
-       }
-
-       // These requirements come from http://criu.org/LXC
-       if (c->lxc_conf->console.path &&
-                       strcmp(c->lxc_conf->console.path, "none") != 0) {
-               ERROR("lxc.console must be none\n");
-               return false;
-       }
-
-       if (c->lxc_conf->tty != 0) {
-               ERROR("lxc.tty must be 0\n");
-               return false;
-       }
-
-       lxc_list_for_each(it, &c->lxc_conf->cgroup) {
-               struct lxc_cgroup *cg = it->elem;
-               if (strcmp(cg->subsystem, "devices.deny") == 0 &&
-                               strcmp(cg->value, "c 5:1 rwm") == 0) {
-
-                       found_deny_rule = true;
-                       break;
-               }
-       }
-
-       if (!found_deny_rule) {
-               ERROR("couldn't find devices.deny = c 5:1 rwm");
-               return false;
-       }
-
-       return true;
-}
-
-static bool dump_net_info(struct lxc_container *c, char *directory)
-{
-       int netnr;
-       struct lxc_list *it;
-
-       netnr = 0;
-       lxc_list_for_each(it, &c->lxc_conf->network) {
-               char *veth = NULL, *bridge = NULL, veth_path[PATH_MAX], eth[128];
-               struct lxc_netdev *n = it->elem;
-               bool has_error = true;
-               int pret;
-
-               pret = snprintf(veth_path, PATH_MAX, "lxc.network.%d.veth.pair", netnr);
-               if (pret < 0 || pret >= PATH_MAX)
-                       goto out;
-
-               veth = lxcapi_get_running_config_item(c, veth_path);
-               if (!veth) {
-                       /* criu_ok() checks that all interfaces are
-                        * LXC_NET{VETH,NONE}, and VETHs should have this
-                        * config */
-                       assert(n->type == LXC_NET_NONE);
-                       break;
-               }
-
-               bridge = lxcapi_get_running_config_item(c, veth_path);
-               if (!bridge)
-                       goto out;
-
-               pret = snprintf(veth_path, PATH_MAX, "%s/veth%d", directory, netnr);
-               if (pret < 0 || pret >= PATH_MAX || print_to_file(veth_path, veth) < 0)
-                       goto out;
-
-               if (n->name) {
-                       if (strlen(n->name) >= 128)
-                               goto out;
-                       strncpy(eth, n->name, 128);
-               } else
-                       sprintf(eth, "eth%d", netnr);
-
-               has_error = false;
-out:
-               free(veth);
-               free(bridge);
-               if (has_error)
-                       return false;
-       }
-
-       return true;
-}
-
 static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, bool stop, bool verbose)
 {
        pid_t pid;
        int status;
+       char path[PATH_MAX];
 
        if (!criu_ok(c))
                return false;
@@ -4052,8 +3691,14 @@ static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, bool
        if (mkdir(directory, 0700) < 0 && errno != EEXIST)
                return false;
 
-       if (!dump_net_info(c, directory))
+       status = snprintf(path, sizeof(path), "%s/inventory.img", directory);
+       if (status < 0 || status >= sizeof(path))
+               return false;
+
+       if (access(path, F_OK) == 0) {
+               ERROR("please use a fresh directory for the dump directory\n");
                return false;
+       }
 
        pid = fork();
        if (pid < 0)
@@ -4088,184 +3733,6 @@ static bool do_lxcapi_checkpoint(struct lxc_container *c, char *directory, bool
 
 WRAP_API_3(bool, lxcapi_checkpoint, char *, bool, bool)
 
-static bool restore_net_info(struct lxc_container *c)
-{
-       struct lxc_list *it;
-       bool has_error = true;
-
-       if (container_mem_lock(c))
-               return false;
-
-       lxc_list_for_each(it, &c->lxc_conf->network) {
-               struct lxc_netdev *netdev = it->elem;
-               char template[IFNAMSIZ];
-               snprintf(template, sizeof(template), "vethXXXXXX");
-
-               if (!netdev->priv.veth_attr.pair)
-                       netdev->priv.veth_attr.pair = lxc_mkifname(template);
-
-               if (!netdev->priv.veth_attr.pair)
-                       goto out_unlock;
-       }
-
-       has_error = false;
-
-out_unlock:
-       container_mem_unlock(c);
-       return !has_error;
-}
-
-// do_restore never returns, the calling process is used as the
-// monitor process. do_restore calls exit() if it fails.
-static void do_restore(struct lxc_container *c, int pipe, char *directory, bool verbose)
-{
-       pid_t pid;
-       char pidfile[L_tmpnam];
-       struct lxc_handler *handler;
-       int status;
-
-       if (!tmpnam(pidfile))
-               goto out;
-
-       handler = lxc_init(c->name, c->lxc_conf, c->config_path);
-       if (!handler)
-               goto out;
-
-       if (!cgroup_init(handler)) {
-               ERROR("failed initing cgroups");
-               goto out_fini_handler;
-       }
-
-       if (!cgroup_create(handler)) {
-               ERROR("failed creating groups");
-               goto out_fini_handler;
-       }
-
-       if (!restore_net_info(c)) {
-               ERROR("failed restoring network info");
-               goto out_fini_handler;
-       }
-
-       resolve_clone_flags(handler);
-
-       pid = fork();
-       if (pid < 0)
-               goto out_fini_handler;
-
-       if (pid == 0) {
-               struct criu_opts os;
-               struct lxc_rootfs *rootfs;
-
-               close(pipe);
-               pipe = -1;
-
-               if (unshare(CLONE_NEWNS))
-                       goto out_fini_handler;
-
-               /* CRIU needs the lxc root bind mounted so that it is the root of some
-                * mount. */
-               rootfs = &c->lxc_conf->rootfs;
-
-               if (rootfs_is_blockdev(c->lxc_conf)) {
-                       if (do_rootfs_setup(c->lxc_conf, c->name, c->config_path) < 0)
-                               goto out_fini_handler;
-               } else {
-                       if (mkdir(rootfs->mount, 0755) < 0 && errno != EEXIST)
-                               goto out_fini_handler;
-
-                       if (mount(rootfs->path, rootfs->mount, NULL, MS_BIND, NULL) < 0) {
-                               rmdir(rootfs->mount);
-                               goto out_fini_handler;
-                       }
-               }
-
-               os.action = "restore";
-               os.directory = directory;
-               os.c = c;
-               os.pidfile = pidfile;
-               os.verbose = verbose;
-               os.cgroup_path = cgroup_canonical_path(handler);
-
-               /* exec_criu() returning is an error */
-               exec_criu(&os);
-               umount(rootfs->mount);
-               rmdir(rootfs->mount);
-               goto out_fini_handler;
-       } else {
-               int ret;
-               char title[2048];
-
-               pid_t w = waitpid(pid, &status, 0);
-               if (w == -1) {
-                       SYSERROR("waitpid");
-                       goto out_fini_handler;
-               }
-
-               ret = write(pipe, &status, sizeof(status));
-               close(pipe);
-               pipe = -1;
-
-               if (sizeof(status) != ret) {
-                       SYSERROR("failed to write all of status");
-                       goto out_fini_handler;
-               }
-
-               if (WIFEXITED(status)) {
-                       if (WEXITSTATUS(status)) {
-                               goto out_fini_handler;
-                       } else {
-                               int ret;
-                               FILE *f = fopen(pidfile, "r");
-                               if (!f) {
-                                       SYSERROR("couldn't read restore's init pidfile %s\n", pidfile);
-                                       goto out_fini_handler;
-                               }
-
-                               ret = fscanf(f, "%d", (int*) &handler->pid);
-                               fclose(f);
-                               if (ret != 1) {
-                                       ERROR("reading restore pid failed");
-                                       goto out_fini_handler;
-                               }
-
-                               if (lxc_set_state(c->name, handler, RUNNING))
-                                       goto out_fini_handler;
-                       }
-               } else {
-                       ERROR("CRIU was killed with signal %d\n", WTERMSIG(status));
-                       goto out_fini_handler;
-               }
-
-               /*
-                * See comment in lxcapi_start; we don't care if these
-                * fail because it's just a beauty thing. We just
-                * assign the return here to silence potential.
-                */
-               ret = snprintf(title, sizeof(title), "[lxc monitor] %s %s", c->config_path, c->name);
-               ret = setproctitle(title);
-
-               ret = lxc_poll(c->name, handler);
-               if (ret)
-                       lxc_abort(c->name, handler);
-               lxc_fini(c->name, handler);
-               exit(ret);
-       }
-
-out_fini_handler:
-       lxc_fini(c->name, handler);
-
-out:
-       if (pipe >= 0) {
-               status = 1;
-               if (write(pipe, &status, sizeof(status)) != sizeof(status)) {
-                       SYSERROR("writing status failed");
-               }
-               close(pipe);
-       }
-
-       exit(1);
-}
-
 static bool do_lxcapi_restore(struct lxc_container *c, char *directory, bool verbose)
 {
        pid_t pid;
@@ -4331,7 +3798,6 @@ static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t
        if (!c)
                return -1;
 
-       struct lxc_conf *old = current_config;
        current_config = c->lxc_conf;
 
        va_start(ap, arg);
@@ -4348,7 +3814,7 @@ static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t
        ret = do_lxcapi_attach_run_wait(c, options, program, (const char * const *)argv);
        free((void*)argv);
 out:
-       current_config = old;
+       current_config = NULL;
        return ret;
 }
 
index a136a43..d60e19a 100644 (file)
@@ -286,17 +286,6 @@ struct lxc_container {
        bool (*destroy)(struct lxc_container *c);
 
        /*!
-        * \brief Delete the container and all its snapshots.
-        *
-        * \param c Container.
-        *
-        * \return \c true on success, else \c false.
-        *
-        * \note Container must be stopped.
-        */
-       bool (*destroy_with_snapshots)(struct lxc_container *c);
-
-       /*!
         * \brief Save configuaration to a file.
         *
         * \param c Container.
@@ -718,15 +707,6 @@ struct lxc_container {
        bool (*snapshot_destroy)(struct lxc_container *c, const char *snapname);
 
        /*!
-        * \brief Destroy all the container's snapshot.
-        *
-        * \param c Container.
-        *
-        * \return \c true on success, else \c false.
-        */
-       bool (*snapshot_destroy_all)(struct lxc_container *c);
-
-       /*!
         * \brief Determine if the caller may control the container.
         *
         * \param c Container.
@@ -761,6 +741,8 @@ struct lxc_container {
         */
        bool (*remove_device_node)(struct lxc_container *c, const char *src_path, const char *dest_path);
 
+       /* Post LXC-1.0 additions */
+
        /*!
         * \brief Add specified netdev to the container.
         *
@@ -804,6 +786,28 @@ struct lxc_container {
         *
         */
        bool (*restore)(struct lxc_container *c, char *directory, bool verbose);
+
+       /*!
+        * \brief Delete the container and all its snapshots.
+        *
+        * \param c Container.
+        *
+        * \return \c true on success, else \c false.
+        *
+        * \note Container must be stopped.
+        */
+       bool (*destroy_with_snapshots)(struct lxc_container *c);
+
+       /*!
+        * \brief Destroy all the container's snapshot.
+        *
+        * \param c Container.
+        *
+        * \return \c true on success, else \c false.
+        */
+       bool (*snapshot_destroy_all)(struct lxc_container *c);
+
+       /* Post LXC-1.1 additions */
 };
 
 /*!
index fe13898..e9e95f7 100644 (file)
@@ -103,13 +103,13 @@ static char *lxclock_name(const char *p, const char *n)
        char *rundir;
 
        /* lockfile will be:
-        * "/run" + "/lock/lxc/$lxcpath/$lxcname + '\0' if root
+        * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root
         * or
-        * $XDG_RUNTIME_DIR + "/lock/lxc/$lxcpath/$lxcname + '\0' if non-root
+        * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root
         */
 
-       /* length of "/lock/lxc/" + $lxcpath + "/" + "." + $lxcname + '\0' */
-       len = strlen("/lock/lxc/") + strlen(n) + strlen(p) + 3;
+       /* length of "/lxc/lock/" + $lxcpath + "/" + "." + $lxcname + '\0' */
+       len = strlen("/lxc/lock/") + strlen(n) + strlen(p) + 3;
        rundir = get_rundir();
        if (!rundir)
                return NULL;
@@ -120,7 +120,7 @@ static char *lxclock_name(const char *p, const char *n)
                return NULL;
        }
 
-       ret = snprintf(dest, len, "%s/lock/lxc/%s", rundir, p);
+       ret = snprintf(dest, len, "%s/lxc/lock/%s", rundir, p);
        if (ret < 0 || ret >= len) {
                free(dest);
                free(rundir);
@@ -128,40 +128,13 @@ static char *lxclock_name(const char *p, const char *n)
        }
        ret = mkdir_p(dest, 0755);
        if (ret < 0) {
-               /* fall back to "/tmp/" + $(id -u) + "/lxc" + $lxcpath + "/" + "." + $lxcname + '\0'
-                * * maximum length of $(id -u) is 10 calculated by (log (2 ** (sizeof(uid_t) * 8) - 1) / log 10 + 1)
-                * * lxcpath always starts with '/'
-                */
-               int l2 = 22 + strlen(n) + strlen(p);
-               if (l2 > len) {
-                       char *d;
-                       d = realloc(dest, l2);
-                       if (!d) {
-                               free(dest);
-                               free(rundir);
-                               return NULL;
-                       }
-                       len = l2;
-                       dest = d;
-               }
-               ret = snprintf(dest, len, "/tmp/%d/lxc%s", geteuid(), p);
-               if (ret < 0 || ret >= len) {
-                       free(dest);
-                       free(rundir);
-                       return NULL;
-               }
-               ret = mkdir_p(dest, 0755);
-               if (ret < 0) {
-                       free(dest);
-                       free(rundir);
-                       return NULL;
-               }
-               ret = snprintf(dest, len, "/tmp/%d/lxc%s/.%s", geteuid(), p, n);
-       } else
-               ret = snprintf(dest, len, "%s/lock/lxc/%s/.%s", rundir, p, n);
+               free(dest);
+               free(rundir);
+               return NULL;
+       }
 
+       ret = snprintf(dest, len, "%s/lxc/lock/%s/.%s", rundir, p, n);
        free(rundir);
-
        if (ret < 0 || ret >= len) {
                free(dest);
                return NULL;
index 1e1c094..dd8ca9e 100644 (file)
@@ -38,6 +38,7 @@
 #include <sys/wait.h>
 #include <netinet/in.h>
 #include <net/if.h>
+#include <poll.h>
 
 #include "error.h"
 #include "af_unix.h"
@@ -181,7 +182,7 @@ int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr) {
 int lxc_monitor_open(const char *lxcpath)
 {
        struct sockaddr_un addr;
-       int fd,ret;
+       int fd,ret = 0;
        int retry,backoff_ms[] = {10, 50, 100};
        size_t len;
 
@@ -219,19 +220,13 @@ err1:
        return ret;
 }
 
-int lxc_monitor_read_fdset(fd_set *rfds, int nfds, struct lxc_msg *msg,
+int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg,
                           int timeout)
 {
-       struct timeval tval,*tv = NULL;
-       int ret,i;
-
-       if (timeout != -1) {
-               tv = &tval;
-               tv->tv_sec = timeout;
-               tv->tv_usec = 0;
-       }
+       long i;
+       int ret;
 
-       ret = select(nfds, rfds, NULL, NULL, tv);
+       ret = poll(fds, nfds, timeout * 1000);
        if (ret == -1)
                return -1;
        else if (ret == 0)
@@ -241,8 +236,9 @@ int lxc_monitor_read_fdset(fd_set *rfds, int nfds, struct lxc_msg *msg,
         * for when this routine is called again
         */
        for (i = 0; i < nfds; i++) {
-               if (FD_ISSET(i, rfds)) {
-                       ret = recv(i, msg, sizeof(*msg), 0);
+               if (fds[i].revents != 0) {
+                       fds[i].revents = 0;
+                       ret = recv(fds[i].fd, msg, sizeof(*msg), 0);
                        if (ret <= 0) {
                                SYSERROR("client failed to recv (monitord died?) %s",
                                         strerror(errno));
@@ -257,12 +253,13 @@ int lxc_monitor_read_fdset(fd_set *rfds, int nfds, struct lxc_msg *msg,
 
 int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout)
 {
-       fd_set rfds;
+       struct pollfd fds;
 
-       FD_ZERO(&rfds);
-       FD_SET(fd, &rfds);
+       fds.fd = fd;
+       fds.events = POLLIN | POLLPRI;
+       fds.revents = 0;
 
-       return lxc_monitor_read_fdset(&rfds, fd+1, msg, timeout);
+       return lxc_monitor_read_fdset(&fds, 1, msg, timeout);
 }
 
 int lxc_monitor_read(int fd, struct lxc_msg *msg)
@@ -332,12 +329,8 @@ int lxc_monitord_spawn(const char *lxcpath)
                exit(EXIT_FAILURE);
        }
        lxc_check_inherited(NULL, true, pipefd[1]);
-       close(0);
-       close(1);
-       close(2);
-       open("/dev/null", O_RDONLY);
-       open("/dev/null", O_RDWR);
-       open("/dev/null", O_RDWR);
+       if (null_stdfds() < 0)
+               exit(EXIT_FAILURE);
        close(pipefd[0]);
        sprintf(pipefd_str, "%d", pipefd[1]);
        execvp(args[0], args);
index 500a9f2..7a350d8 100644 (file)
@@ -26,6 +26,7 @@
 #include <limits.h>
 #include <sys/param.h>
 #include <sys/un.h>
+#include <poll.h>
 
 #include "conf.h"
 
@@ -41,7 +42,6 @@ struct lxc_msg {
        int value;
 };
 
-extern int lxc_monitor_open(const char *lxcpath);
 extern int lxc_monitor_sock_name(const char *lxcpath, struct sockaddr_un *addr);
 extern int lxc_monitor_fifo_name(const char *lxcpath, char *fifo_path,
                                 size_t fifo_path_sz, int do_mkdirp);
@@ -51,4 +51,44 @@ extern void lxc_monitor_send_exit_code(const char *name, int exit_code,
                            const char *lxcpath);
 extern int lxc_monitord_spawn(const char *lxcpath);
 
+/*
+ * Open the monitoring mechanism for a specific container
+ * The function will return an fd corresponding to the events
+ * Returns a file descriptor on success, < 0 otherwise
+ */
+extern int lxc_monitor_open(const char *lxcpath);
+
+/*
+ * Blocking read for the next container state change
+ * @fd  : the file descriptor provided by lxc_monitor_open
+ * @msg : the variable which will be filled with the state
+ * Returns 0 if the monitored container has exited, > 0 if
+ * data was read, < 0 otherwise
+ */
+extern int lxc_monitor_read(int fd, struct lxc_msg *msg);
+
+/*
+ * Blocking read for the next container state change with timeout
+ * @fd      : the file descriptor provided by lxc_monitor_open
+ * @msg     : the variable which will be filled with the state
+ * @timeout : the timeout in seconds to wait for a state change
+ * Returns 0 if the monitored container has exited, > 0 if
+ * data was read, < 0 otherwise
+ */
+extern int lxc_monitor_read_timeout(int fd, struct lxc_msg *msg, int timeout);
+
+/*
+ * Blocking read from multiple monitors for the next container state
+ * change with timeout
+ * @fds     : struct pollfd descripting the fds to use
+ * @nfds    : the number of entries in fds
+ * @msg     : the variable which will be filled with the state
+ * @timeout : the timeout in seconds to wait for a state change
+ * Returns 0 if the monitored container has exited, > 0 if
+ * data was read, < 0 otherwise
+ */
+extern int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg,
+                          int timeout);
+
+
 #endif
index 108faa0..07dfbc6 100644 (file)
@@ -259,6 +259,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
        uint32_t default_policy_action = -1, default_rule_action = -1, action;
        enum lxc_hostarch_t native_arch = get_hostarch(),
                            cur_rule_arch = native_arch;
+       uint32_t compat_arch = SCMP_ARCH_NATIVE;
 
        if (strncmp(line, "blacklist", 9) == 0)
                blacklist = true;
@@ -288,6 +289,7 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
 
        if (native_arch == lxc_seccomp_arch_amd64) {
                cur_rule_arch = lxc_seccomp_arch_all;
+               compat_arch = SCMP_ARCH_X86;
                compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
                                default_policy_action);
                if (!compat_ctx)
@@ -324,14 +326,6 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
                                        continue;
                                }
                                cur_rule_arch = lxc_seccomp_arch_i386;
-                               if (native_arch == lxc_seccomp_arch_amd64) {
-                                       if (compat_ctx)
-                                               continue;
-                                       compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
-                                                       default_policy_action);
-                                       if (!compat_ctx)
-                                               goto bad;
-                               }
                        } else if (strcmp(line, "[X86_64]") == 0 ||
                                        strcmp(line, "[x86_64]") == 0) {
                                if (native_arch != lxc_seccomp_arch_amd64) {
@@ -342,14 +336,6 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
                        } else if (strcmp(line, "[all]") == 0 ||
                                        strcmp(line, "[ALL]") == 0) {
                                cur_rule_arch = lxc_seccomp_arch_all;
-                               if (native_arch == lxc_seccomp_arch_amd64 && !compat_ctx) {
-                                       if (compat_ctx)
-                                               continue;
-                                       compat_ctx = get_new_ctx(lxc_seccomp_arch_i386,
-                                                       default_policy_action);
-                                       if (!compat_ctx)
-                                               goto bad;
-                               }
                        }
 #ifdef SCMP_ARCH_ARM
                        else if (strcmp(line, "[arm]") == 0 ||
@@ -408,41 +394,24 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
                        goto bad_rule;
                }
 
-               /*
-                * TODO generalize - if !is_compat_only(native_arch, cur_rule_arch)
-                *
-                * in other words, the rule is 32-bit only, on 64-bit host;  don't run
-                * the rule against the native arch.
-                */
-               if (!(cur_rule_arch == lxc_seccomp_arch_i386 &&
-                       native_arch == lxc_seccomp_arch_amd64)) {
-                       INFO("Adding non-compat rule for %s action %d", line, action);
+               if (cur_rule_arch == native_arch ||
+                   cur_rule_arch == lxc_seccomp_arch_native ||
+                   compat_arch == SCMP_ARCH_NATIVE) {
+                       INFO("Adding native rule for %s action %d", line, action);
                        if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
                                goto bad_rule;
                }
-
-               /*
-                * TODO generalize - if need_compat(native_arch, cur_rule_arch)
-                */
-               if (native_arch == lxc_seccomp_arch_amd64 &&
-                       cur_rule_arch != lxc_seccomp_arch_amd64) {
-                       int nr1, nr2;
+               else if (cur_rule_arch != lxc_seccomp_arch_all) {
+                       INFO("Adding compat-only rule for %s action %d", line, action);
+                       if (!do_resolve_add_rule(compat_arch, line, compat_ctx, action))
+                               goto bad_rule;
+               }
+               else {
+                       INFO("Adding native rule for %s action %d", line, action);
+                       if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
+                               goto bad_rule;
                        INFO("Adding compat rule for %s action %d", line, action);
-                       nr1 = seccomp_syscall_resolve_name_arch(SCMP_ARCH_X86, line);
-                       nr2 = seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, line);
-                       if (nr1 == nr2) {
-                               /* If the syscall # is the same for 32- and 64-bit, then we cannot
-                                * apply it to the compat_ctx.  So apply it to the noncompat ctx.
-                                * We may already have done so, but that's ok
-                                */
-                               INFO("Adding non-compat rule bc nr1 == nr2 (%d, %d)", nr1, nr2);
-                               if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, conf->seccomp_ctx, action))
-                                       goto bad_rule;
-                               continue;
-                       }
-                       INFO("Really adding compat rule bc nr1 == nr2 (%d, %d)", nr1, nr2);
-                       if (!do_resolve_add_rule(SCMP_ARCH_X86, line,
-                                               compat_ctx, action))
+                       if (!do_resolve_add_rule(compat_arch, line, compat_ctx, action))
                                goto bad_rule;
                }
        }
index d615375..2fc026e 100644 (file)
@@ -212,6 +212,9 @@ restart:
                if (fd == fddir || fd == lxc_log_fd || fd == fd_to_ignore)
                        continue;
 
+               if (current_config && fd == current_config->logfd)
+                       continue;
+
                if (match_fd(fd))
                        continue;
 
@@ -759,6 +762,9 @@ static int do_start(void *data)
 
        close(handler->sigfd);
 
+       if (handler->backgrounded && null_stdfds() < 0)
+               goto out_warn_father;
+
        /* after this call, we are in error because this
         * ops should not return as it execs */
        handler->ops->start(handler, handler->data);
@@ -1112,7 +1118,8 @@ int get_netns_fd(int pid)
 }
 
 int __lxc_start(const char *name, struct lxc_conf *conf,
-               struct lxc_operations* ops, void *data, const char *lxcpath)
+               struct lxc_operations* ops, void *data, const char *lxcpath,
+               bool backgrounded)
 {
        struct lxc_handler *handler;
        int err = -1;
@@ -1126,6 +1133,7 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
        }
        handler->ops = ops;
        handler->data = data;
+       handler->backgrounded = backgrounded;
 
        if (must_drop_cap_sys_boot(handler->conf)) {
                #if HAVE_SYS_CAPABILITY_H
@@ -1165,6 +1173,8 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
                goto out_detach_blockdev;
        }
 
+       handler->conf->reboot = 0;
+
        netnsfd = get_netns_fd(handler->pid);
 
        err = lxc_poll(name, handler);
@@ -1257,12 +1267,12 @@ static struct lxc_operations start_ops = {
 };
 
 int lxc_start(const char *name, char *const argv[], struct lxc_conf *conf,
-             const char *lxcpath)
+             const char *lxcpath, bool backgrounded)
 {
        struct start_args start_arg = {
                .argv = argv,
        };
 
        conf->need_utmp_watch = 1;
-       return __lxc_start(name, conf, &start_ops, &start_arg, lxcpath);
+       return __lxc_start(name, conf, &start_ops, &start_arg, lxcpath, backgrounded);
 }
index aab063a..f1a41f5 100644 (file)
@@ -74,6 +74,7 @@ struct lxc_handler {
        const char *lxcpath;
        void *cgroup_data;
        int ttysock[2]; // socketpair for child->parent tty fd passing
+       bool backgrounded; // indicates whether should we close std{in,out,err} on start
 };
 
 
@@ -85,7 +86,7 @@ extern void lxc_fini(const char *name, struct lxc_handler *handler);
 
 extern int lxc_check_inherited(struct lxc_conf *conf, bool closeall, int fd_to_ignore);
 int __lxc_start(const char *, struct lxc_conf *, struct lxc_operations *,
-               void *, const char *);
+               void *, const char *, bool);
 
 extern void resolve_clone_flags(struct lxc_handler *handler);
 #endif
index 1df6e8f..7ced314 100644 (file)
 
 lxc_log_define(lxc_utils, lxc);
 
+/*
+ * if path is btrfs, tries to remove it and any subvolumes beneath it
+ */
+extern bool btrfs_try_remove_subvol(const char *path);
+
 static int _recursive_rmdir(char *dirname, dev_t pdev,
                            const char *exclude, int level, bool onedev)
 {
@@ -127,11 +132,16 @@ static int _recursive_rmdir(char *dirname, dev_t pdev,
                ret = lstat(pathname, &mystat);
                if (ret) {
                        ERROR("%s: failed to stat %s", __func__, pathname);
-                       failed=1;
+                       failed = 1;
                        continue;
                }
-               if (onedev && mystat.st_dev != pdev)
+               if (onedev && mystat.st_dev != pdev) {
+                       /* TODO should we be checking /proc/self/mountinfo for
+                        * pathname and not doing this if found? */
+                       if (btrfs_try_remove_subvol(pathname))
+                               INFO("Removed btrfs subvolume at %s\n", pathname);
                        continue;
+               }
                if (S_ISDIR(mystat.st_mode)) {
                        if (_recursive_rmdir(pathname, pdev, exclude, level+1, onedev) < 0)
                                failed=1;
@@ -143,11 +153,9 @@ static int _recursive_rmdir(char *dirname, dev_t pdev,
                }
        }
 
-       if (rmdir(dirname) < 0) {
-               if (!hadexclude) {
-                       ERROR("%s: failed to delete %s", __func__, dirname);
-                       failed=1;
-               }
+       if (rmdir(dirname) < 0 && !btrfs_try_remove_subvol(dirname) && !hadexclude) {
+               ERROR("%s: failed to delete %s", __func__, dirname);
+               failed=1;
        }
 
        ret = closedir(dir);
@@ -196,43 +204,6 @@ extern int lxc_rmdir_onedev(char *path, const char *exclude)
        return _recursive_rmdir(path, mystat.st_dev, exclude, 0, onedev);
 }
 
-static int mount_fs(const char *source, const char *target, const char *type)
-{
-       /* the umount may fail */
-       if (umount(target))
-               WARN("failed to unmount %s : %s", target, strerror(errno));
-
-       if (mount(source, target, type, 0, NULL)) {
-               ERROR("failed to mount %s : %s", target, strerror(errno));
-               return -1;
-       }
-
-       DEBUG("'%s' mounted on '%s'", source, target);
-
-       return 0;
-}
-
-extern void lxc_setup_fs(void)
-{
-       if (mount_fs("proc", "/proc", "proc"))
-               INFO("failed to remount proc");
-
-       /* if we can't mount /dev/shm, continue anyway */
-       if (mount_fs("shmfs", "/dev/shm", "tmpfs"))
-               INFO("failed to mount /dev/shm");
-
-       /* If we were able to mount /dev/shm, then /dev exists */
-       /* Sure, but it's read-only per config :) */
-       if (access("/dev/mqueue", F_OK) && mkdir("/dev/mqueue", 0666)) {
-               DEBUG("failed to create '/dev/mqueue'");
-               return;
-       }
-
-       /* continue even without posix message queue support */
-       if (mount_fs("mqueue", "/dev/mqueue", "mqueue"))
-               INFO("failed to mount /dev/mqueue");
-}
-
 /* borrowed from iproute2 */
 extern int get_u16(unsigned short *val, const char *arg, int base)
 {
@@ -275,195 +246,6 @@ extern int mkdir_p(const char *dir, mode_t mode)
        return 0;
 }
 
-extern void remove_trailing_slashes(char *p)
-{
-       int l = strlen(p);
-       while (--l >= 0 && (p[l] == '/' || p[l] == '\n'))
-               p[l] = '\0';
-}
-
-static char *copy_global_config_value(char *p)
-{
-       int len = strlen(p);
-       char *retbuf;
-
-       if (len < 1)
-               return NULL;
-       if (p[len-1] == '\n') {
-               p[len-1] = '\0';
-               len--;
-       }
-       retbuf = malloc(len+1);
-       if (!retbuf)
-               return NULL;
-       strcpy(retbuf, p);
-       return retbuf;
-}
-
-#define DEFAULT_VG "lxc"
-#define DEFAULT_THIN_POOL "lxc"
-#define DEFAULT_ZFSROOT "lxc"
-
-const char *lxc_global_config_value(const char *option_name)
-{
-       static const char * const options[][2] = {
-               { "lxc.bdev.lvm.vg",        DEFAULT_VG      },
-               { "lxc.bdev.lvm.thin_pool", DEFAULT_THIN_POOL },
-               { "lxc.bdev.zfs.root",      DEFAULT_ZFSROOT },
-               { "lxc.lxcpath",            NULL            },
-               { "lxc.default_config",     NULL            },
-               { "lxc.cgroup.pattern",     NULL            },
-               { "lxc.cgroup.use",         NULL            },
-               { NULL, NULL },
-       };
-
-       /* placed in the thread local storage pool for non-bionic targets */
-#ifdef HAVE_TLS
-       static __thread const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
-#else
-       static const char *values[sizeof(options) / sizeof(options[0])] = { 0 };
-#endif
-
-       /* user_config_path is freed as soon as it is used */
-       char *user_config_path = NULL;
-
-       /*
-        * The following variables are freed at bottom unconditionally.
-        * So NULL the value if it is to be returned to the caller
-        */
-       char *user_default_config_path = NULL;
-       char *user_lxc_path = NULL;
-       char *user_cgroup_pattern = NULL;
-
-       if (geteuid() > 0) {
-               const char *user_home = getenv("HOME");
-               if (!user_home)
-                       user_home = "/";
-
-               user_config_path = malloc(sizeof(char) * (22 + strlen(user_home)));
-               user_default_config_path = malloc(sizeof(char) * (26 + strlen(user_home)));
-               user_lxc_path = malloc(sizeof(char) * (19 + strlen(user_home)));
-
-               sprintf(user_config_path, "%s/.config/lxc/lxc.conf", user_home);
-               sprintf(user_default_config_path, "%s/.config/lxc/default.conf", user_home);
-               sprintf(user_lxc_path, "%s/.local/share/lxc/", user_home);
-               user_cgroup_pattern = strdup("lxc/%n");
-       }
-       else {
-               user_config_path = strdup(LXC_GLOBAL_CONF);
-               user_default_config_path = strdup(LXC_DEFAULT_CONFIG);
-               user_lxc_path = strdup(LXCPATH);
-               user_cgroup_pattern = strdup(DEFAULT_CGROUP_PATTERN);
-       }
-
-       const char * const (*ptr)[2];
-       size_t i;
-       char buf[1024], *p, *p2;
-       FILE *fin = NULL;
-
-       for (i = 0, ptr = options; (*ptr)[0]; ptr++, i++) {
-               if (!strcmp(option_name, (*ptr)[0]))
-                       break;
-       }
-       if (!(*ptr)[0]) {
-               free(user_config_path);
-               free(user_default_config_path);
-               free(user_lxc_path);
-               free(user_cgroup_pattern);
-               errno = EINVAL;
-               return NULL;
-       }
-
-       if (values[i]) {
-               free(user_config_path);
-               free(user_default_config_path);
-               free(user_lxc_path);
-               free(user_cgroup_pattern);
-               return values[i];
-       }
-
-       fin = fopen_cloexec(user_config_path, "r");
-       free(user_config_path);
-       if (fin) {
-               while (fgets(buf, 1024, fin)) {
-                       if (buf[0] == '#')
-                               continue;
-                       p = strstr(buf, option_name);
-                       if (!p)
-                               continue;
-                       /* see if there was just white space in front
-                        * of the option name
-                        */
-                       for (p2 = buf; p2 < p; p2++) {
-                               if (*p2 != ' ' && *p2 != '\t')
-                                       break;
-                       }
-                       if (p2 < p)
-                               continue;
-                       p = strchr(p, '=');
-                       if (!p)
-                               continue;
-                       /* see if there was just white space after
-                        * the option name
-                        */
-                       for (p2 += strlen(option_name); p2 < p; p2++) {
-                               if (*p2 != ' ' && *p2 != '\t')
-                                       break;
-                       }
-                       if (p2 < p)
-                               continue;
-                       p++;
-                       while (*p && (*p == ' ' || *p == '\t')) p++;
-                       if (!*p)
-                               continue;
-
-                       if (strcmp(option_name, "lxc.lxcpath") == 0) {
-                               free(user_lxc_path);
-                               user_lxc_path = copy_global_config_value(p);
-                               remove_trailing_slashes(user_lxc_path);
-                               values[i] = user_lxc_path;
-                               user_lxc_path = NULL;
-                               goto out;
-                       }
-
-                       values[i] = copy_global_config_value(p);
-                       goto out;
-               }
-       }
-       /* could not find value, use default */
-       if (strcmp(option_name, "lxc.lxcpath") == 0) {
-               remove_trailing_slashes(user_lxc_path);
-               values[i] = user_lxc_path;
-               user_lxc_path = NULL;
-       }
-       else if (strcmp(option_name, "lxc.default_config") == 0) {
-               values[i] = user_default_config_path;
-               user_default_config_path = NULL;
-       }
-       else if (strcmp(option_name, "lxc.cgroup.pattern") == 0) {
-               values[i] = user_cgroup_pattern;
-               user_cgroup_pattern = NULL;
-       }
-       else
-               values[i] = (*ptr)[1];
-
-       /* special case: if default value is NULL,
-        * and there is no config, don't view that
-        * as an error... */
-       if (!values[i])
-               errno = 0;
-
-out:
-       if (fin)
-               fclose(fin);
-
-       free(user_cgroup_pattern);
-       free(user_default_config_path);
-       free(user_lxc_path);
-
-       return values[i];
-}
-
 char *get_rundir()
 {
        char *rundir;
@@ -669,50 +451,6 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
        return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
 }
 
-FILE *fopen_cloexec(const char *path, const char *mode)
-{
-       int open_mode = 0;
-       int step = 0;
-       int fd;
-       int saved_errno = 0;
-       FILE *ret;
-
-       if (!strncmp(mode, "r+", 2)) {
-               open_mode = O_RDWR;
-               step = 2;
-       } else if (!strncmp(mode, "r", 1)) {
-               open_mode = O_RDONLY;
-               step = 1;
-       } else if (!strncmp(mode, "w+", 2)) {
-               open_mode = O_RDWR | O_TRUNC | O_CREAT;
-               step = 2;
-       } else if (!strncmp(mode, "w", 1)) {
-               open_mode = O_WRONLY | O_TRUNC | O_CREAT;
-               step = 1;
-       } else if (!strncmp(mode, "a+", 2)) {
-               open_mode = O_RDWR | O_CREAT | O_APPEND;
-               step = 2;
-       } else if (!strncmp(mode, "a", 1)) {
-               open_mode = O_WRONLY | O_CREAT | O_APPEND;
-               step = 1;
-       }
-       for (; mode[step]; step++)
-               if (mode[step] == 'x')
-                       open_mode |= O_EXCL;
-       open_mode |= O_CLOEXEC;
-
-       fd = open(path, open_mode, 0666);
-       if (fd < 0)
-               return NULL;
-
-       ret = fdopen(fd, mode);
-       saved_errno = errno;
-       if (!ret)
-               close(fd);
-       errno = saved_errno;
-       return ret;
-}
-
 extern struct lxc_popen_FILE *lxc_popen(const char *command)
 {
        struct lxc_popen_FILE *fp = NULL;
@@ -1644,15 +1382,87 @@ int setproctitle(char *title)
                if (len >= arg_end - arg_start) {
                        env_start = env_end;
                }
+
                arg_end = arg_start + len;
+
+               /* check overflow */
+               if (arg_end < len || arg_end < arg_start) {
+                       return -1;
+               }
+
        }
 
        strcpy((char*)arg_start, title);
 
-       ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_START,   (long)arg_start, 0, 0);
-       ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_END,     (long)arg_end, 0, 0);
-       ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_START,   (long)env_start, 0, 0);
-       ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_END,     (long)env_end, 0, 0);
+       ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_START,   arg_start, 0, 0);
+       ret |= prctl(PR_SET_MM, PR_SET_MM_ARG_END,     arg_end, 0, 0);
+       ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_START,   env_start, 0, 0);
+       ret |= prctl(PR_SET_MM, PR_SET_MM_ENV_END,     env_end, 0, 0);
+
+       return ret;
+}
+
+/*
+ * Mount a proc under @rootfs if proc self points to a pid other than
+ * my own.  This is needed to have a known-good proc mount for setting
+ * up LSMs both at container startup and attach.
+ *
+ * @rootfs : the rootfs where proc should be mounted
+ *
+ * Returns < 0 on failure, 0 if the correct proc was already mounted
+ * and 1 if a new proc was mounted.
+ */
+int mount_proc_if_needed(const char *rootfs)
+{
+       char path[MAXPATHLEN];
+       char link[20];
+       int linklen, ret;
+       int mypid;
+
+       ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs);
+       if (ret < 0 || ret >= MAXPATHLEN) {
+               SYSERROR("proc path name too long");
+               return -1;
+       }
+       memset(link, 0, 20);
+       linklen = readlink(path, link, 20);
+       mypid = (int)getpid();
+       INFO("I am %d, /proc/self points to '%s'", mypid, link);
+       ret = snprintf(path, MAXPATHLEN, "%s/proc", rootfs);
+       if (linklen < 0) /* /proc not mounted */
+               goto domount;
+       if (atoi(link) != mypid) {
+               /* wrong /procs mounted */
+               umount2(path, MNT_DETACH); /* ignore failure */
+               goto domount;
+       }
+       /* the right proc is already mounted */
+       return 0;
+
+domount:
+       if (mount("proc", path, "proc", 0, NULL))
+               return -1;
+       INFO("Mounted /proc in container for security transition");
+       return 1;
+}
 
+int null_stdfds(void)
+{
+       int fd, ret = -1;
+
+       fd = open("/dev/null", O_RDWR);
+       if (fd < 0)
+               return -1;
+
+       if (dup2(fd, 0) < 0)
+               goto err;
+       if (dup2(fd, 1) < 0)
+               goto err;
+       if (dup2(fd, 2) < 0)
+               goto err;
+
+       ret = 0;
+err:
+       close(fd);
        return ret;
 }
index cc18906..ee12dde 100644 (file)
 #include <unistd.h>
 
 #include "config.h"
+#include "initutils.h"
 
 /* returns 1 on success, 0 if there were any failures */
 extern int lxc_rmdir_onedev(char *path, const char *exclude);
-extern void lxc_setup_fs(void);
 extern int get_u16(unsigned short *val, const char *arg, int base);
 extern int mkdir_p(const char *dir, mode_t mode);
-extern void remove_trailing_slashes(char *p);
 extern char *get_rundir(void);
 
-extern const char *lxc_global_config_value(const char *option_name);
-
 /* Define getline() if missing from the C library */
 #ifndef HAVE_GETLINE
 #ifdef HAVE_FGETLN
@@ -148,10 +145,6 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
 }
 #endif
 
-/* open a file with O_CLOEXEC */
-FILE *fopen_cloexec(const char *path, const char *mode);
-
-
 /* Struct to carry child pid from lxc_popen() to lxc_pclose().
  * Not an opaque struct to allow direct access to the underlying FILE *
  * (i.e., struct lxc_popen_FILE *file; fgets(buf, sizeof(buf), file->f))
@@ -275,7 +268,6 @@ extern bool dir_exists(const char *path);
 
 #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
 uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
-#endif
 
 int detect_shared_rootfs(void);
 int detect_ramfs_rootfs(void);
@@ -287,3 +279,6 @@ bool switch_to_ns(pid_t pid, const char *ns);
 int is_dir(const char *path);
 char *get_template_path(const char *t);
 int setproctitle(char *title);
+int mount_proc_if_needed(const char *rootfs);
+int null_stdfds(void);
+#endif /* __LXC_UTILS_H */
index 40c3b5e..cfe9e90 100644 (file)
@@ -25,7 +25,7 @@
 
 #define LXC_VERSION_MAJOR 1
 #define LXC_VERSION_MINOR 1
-#define LXC_VERSION_MICRO 2
-#define LXC_VERSION "1.1.2"
+#define LXC_VERSION_MICRO 3
+#define LXC_VERSION "1.1.3"
 
 #endif
index dd3393a..233ca12 100644 (file)
@@ -122,7 +122,7 @@ int main(int argc, char *argv[])
                exit(1);
        }
        struct stat sb;
-       char *pathname = RUNTIME_PATH "/lock/lxc/var/lib/lxc/";
+       char *pathname = RUNTIME_PATH "/lxc/lock/var/lib/lxc/";
        ret = stat(pathname, &sb);
        if (ret != 0) {
                fprintf(stderr, "%d: filename %s not created\n", __LINE__,
index 181b693..4c91339 100755 (executable)
@@ -45,7 +45,7 @@ sleep 5s
 # The first time this usually fails because CRIU cannot checkpoint things with
 # data on a socket.
 lxc-checkpoint -n $name -v -s -D /tmp/checkpoint || FAIL "failed checkpointing"
-lxc-wait -n u1 -s STOPPED
+lxc-wait -n $name -s STOPPED
 lxc-checkpoint -n $name -v -r -D /tmp/checkpoint || FAIL "failed restoring"
 
 lxc-stop -n $name -t 1
index 886a838..6dcc51b 100644 (file)
@@ -83,7 +83,7 @@ get_static_apk () {
 
     # verify the static apk binary signature
     APK=$rootfs/sbin/apk.static
-    openssl dgst -verify $rootfs/etc/apk/keys/$keyname \
+    openssl dgst -sha1 -verify $rootfs/etc/apk/keys/$keyname \
         -signature "$APK.SIGN.RSA.$keyname" "$APK" || return 1
 
     if [ "$auto_repo_dir" ]; then
@@ -251,7 +251,7 @@ lxc.cgroup.devices.allow = c 254:0 rm
 # mounts point
 lxc.mount.auto=cgroup:mixed proc:mixed sys:mixed
 lxc.mount.entry=run run tmpfs nodev,noexec,nosuid,relatime,size=1m,mode=0755 0 0
-lxc.mount.entry=shm dev/shm tmpfs nodev,nosuid,noexec,mode=1777 0 0
+lxc.mount.entry=shm dev/shm tmpfs nodev,nosuid,noexec,mode=1777,create=dir 0 0
 
 EOF
 
index 265b7d0..1a27cd3 100644 (file)
@@ -253,7 +253,7 @@ HOSTNAME=${UTSNAME}
 NM_CONTROLLED=no
 TYPE=Ethernet
 MTU=${MTU}
-DHCP_HOSTNAME=$name
+DHCP_HOSTNAME=\`hostname\`
 EOF
 
     # set the hostname
@@ -413,10 +413,12 @@ download_centos()
 
     # download a mini centos into a cache
     echo "Downloading centos minimal ..."
+    YUM0="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
+
     if yum -h | grep -q 'releasever=RELEASEVER'; then
-        YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck --releasever=$release"
+       YUM="$YUM0 --releasever=$release"
     else
-        YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
+       YUM="$YUM0"
     fi
     PKG_LIST="yum initscripts passwd rsyslog vim-minimal openssh-server openssh-clients dhclient chkconfig rootfiles policycoreutils"
 
@@ -483,7 +485,7 @@ EOF
         mknod -m 666 $INSTALL_ROOT/$INSTALL_ROOT/dev/urandom c 1 9
         mkdir -p $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum
         cp -al $INSTALL_ROOT/var/cache/yum/* $INSTALL_ROOT/$INSTALL_ROOT/var/cache/yum/
-        chroot $INSTALL_ROOT $YUM install $PKG_LIST
+        chroot $INSTALL_ROOT $YUM0 install $PKG_LIST
         if [ $? -ne 0 ]; then
             echo "Failed to download the rootfs, aborting."
             return 1
index 938f0db..b57e526 100644 (file)
@@ -32,6 +32,7 @@ done
 
 # Make sure the usual locations are in PATH
 export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin
+export GREP_OPTIONS=""
 
 MIRROR=${MIRROR:-http://http.debian.net/debian}
 SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.debian.org/}
@@ -96,16 +97,6 @@ $hostname
 EOF
 
     # reconfigure some services
-    if [ -z "$LANG" ]; then
-        chroot $rootfs locale-gen en_US.UTF-8 UTF-8
-        chroot $rootfs update-locale LANG=en_US.UTF-8
-    else
-        encoding=$(echo $LANG | cut -d. -f2)
-        chroot $rootfs sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
-            -i /etc/locale.gen 2> /dev/null
-        chroot $rootfs locale-gen $LANG $encoding
-        chroot $rootfs update-locale LANG=$LANG
-    fi
 
     # remove pointless services in a container
     chroot $rootfs /usr/sbin/update-rc.d -f checkroot.sh disable
@@ -168,8 +159,13 @@ write_sourceslist()
 
     cat >> "${rootfs}/etc/apt/sources.list" << EOF
 ${prefix} $MIRROR          ${release}         main contrib non-free
+EOF
+
+    if [ "$release" != "unstable" -a "$release" != "sid" ]; then
+      cat >> "${rootfs}/etc/apt/sources.list" << EOF
 ${prefix} $SECURITY_MIRROR ${release}/updates main contrib non-free
 EOF
+    fi
 }
 
 install_packages()
@@ -200,6 +196,11 @@ configure_debian_systemd()
     mkdir -p ${rootfs}/{lib,etc}/systemd/system
     mkdir -p ${rootfs}/etc/systemd/system/getty.target.wants
 
+    # Fix getty-static-service as debootstrap does not install dbus
+    if [ -e $rootfs//lib/systemd/system/getty-static.service ] ; then
+        sed 's/ getty@tty[5-9].service//g' $rootfs/lib/systemd/system/getty-static.service |  sed 's/\(tty2-tty\)[5-9]/\14/g' > $rootfs/etc/systemd/system/getty-static.service
+    fi
+
     # This function has been copied and adapted from lxc-fedora
     rm -f ${rootfs}/etc/systemd/system/default.target
     chroot ${rootfs} ln -s /dev/null /etc/systemd/system/udev.service
@@ -397,6 +398,25 @@ EOF
 
     # Re-enable service startup
     rm ${rootfs}/usr/sbin/policy-rc.d
+    
+    # reconfigure locales
+    if [ -z "$LANG" ]; then
+        cat >> $rootfs/etc/locale.gen << EOF
+en_US.UTF-8 UTF-8
+EOF
+        chroot $rootfs locale-gen en_US.UTF-8 UTF-8
+        chroot $rootfs update-locale LANG=en_US.UTF-8
+    else
+        encoding=$(echo $LANG | cut -d. -f2)
+        chroot $rootfs sed -e "s/^# \(${LANG} ${encoding}\)/\1/" \
+            -i /etc/locale.gen 2> /dev/null
+        cat >> $rootfs/etc/locale.gen << EOF
+$LANG $encoding
+EOF
+        chroot $rootfs locale-gen $LANG $encoding
+        chroot $rootfs update-locale LANG=$LANG
+    fi
+    # end
 }
 
 clean()
index 499685f..f6e5be5 100644 (file)
@@ -226,6 +226,7 @@ DEVICE=eth0
 BOOTPROTO=dhcp
 ONBOOT=yes
 HOSTNAME=${utsname}
+DHCP_HOSTNAME=\`hostname\`
 NM_CONTROLLED=no
 TYPE=Ethernet
 MTU=${MTU}
@@ -586,7 +587,7 @@ Have a beer or a cup of coffee.  This will take a bit (~300MB).
         # Right now, we are using Fedora 20 for the inial bootstrap.
         # We could make this the "current" Fedora rev (F > 15).
 
-        rsync -av mirrors.kernel.org::fedora/releases/20/Fedora/$basearch/os/LiveOS .
+        rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/LiveOS .
 
         if [[ 0 == $? ]]
         then
@@ -663,8 +664,8 @@ This will take a couple of minutes.  Patience..."
     # of this LiveOS image we're camped out on.  This is the beginning
     # of the butt ugly hack.  Look close or you may missing it...
 
-    rsync -av mirrors.kernel.org::fedora/releases/20/Fedora/$basearch/os/Packages/r/rpm-[0-9]* \
-        mirrors.kernel.org::fedora/releases/20/Fedora/$basearch/os/Packages/y/yum-[0-9]* .
+    rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/r/rpm-[0-9]* \
+        ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/y/yum-[0-9]* .
 
     # And here it is...
     # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?!
@@ -696,7 +697,7 @@ This will take a couple of minutes.  Patience..."
     echo "Stage 1 creation complete.  Building stage 2 Installation Bootstrap"
 
     mount -o bind ../bootstrap run/install
-    rsync -av mirrors.kernel.org::fedora/releases/20/Fedora/$basearch/os/Packages/f/fedora-release-20* .
+    rsync -av ${mirrorurl}/fedora/linux/releases/20/Fedora/$basearch/os/Packages/f/fedora-release-20* .
 
     # The --nodeps is STUPID but F15 had a bogus dependency on RawHide?!?!
     chroot . rpm --root /run/install --nodeps -ivh fedora-release-*
@@ -1232,7 +1233,6 @@ if [ ! -z "$clean" -a -z "$path" ]; then
     exit 0
 fi
 
-
 basearch=${arch}
 # Map a few architectures to their generic Fedora repository archs.
 # The two ARM archs are a bit of a guesstimate for the v5 and v6
@@ -1247,6 +1247,12 @@ armv6l|armv7l|armv8l) basearch=armhfp ;;
 *) ;;
 esac
 
+mirrorurl="archives.fedoraproject.org::fedora-archive"
+case "$basearch" in
+ppc64|s390x) mirrorurl="archives.fedoraproject.org::fedora-secondary" ;;
+*) ;;
+esac
+
 # Somebody wants to specify an arch.  This is very limited case.
 #       i386/i586/i686 on i386/x86_64
 #           - or -
@@ -1344,8 +1350,8 @@ if [ -z "$release" ]; then
     if [ "$is_fedora" -a "$fedora_host_ver" ]; then
         release=$fedora_host_ver
     else
-        echo "This is not a fedora host and release missing, defaulting to 20 use -R|--release to specify release"
-        release=20
+        echo "This is not a fedora host and release missing, defaulting to 22 use -R|--release to specify release"
+        release=22
     fi
 fi
 
index 4ff1dcf..d4e2b28 100644 (file)
@@ -421,7 +421,8 @@ if [ -z "$path" ]; then
 fi
 
 if grep -q Harlequin /etc/os-release || grep -q Tumbleweed /etc/os-release ; then
-    if [[ "$(zypper info build|awk -F "[- ]" '/Version/ {print $2}')" -lt "20141120" ]] ; then
+    BVER=`rpm -q --qf '%{version}\n' build`
+    if [ $? -ne 0 -o "$BVER" -lt "20141120" ]; then
        echo "Building openSUSE containers with your version of the build package is broken. Please install the update to version 20141120 or newer."
        exit 1
     fi
index 5a6c3de..fbd0fd2 100644 (file)
@@ -302,8 +302,8 @@ EOF
         fi
     fi
     if [ $container_release_major = "6" ]; then
-        sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit
-        sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm && mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit
+        sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.sysinit
+        sed -i 's|mount -n -o remount /dev/shm >/dev/null 2>&1$|mkdir -p /dev/shm \&\& mount -t tmpfs tmpfs /dev/shm # LXC|' $container_rootfs/etc/rc.d/rc.sysinit
     fi
 
     # there might be other services that are useless but the below set is a good start
@@ -336,7 +336,7 @@ DEVICE=eth0
 BOOTPROTO=dhcp
 ONBOOT=yes
 HOSTNAME=$name
-DHCP_HOSTNAME=$name
+DHCP_HOSTNAME=\`hostname\`
 NM_CONTROLLED=no
 TYPE=Ethernet
 EOF