]> git.proxmox.com Git - lxc.git/commitdiff
bump version to 2.1.1-1
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Mon, 20 Nov 2017 10:14:38 +0000 (11:14 +0100)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Mon, 20 Nov 2017 10:27:18 +0000 (11:27 +0100)
And switch to using submodules.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
23 files changed:
.gitmodules [new file with mode: 0644]
Makefile
debian/changelog
debian/patches/0001-lxc.service-start-after-a-potential-syslog.service.patch
debian/patches/0002-jessie-systemd-remove-Delegate-flag-to-silence-warni.patch [deleted file]
debian/patches/0002-pve-run-lxcnetaddbr-when-instantiating-veths.patch [new file with mode: 0644]
debian/patches/0003-deny-rw-mounting-of-sys-and-proc.patch [new file with mode: 0644]
debian/patches/0003-pve-run-lxcnetaddbr-when-instantiating-veths.patch [deleted file]
debian/patches/0004-deny-rw-mounting-of-sys-and-proc.patch [deleted file]
debian/patches/0004-separate-the-limiting-from-the-namespaced-cgroup-roo.patch [new file with mode: 0644]
debian/patches/0005-separate-the-limiting-from-the-namespaced-cgroup-roo.patch [deleted file]
debian/patches/0005-start-initutils-make-cgroupns-separation-level-confi.patch [new file with mode: 0644]
debian/patches/0006-rename-cgroup-namespace-directory-to-ns.patch [new file with mode: 0644]
debian/patches/0006-start-initutils-make-cgroupns-separation-level-confi.patch [deleted file]
debian/patches/0007-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch [new file with mode: 0644]
debian/patches/0007-rename-cgroup-namespace-directory-to-ns.patch [deleted file]
debian/patches/0008-Make-lxc-.service-forking.patch [new file with mode: 0644]
debian/patches/0008-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch [deleted file]
debian/patches/0009-network-add-missing-checks-for-empty-links.patch [deleted file]
debian/patches/0010-start-unshare-cgroup-after-setting-up-device-limits.patch [deleted file]
debian/patches/series
lxc [new submodule]
lxc.tgz [deleted file]

diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..90a83b1
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "lxc"]
+       path = lxc
+       url = ../mirror_lxc
index d88440bf3688db1abe1af80a81052112d044cd3a..844b9c03227aab848ec937ee505f0d1e7cab2817 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
 PACKAGE=lxc-pve
-LXCVER=2.1.0
-DEBREL=2
+LXCVER=2.1.1
+DEBREL=1
 
 SRCDIR=lxc
-SRCTAR=${SRCDIR}.tgz
+BUILDSRC := $(SRCDIR).tmp
 
 ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH)
 GITVERSION:=$(shell cat .git/refs/heads/master)
@@ -16,24 +16,22 @@ DEBS=$(DEB1) $(DEB2)
 all: ${DEBS}
        echo ${DEBS}
 
+.PHONY: submodule
+submodule:
+       test -f "${SRCDIR}/debian/changelog" || git submodule update --init
+
 .PHONY: deb
 deb: ${DEBS}
 $(DEB2): $(DEB1)
-$(DEB1): ${SRCTAR}
-       rm -rf ${SRCDIR}
-       tar xf ${SRCTAR}
-       cp -a debian ${SRCDIR}/debian
-       echo "git clone git://git.proxmox.com/git/lxc.git\\ngit checkout ${GITVERSION}" >  ${SRCDIR}/debian/SOURCE
-       cd ${SRCDIR}; dpkg-buildpackage -rfakeroot -b -us -uc
-       lintian ${DEBS}
-
-
-.PHONY: download
-download ${SRCTAR}:
-       rm -rf ${SRCDIR} ${SRCTAR}
-       git clone -b lxc-${LXCVER} git://github.com/lxc/lxc
-       tar czf ${SRCTAR}.tmp ${SRCDIR}
-       mv ${SRCTAR}.tmp ${SRCTAR}
+$(DEB1): | submodule
+       rm -f *.deb
+       rm -rf $(BUILDSRC)
+       mkdir $(BUILDSRC)
+       cp -a $(SRCDIR)/* $(BUILDSRC)/
+       cp -a debian $(BUILDSRC)/debian
+       echo "git clone git://git.proxmox.com/git/lxc.git\\ngit checkout $(GITVERSION)" > $(BUILDSRC)/debian/SOURCE
+       cd $(BUILDSRC); dpkg-buildpackage -rfakeroot -b -us -uc
+       lintian $(DEBS)
 
 .PHONY: upload
 upload: ${DEBS}
@@ -43,8 +41,7 @@ distclean: clean
 
 .PHONY: clean
 clean:
-       rm -rf ${SRCDIR} ${SRCDIR}.tmp *_${ARCH}.deb *.changes *.dsc *.buildinfo
-       find . -name '*~' -exec rm {} ';'
+       rm -rf $(BUILDSRC) *_${ARCH}.deb *.changes *.dsc *.buildinfo
 
 .PHONY: dinstall
 dinstall: ${DEBS}
index f732750b27257adaec388db6650a090cff6c351b..684d184dbef0f72a3eac27dc9bd4502f3fb74beb 100644 (file)
@@ -1,3 +1,9 @@
+lxc (2.1.1-1) unstable; urgency=medium
+
+  * update to lxc-2.1.1
+
+ -- Proxmox Support Team <support@proxmox.com>  Mon, 20 Nov 2017 11:18:38 +0100
+
 lxc (2.1.0-2) unstable; urgency=medium
 
   * update cgroup namespace separation for conflicting changes in 2.1.0
index 1a1c6f4d9b1afa6ecff04aa5a169c0cb5dd2a5ac..3050937ba8a1f50b1c02ae84ba68f64aab8a5780 100644 (file)
@@ -1,7 +1,7 @@
-From 674c54165393b3ad0059f4a5c5d1e1505eea9114 Mon Sep 17 00:00:00 2001
+From 92f2489b28e79f7a67f45bc698f1d61785a6537d Mon Sep 17 00:00:00 2001
 From: Wolfgang Bumiller <w.bumiller@proxmox.com>
 Date: Fri, 10 Feb 2017 09:13:40 +0100
-Subject: [PATCH 01/10] lxc.service: start after a potential syslog.service
+Subject: [PATCH 1/8] lxc.service: start after a potential syslog.service
 
 Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
 ---
diff --git a/debian/patches/0002-jessie-systemd-remove-Delegate-flag-to-silence-warni.patch b/debian/patches/0002-jessie-systemd-remove-Delegate-flag-to-silence-warni.patch
deleted file mode 100644 (file)
index 6d987c0..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-From a5ee14df834c008294b790d96982a1fea36c807a Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Fri, 10 Feb 2017 09:14:55 +0100
-Subject: [PATCH 02/10] jessie/systemd: remove Delegate flag to silence
- warnings
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- config/init/systemd/lxc.service.in  | 1 -
- config/init/systemd/lxc@.service.in | 1 -
- 2 files changed, 2 deletions(-)
-
-diff --git a/config/init/systemd/lxc.service.in b/config/init/systemd/lxc.service.in
-index 77541917..bdd58283 100644
---- a/config/init/systemd/lxc.service.in
-+++ b/config/init/systemd/lxc.service.in
-@@ -12,7 +12,6 @@ ExecStart=@LIBEXECDIR@/lxc/lxc-containers start
- ExecStop=@LIBEXECDIR@/lxc/lxc-containers stop
- # Environment=BOOTUP=serial
- # Environment=CONSOLETYPE=serial
--Delegate=yes
- StandardOutput=syslog
- StandardError=syslog
-diff --git a/config/init/systemd/lxc@.service.in b/config/init/systemd/lxc@.service.in
-index a2aa2211..98d5a3a7 100644
---- a/config/init/systemd/lxc@.service.in
-+++ b/config/init/systemd/lxc@.service.in
-@@ -13,7 +13,6 @@ ExecStart=@BINDIR@/lxc-start -F -n %i
- ExecStop=@BINDIR@/lxc-stop -n %i
- # Environment=BOOTUP=serial
- # Environment=CONSOLETYPE=serial
--Delegate=yes
- StandardOutput=syslog
- StandardError=syslog
--- 
-2.11.0
-
diff --git a/debian/patches/0002-pve-run-lxcnetaddbr-when-instantiating-veths.patch b/debian/patches/0002-pve-run-lxcnetaddbr-when-instantiating-veths.patch
new file mode 100644 (file)
index 0000000..a767784
--- /dev/null
@@ -0,0 +1,31 @@
+From 6aecf604cf28c5164f3d957b0ad33bf03527fa26 Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Fri, 10 Feb 2017 09:15:37 +0100
+Subject: [PATCH 2/8] pve: run lxcnetaddbr when instantiating veths
+
+FIXME: Why aren't we using regular up-scripts?
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ src/lxc/network.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/lxc/network.c b/src/lxc/network.c
+index 909b7e58..c9b510f6 100644
+--- a/src/lxc/network.c
++++ b/src/lxc/network.c
+@@ -208,6 +208,11 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
+                                "veth", veth1, (char*) NULL);
+               if (err)
+                       goto out_delete;
++      } else if (netdev->link[0] == '\0') {
++              err = run_script(handler->name, "net", "/usr/share/lxc/lxcnetaddbr", "up",
++                               "veth", veth1, (char*) NULL);
++              if (err)
++                      goto out_delete;
+       }
+       DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1, veth2,
+-- 
+2.11.0
+
diff --git a/debian/patches/0003-deny-rw-mounting-of-sys-and-proc.patch b/debian/patches/0003-deny-rw-mounting-of-sys-and-proc.patch
new file mode 100644 (file)
index 0000000..ffb903e
--- /dev/null
@@ -0,0 +1,66 @@
+From 8c695baaff8d18a87233ffc119e8fd0495819dbe Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
+Date: Wed, 9 Nov 2016 09:14:26 +0100
+Subject: [PATCH 3/8] deny rw mounting of /sys and /proc
+
+this would allow root in a privileged container to change
+the permissions of /sys on the host, which could lock out
+non-root users.
+
+if a rw /sys is desired, set "lxc.mount.auto" accordingly
+---
+ config/apparmor/abstractions/container-base    | 6 +++++-
+ config/apparmor/abstractions/container-base.in | 6 +++++-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
+index a5e6c35f..4c3a4ba8 100644
+--- a/config/apparmor/abstractions/container-base
++++ b/config/apparmor/abstractions/container-base
+@@ -82,7 +82,6 @@
+   deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
+   mount fstype=proc -> /proc/,
+   mount fstype=sysfs -> /sys/,
+-  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
+   deny /sys/firmware/efi/efivars/** rwklx,
+   deny /sys/kernel/security/** rwklx,
+   mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
+@@ -91,6 +90,11 @@
+   # deny reads from debugfs
+   deny /sys/kernel/debug/{,**} rwklx,
++  # prevent rw mounting of /sys, because that allows changing its global permissions
++  deny mount -> /proc/,
++  deny mount -> /sys/,
++#  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
++
+   # allow paths to be made slave, shared, private or unbindable
+   # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.
+ #  mount options=(rw,make-slave) -> **,
+diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
+index 16529bbf..54f9ddf0 100644
+--- a/config/apparmor/abstractions/container-base.in
++++ b/config/apparmor/abstractions/container-base.in
+@@ -82,7 +82,6 @@
+   deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
+   mount fstype=proc -> /proc/,
+   mount fstype=sysfs -> /sys/,
+-  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
+   deny /sys/firmware/efi/efivars/** rwklx,
+   deny /sys/kernel/security/** rwklx,
+   mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
+@@ -91,6 +90,11 @@
+   # deny reads from debugfs
+   deny /sys/kernel/debug/{,**} rwklx,
++  # prevent rw mounting of /sys, because that allows changing its global permissions
++  deny mount -> /proc/,
++  deny mount -> /sys/,
++#  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
++
+   # allow paths to be made slave, shared, private or unbindable
+   # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.
+ #  mount options=(rw,make-slave) -> **,
+-- 
+2.11.0
+
diff --git a/debian/patches/0003-pve-run-lxcnetaddbr-when-instantiating-veths.patch b/debian/patches/0003-pve-run-lxcnetaddbr-when-instantiating-veths.patch
deleted file mode 100644 (file)
index 7f683cd..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 84da55875d3a9468957fe0f0012ea2b39b9f7785 Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Fri, 10 Feb 2017 09:15:37 +0100
-Subject: [PATCH 03/10] pve: run lxcnetaddbr when instantiating veths
-
-FIXME: Why aren't we using regular up-scripts?
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- src/lxc/network.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
-diff --git a/src/lxc/network.c b/src/lxc/network.c
-index a7f054e7..3c0597c7 100644
---- a/src/lxc/network.c
-+++ b/src/lxc/network.c
-@@ -208,6 +208,11 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
-                                "veth", veth1, (char*) NULL);
-               if (err)
-                       goto out_delete;
-+      } else if (netdev->link[0] == '\0') {
-+              err = run_script(handler->name, "net", "/usr/share/lxc/lxcnetaddbr", "up",
-+                               "veth", veth1, (char*) NULL);
-+              if (err)
-+                      goto out_delete;
-       }
-       DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1, veth2,
--- 
-2.11.0
-
diff --git a/debian/patches/0004-deny-rw-mounting-of-sys-and-proc.patch b/debian/patches/0004-deny-rw-mounting-of-sys-and-proc.patch
deleted file mode 100644 (file)
index 2657a9e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From 2d651f876f4afa97ddd6081d996776c10355732a Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= <f.gruenbichler@proxmox.com>
-Date: Wed, 9 Nov 2016 09:14:26 +0100
-Subject: [PATCH 04/10] deny rw mounting of /sys and /proc
-
-this would allow root in a privileged container to change
-the permissions of /sys on the host, which could lock out
-non-root users.
-
-if a rw /sys is desired, set "lxc.mount.auto" accordingly
----
- config/apparmor/abstractions/container-base    | 6 +++++-
- config/apparmor/abstractions/container-base.in | 6 +++++-
- 2 files changed, 10 insertions(+), 2 deletions(-)
-
-diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
-index 06290de2..779aadd4 100644
---- a/config/apparmor/abstractions/container-base
-+++ b/config/apparmor/abstractions/container-base
-@@ -84,7 +84,6 @@
-   deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
-   mount fstype=proc -> /proc/,
-   mount fstype=sysfs -> /sys/,
--  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
-   deny /sys/firmware/efi/efivars/** rwklx,
-   deny /sys/kernel/security/** rwklx,
-   mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
-@@ -93,6 +92,11 @@
-   # deny reads from debugfs
-   deny /sys/kernel/debug/{,**} rwklx,
-+  # prevent rw mounting of /sys, because that allows changing its global permissions
-+  deny mount -> /proc/,
-+  deny mount -> /sys/,
-+#  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
-+
-   # allow paths to be made slave, shared, private or unbindable
-   # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.
- #  mount options=(rw,make-slave) -> **,
-diff --git a/config/apparmor/abstractions/container-base.in b/config/apparmor/abstractions/container-base.in
-index 5bc9b28b..5c8e441f 100644
---- a/config/apparmor/abstractions/container-base.in
-+++ b/config/apparmor/abstractions/container-base.in
-@@ -84,7 +84,6 @@
-   deny mount fstype=debugfs -> /var/lib/ureadahead/debugfs/,
-   mount fstype=proc -> /proc/,
-   mount fstype=sysfs -> /sys/,
--  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
-   deny /sys/firmware/efi/efivars/** rwklx,
-   deny /sys/kernel/security/** rwklx,
-   mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
-@@ -93,6 +92,11 @@
-   # deny reads from debugfs
-   deny /sys/kernel/debug/{,**} rwklx,
-+  # prevent rw mounting of /sys, because that allows changing its global permissions
-+  deny mount -> /proc/,
-+  deny mount -> /sys/,
-+#  mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
-+
-   # allow paths to be made slave, shared, private or unbindable
-   # FIXME: This currently doesn't work due to the apparmor parser treating those as allowing all mounts.
- #  mount options=(rw,make-slave) -> **,
--- 
-2.11.0
-
diff --git a/debian/patches/0004-separate-the-limiting-from-the-namespaced-cgroup-roo.patch b/debian/patches/0004-separate-the-limiting-from-the-namespaced-cgroup-roo.patch
new file mode 100644 (file)
index 0000000..fd6f4be
--- /dev/null
@@ -0,0 +1,709 @@
+From 6ebdc24c00b4dee75aebef3136469a5297e1d9ee Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Tue, 15 Nov 2016 09:20:24 +0100
+Subject: [PATCH 4/8] separate the limiting from the namespaced cgroup root
+
+When cgroup namespaces are enabled a privileged container
+with mixed cgroups has full write access to its own root
+cgroup effectively allowing it to overwrite values written
+from the outside or configured via lxc.cgroup.*.
+
+This patch causes an additional 'ns/' directory to be
+created in all cgroups if cgroup namespaces and cgfsng are
+being used in order to combat this.
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ src/lxc/cgroups/cgfs.c      | 19 ++++++++---
+ src/lxc/cgroups/cgfsng.c    | 79 +++++++++++++++++++++++++++++++++++++--------
+ src/lxc/cgroups/cgmanager.c | 19 ++++++++---
+ src/lxc/cgroups/cgroup.c    | 17 +++++-----
+ src/lxc/cgroups/cgroup.h    | 22 ++++++++-----
+ src/lxc/commands.c          | 76 ++++++++++++++++++++++++++++++++++---------
+ src/lxc/commands.h          |  2 ++
+ src/lxc/criu.c              |  4 +--
+ src/lxc/start.c             | 27 ++++++++++++----
+ 9 files changed, 204 insertions(+), 61 deletions(-)
+
+diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
+index bcbd6613..573ccb25 100644
+--- a/src/lxc/cgroups/cgfs.c
++++ b/src/lxc/cgroups/cgfs.c
+@@ -2387,12 +2387,15 @@ static void cgfs_destroy(void *hdata, struct lxc_conf *conf)
+       free(d);
+ }
+-static inline bool cgfs_create(void *hdata)
++static inline bool cgfs_create(void *hdata, bool inner)
+ {
+       struct cgfs_data *d = hdata;
+       struct cgroup_process_info *i;
+       struct cgroup_meta_data *md;
++      if (inner)
++              return true;
++
+       if (!d)
+               return false;
+       md = d->meta;
+@@ -2403,12 +2406,15 @@ static inline bool cgfs_create(void *hdata)
+       return true;
+ }
+-static inline bool cgfs_enter(void *hdata, pid_t pid)
++static inline bool cgfs_enter(void *hdata, pid_t pid, bool inner)
+ {
+       struct cgfs_data *d = hdata;
+       struct cgroup_process_info *i;
+       int ret;
++      if (inner)
++              return true;
++
+       if (!d)
+               return false;
+       i = d->info;
+@@ -2432,10 +2438,12 @@ static inline bool cgfs_create_legacy(void *hdata, pid_t pid)
+       return true;
+ }
+-static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
++static const char *cgfs_get_cgroup(void *hdata, const char *subsystem, bool inner)
+ {
+       struct cgfs_data *d = hdata;
++      (void)inner;
++
+       if (!d)
+               return NULL;
+       return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
+@@ -2651,13 +2659,16 @@ static bool do_cgfs_chown(char *cgroup_path, struct lxc_conf *conf)
+       return true;
+ }
+-static bool cgfs_chown(void *hdata, struct lxc_conf *conf)
++static bool cgfs_chown(void *hdata, struct lxc_conf *conf, bool inner)
+ {
+       struct cgfs_data *d = hdata;
+       struct cgroup_process_info *info_ptr;
+       char *cgpath;
+       bool r = true;
++      if (inner)
++              return true;
++
+       if (!d)
+               return false;
+diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
+index 897336f0..81c589e0 100644
+--- a/src/lxc/cgroups/cgfsng.c
++++ b/src/lxc/cgroups/cgfsng.c
+@@ -77,6 +77,7 @@ struct hierarchy {
+       char *mountpoint;
+       char *base_cgroup;
+       char *fullcgpath;
++      char *innercgpath;
+       bool is_cgroup_v2;
+ };
+@@ -813,6 +814,7 @@ static void add_controller(char **clist, char *mountpoint, char *base_cgroup)
+       new->mountpoint = mountpoint;
+       new->base_cgroup = base_cgroup;
+       new->fullcgpath = NULL;
++      new->innercgpath = NULL;
+       /* record if this is the cgroup v2 hierarchy */
+       if (!strcmp(base_cgroup, "cgroup2"))
+@@ -1302,6 +1304,8 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
+                               free(h->fullcgpath);
+                               h->fullcgpath = NULL;
+                       }
++                      free(h->innercgpath);
++                      h->innercgpath = NULL;
+               }
+       }
+@@ -1319,18 +1323,25 @@ struct cgroup_ops *cgfsng_ops_init(void)
+       return &cgfsng_ops;
+ }
+-static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname)
++static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, bool inner)
+ {
+-      h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
+-      if (dir_exists(h->fullcgpath)) { /* it must not already exist */
+-              ERROR("Path \"%s\" already existed.", h->fullcgpath);
++      char *path;
++      if (inner) {
++              path = must_make_path(h->fullcgpath, CGROUP_NAMESPACE_SUBDIR, NULL);
++              h->innercgpath = path;
++      } else {
++              path = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
++              h->fullcgpath = path;
++      }
++      if (dir_exists(path)) { // it must not already exist
++              ERROR("Path \"%s\" already existed.", path);
+               return false;
+       }
+-      if (!handle_cpuset_hierarchy(h, cgname)) {
++      if (!inner && !handle_cpuset_hierarchy(h, cgname)) {
+               ERROR("Failed to handle cgroupfs v1 cpuset controller.");
+               return false;
+       }
+-      return mkdir_p(h->fullcgpath, 0755) == 0;
++      return mkdir_p(path, 0755) == 0;
+ }
+ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
+@@ -1341,11 +1352,27 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
+       h->fullcgpath = NULL;
+ }
++static inline bool cgfsng_create_inner(struct cgfsng_handler_data *d)
++{
++      size_t i;
++      bool ret = true;
++      char *cgname = must_make_path(d->container_cgroup, CGROUP_NAMESPACE_SUBDIR, NULL);
++      for (i = 0; hierarchies[i]; i++) {
++              if (!create_path_for_hierarchy(hierarchies[i], cgname, true)) {
++                      SYSERROR("Failed to create %s namespace subdirectory: %s", hierarchies[i]->fullcgpath, strerror(errno));
++                      ret = false;
++                      break;
++              }
++      }
++      free(cgname);
++      return ret;
++}
++
+ /*
+  * Try to create the same cgroup in all hierarchies.
+  * Start with cgroup_pattern; next cgroup_pattern-1, -2, ..., -999
+  */
+-static inline bool cgfsng_create(void *hdata)
++static inline bool cgfsng_create(void *hdata, bool inner)
+ {
+       int i;
+       size_t len;
+@@ -1357,9 +1384,15 @@ static inline bool cgfsng_create(void *hdata)
+               return false;
+       if (d->container_cgroup) {
++              if (inner)
++                      return cgfsng_create_inner(d);
+               WARN("cgfsng_create called a second time");
+               return false;
+       }
++      if (inner) {
++              ERROR("cgfsng_create called twice for innner cgroup");
++              return false;
++      }
+       if (d->cgroup_meta.dir)
+               tmp = lxc_string_join("/", (const char *[]){d->cgroup_meta.dir, d->name, NULL}, false);
+@@ -1395,7 +1428,7 @@ again:
+               }
+       }
+       for (i = 0; hierarchies[i]; i++) {
+-              if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
++              if (!create_path_for_hierarchy(hierarchies[i], cgname, false)) {
+                       int j;
+                       ERROR("Failed to create \"%s\"", hierarchies[i]->fullcgpath);
+                       free(hierarchies[i]->fullcgpath);
+@@ -1415,7 +1448,7 @@ out_free:
+       return false;
+ }
+-static bool cgfsng_enter(void *hdata, pid_t pid)
++static bool cgfsng_enter(void *hdata, pid_t pid, bool inner)
+ {
+       char pidstr[25];
+       int i, len;
+@@ -1425,7 +1458,13 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
+               return false;
+       for (i = 0; hierarchies[i]; i++) {
+-              char *fullpath = must_make_path(hierarchies[i]->fullcgpath,
++              char *fullpath;
++              if (inner)
++                      fullpath = must_make_path(hierarchies[i]->fullcgpath,
++                                              CGROUP_NAMESPACE_SUBDIR,
++                                              "cgroup.procs", NULL);
++              else
++                      fullpath = must_make_path(hierarchies[i]->fullcgpath,
+                                               "cgroup.procs", NULL);
+               if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
+                       SYSERROR("Failed to enter %s", fullpath);
+@@ -1441,6 +1480,7 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
+ struct chown_data {
+       struct cgfsng_handler_data *d;
+       uid_t origuid; /* target uid in parent namespace */
++      bool inner;
+ };
+ /*
+@@ -1469,13 +1509,20 @@ static int chown_cgroup_wrapper(void *data)
+       for (i = 0; hierarchies[i]; i++) {
+               char *fullpath, *path = hierarchies[i]->fullcgpath;
++              if (arg->inner)
++                      path = must_make_path(path, CGROUP_NAMESPACE_SUBDIR, NULL);
++
+               if (chown(path, destuid, 0) < 0) {
+                       SYSERROR("Error chowning %s to %d", path, (int) destuid);
++                      if (arg->inner)
++                              free(path);
+                       return -1;
+               }
+               if (chmod(path, 0775) < 0) {
+                       SYSERROR("Error chmoding %s", path);
++                      if (arg->inner)
++                              free(path);
+                       return -1;
+               }
+@@ -1501,12 +1548,14 @@ static int chown_cgroup_wrapper(void *data)
+               if (chmod(fullpath, 0664) < 0)
+                       WARN("Error chmoding %s: %s", path, strerror(errno));
+               free(fullpath);
++              if (arg->inner)
++                      free(path);
+       }
+       return 0;
+ }
+-static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
++static bool cgfsns_chown(void *hdata, struct lxc_conf *conf, bool inner)
+ {
+       struct cgfsng_handler_data *d = hdata;
+       struct chown_data wrap;
+@@ -1519,6 +1568,7 @@ static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
+       wrap.d = d;
+       wrap.origuid = geteuid();
++      wrap.inner = inner;
+       if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap,
+                         "chown_cgroup_wrapper") < 0) {
+@@ -1815,12 +1865,15 @@ static bool cgfsng_unfreeze(void *hdata)
+       return true;
+ }
+-static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem)
++static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem, bool inner)
+ {
+       struct hierarchy *h = get_hierarchy(subsystem);
+       if (!h)
+               return NULL;
++      if (inner && h->innercgpath)
++              return h->innercgpath + strlen(h->mountpoint);
++
+       return h->fullcgpath ? h->fullcgpath + strlen(h->mountpoint) : NULL;
+ }
+@@ -1848,7 +1901,7 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
+               char *path, *fullpath;
+               struct hierarchy *h = hierarchies[i];
+-              path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
++              path = lxc_cmd_get_attach_cgroup_path(name, lxcpath, h->controllers[0]);
+               if (!path) /* not running */
+                       continue;
+diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
+index 054eb171..04ae3a16 100644
+--- a/src/lxc/cgroups/cgmanager.c
++++ b/src/lxc/cgroups/cgmanager.c
+@@ -610,7 +610,7 @@ static inline void cleanup_cgroups(char *path)
+               cgm_remove_cgroup(slist[i], path);
+ }
+-static inline bool cgm_create(void *hdata)
++static inline bool cgm_create(void *hdata, bool inner)
+ {
+       struct cgm_data *d = hdata;
+       char **slist = subsystems;
+@@ -618,6 +618,9 @@ static inline bool cgm_create(void *hdata)
+       int32_t existed;
+       char result[MAXPATHLEN], *tmp, *cgroup_path;
++      if (inner)
++              return true;
++
+       if (!d)
+               return false;
+@@ -710,13 +713,16 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
+       return true;
+ }
+-static inline bool cgm_enter(void *hdata, pid_t pid)
++static inline bool cgm_enter(void *hdata, pid_t pid, bool inner)
+ {
+       struct cgm_data *d = hdata;
+       char **slist = subsystems;
+       bool ret = false;
+       int i;
++      if (inner)
++              return true;
++
+       if (!d || !d->cgroup_path)
+               return false;
+@@ -738,10 +744,12 @@ out:
+       return ret;
+ }
+-static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
++static const char *cgm_get_cgroup(void *hdata, const char *subsystem, bool inner)
+ {
+       struct cgm_data *d = hdata;
++      (void)inner;
++
+       if (!d || !d->cgroup_path)
+               return NULL;
+       return d->cgroup_path;
+@@ -1542,10 +1550,13 @@ out:
+       return ret;
+ }
+-static bool cgm_chown(void *hdata, struct lxc_conf *conf)
++static bool cgm_chown(void *hdata, struct lxc_conf *conf, bool inner)
+ {
+       struct cgm_data *d = hdata;
++      if (inner)
++              return true;
++
+       if (!d || !d->cgroup_path)
+               return false;
+       if (!cgm_dbus_connect()) {
+diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
+index 674e3090..6f0d2fe8 100644
+--- a/src/lxc/cgroups/cgroup.c
++++ b/src/lxc/cgroups/cgroup.c
+@@ -80,19 +80,19 @@ void cgroup_destroy(struct lxc_handler *handler)
+ }
+ /* Create the container cgroups for all requested controllers. */
+-bool cgroup_create(struct lxc_handler *handler)
++bool cgroup_create(struct lxc_handler *handler, bool inner)
+ {
+       if (ops)
+-              return ops->create(handler->cgroup_data);
++              return ops->create(handler->cgroup_data, inner);
+       return false;
+ }
+ /* Enter the container init into its new cgroups for all requested controllers. */
+-bool cgroup_enter(struct lxc_handler *handler)
++bool cgroup_enter(struct lxc_handler *handler, bool inner)
+ {
+       if (ops)
+-              return ops->enter(handler->cgroup_data, handler->pid);
++              return ops->enter(handler->cgroup_data, handler->pid, inner);
+       return false;
+ }
+@@ -106,10 +106,11 @@ bool cgroup_create_legacy(struct lxc_handler *handler)
+ }
+ const char *cgroup_get_cgroup(struct lxc_handler *handler,
+-                            const char *subsystem)
++                            const char *subsystem,
++                            bool inner)
+ {
+       if (ops)
+-              return ops->get_cgroup(handler->cgroup_data, subsystem);
++              return ops->get_cgroup(handler->cgroup_data, subsystem, inner);
+       return NULL;
+ }
+@@ -155,10 +156,10 @@ bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
+       return false;
+ }
+-bool cgroup_chown(struct lxc_handler *handler)
++bool cgroup_chown(struct lxc_handler *handler, bool inner)
+ {
+       if (ops && ops->chown)
+-              return ops->chown(handler->cgroup_data, handler->conf);
++              return ops->chown(handler->cgroup_data, handler->conf, inner);
+       return true;
+ }
+diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
+index f17a6abe..f05fda4e 100644
+--- a/src/lxc/cgroups/cgroup.h
++++ b/src/lxc/cgroups/cgroup.h
+@@ -28,6 +28,12 @@
+ #include <stddef.h>
+ #include <sys/types.h>
++/* When lxc.cgroup.protect_limits is in effect the container's cgroup namespace
++ * will be moved into an additional subdirectory "cgns/" inside the cgroup in
++ * order to prevent it from accessing the outer limiting cgroup.
++ */
++#define CGROUP_NAMESPACE_SUBDIR "cgns"
++
+ struct lxc_handler;
+ struct lxc_conf;
+ struct lxc_list;
+@@ -43,10 +49,10 @@ struct cgroup_ops {
+       void *(*init)(struct lxc_handler *handler);
+       void (*destroy)(void *hdata, struct lxc_conf *conf);
+-      bool (*create)(void *hdata);
+-      bool (*enter)(void *hdata, pid_t pid);
++      bool (*create)(void *hdata, bool inner);
++      bool (*enter)(void *hdata, pid_t pid, bool inner);
+       bool (*create_legacy)(void *hdata, pid_t pid);
+-      const char *(*get_cgroup)(void *hdata, const char *subsystem);
++      const char *(*get_cgroup)(void *hdata, const char *subsystem, bool inner);
+       bool (*escape)();
+       int (*num_hierarchies)();
+       bool (*get_hierarchies)(int n, char ***out);
+@@ -54,7 +60,7 @@ struct cgroup_ops {
+       int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
+       bool (*unfreeze)(void *hdata);
+       bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
+-      bool (*chown)(void *hdata, struct lxc_conf *conf);
++      bool (*chown)(void *hdata, struct lxc_conf *conf, bool inner);
+       bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
+       bool (*mount_cgroup)(void *hdata, const char *root, int type);
+       int (*nrtasks)(void *hdata);
+@@ -66,14 +72,14 @@ extern bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
+ extern bool cgroup_mount(const char *root, struct lxc_handler *handler, int type);
+ extern void cgroup_destroy(struct lxc_handler *handler);
+ extern bool cgroup_init(struct lxc_handler *handler);
+-extern bool cgroup_create(struct lxc_handler *handler);
++extern bool cgroup_create(struct lxc_handler *handler, bool inner);
+ extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
+-extern bool cgroup_chown(struct lxc_handler *handler);
+-extern bool cgroup_enter(struct lxc_handler *handler);
++extern bool cgroup_chown(struct lxc_handler *handler, bool inner);
++extern bool cgroup_enter(struct lxc_handler *handler, bool inner);
+ extern void cgroup_cleanup(struct lxc_handler *handler);
+ extern bool cgroup_create_legacy(struct lxc_handler *handler);
+ extern int cgroup_nrtasks(struct lxc_handler *handler);
+-extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
++extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem, bool inner);
+ extern bool cgroup_escape();
+ extern int cgroup_num_hierarchies();
+ extern bool cgroup_get_hierarchies(int i, char ***out);
+diff --git a/src/lxc/commands.c b/src/lxc/commands.c
+index 68fbd387..ccdbeeba 100644
+--- a/src/lxc/commands.c
++++ b/src/lxc/commands.c
+@@ -410,30 +410,29 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
+       return lxc_cmd_rsp_send(fd, &rsp);
+ }
+-/*
+- * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
+- * particular subsystem. This is the cgroup path relative to the root
+- * of the cgroup filesystem.
+- *
+- * @name      : name of container to connect to
+- * @lxcpath   : the lxcpath in which the container is running
+- * @subsystem : the subsystem being asked about
+- *
+- * Returns the path on success, NULL on failure. The caller must free() the
+- * returned path.
+- */
+-char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
+-      const char *subsystem)
++static char *do_lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
++      const char *subsystem,
++      bool inner)
+ {
+       int ret, stopped;
++      size_t subsyslen = strlen(subsystem);
++
+       struct lxc_cmd_rr cmd = {
+               .req = {
+                       .cmd = LXC_CMD_GET_CGROUP,
+-                      .datalen = strlen(subsystem)+1,
++                      .datalen = subsyslen+1,
+                       .data = subsystem,
+               },
+       };
++      if (inner) {
++              char *data = alloca(subsyslen+2);
++              memcpy(data, subsystem, subsyslen+1);
++              data[subsyslen+1] = 1;
++              cmd.req.datalen = subsyslen+2,
++              cmd.req.data = data;
++      }
++
+       ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
+       if (ret < 0) {
+               TRACE("command %s failed for container \"%s\": %s.",
+@@ -458,16 +457,61 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
+       return cmd.rsp.data;
+ }
++/*
++ * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
++ * particular subsystem. This is the cgroup path relative to the root
++ * of the cgroup filesystem.
++ *
++ * @name      : name of container to connect to
++ * @lxcpath   : the lxcpath in which the container is running
++ * @subsystem : the subsystem being asked about
++ *
++ * Returns the path on success, NULL on failure. The caller must free() the
++ * returned path.
++ */
++char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
++      const char *subsystem)
++{
++      return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, false);
++}
++
++/*
++ * lxc_cmd_get_attach_cgroup_path: Calculate a container's inner cgroup path
++ * for a particular subsystem. This is the cgroup path relative to the root
++ * of the cgroup filesystem.
++ *
++ * @name      : name of container to connect to
++ * @lxcpath   : the lxcpath in which the container is running
++ * @subsystem : the subsystem being asked about
++ *
++ * Returns the path on success, NULL on failure. The caller must free() the
++ * returned path.
++ */
++char *lxc_cmd_get_attach_cgroup_path(const char *name, const char *lxcpath,
++      const char *subsystem)
++{
++      return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, true);
++}
++
++
+ static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
+                                      struct lxc_handler *handler)
+ {
+       struct lxc_cmd_rsp rsp;
+       const char *path;
++      const char *subsystem;
++      size_t subsyslen;
++      bool inner = false;
+       if (req->datalen < 1)
+               return -1;
+-      path = cgroup_get_cgroup(handler, req->data);
++      subsystem = req->data;
++      subsyslen = strlen(subsystem);
++      if (req->datalen == subsyslen+2)
++              inner = (subsystem[subsyslen+1] == 1);
++
++      path = cgroup_get_cgroup(handler, req->data, inner);
+       if (!path)
+               return -1;
+       rsp.datalen = strlen(path) + 1,
+diff --git a/src/lxc/commands.h b/src/lxc/commands.h
+index 28428c77..9557dcaa 100644
+--- a/src/lxc/commands.h
++++ b/src/lxc/commands.h
+@@ -82,6 +82,8 @@ extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
+  */
+ extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
+                       const char *subsystem);
++extern char *lxc_cmd_get_attach_cgroup_path(const char *name,
++                      const char *lxcpath, const char *subsystem);
+ extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
+ extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
+ extern char *lxc_cmd_get_name(const char *hashed_sock);
+diff --git a/src/lxc/criu.c b/src/lxc/criu.c
+index 96688edc..539ae8bd 100644
+--- a/src/lxc/criu.c
++++ b/src/lxc/criu.c
+@@ -324,7 +324,7 @@ static void exec_criu(struct criu_opts *opts)
+               } else {
+                       const char *p;
+-                      p = cgroup_get_cgroup(opts->handler, controllers[0]);
++                      p = cgroup_get_cgroup(opts->handler, controllers[0], false);
+                       if (!p) {
+                               ERROR("failed to get cgroup path for %s", controllers[0]);
+                               goto err;
+@@ -857,7 +857,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
+               goto out_fini_handler;
+       }
+-      if (!cgroup_create(handler)) {
++      if (!cgroup_create(handler, false)) {
+               ERROR("failed creating groups");
+               goto out_fini_handler;
+       }
+diff --git a/src/lxc/start.c b/src/lxc/start.c
+index a6a40c72..920f3c23 100644
+--- a/src/lxc/start.c
++++ b/src/lxc/start.c
+@@ -1217,7 +1217,7 @@ static int lxc_spawn(struct lxc_handler *handler)
+       cgroups_connected = true;
+-      if (!cgroup_create(handler)) {
++      if (!cgroup_create(handler, false)) {
+               ERROR("Failed creating cgroups.");
+               goto out_delete_net;
+       }
+@@ -1292,10 +1292,10 @@ static int lxc_spawn(struct lxc_handler *handler)
+               goto out_delete_net;
+       }
+-      if (!cgroup_enter(handler))
++      if (!cgroup_enter(handler, false))
+               goto out_delete_net;
+-      if (!cgroup_chown(handler))
++      if (!cgroup_chown(handler, false))
+               goto out_delete_net;
+       handler->netnsfd = lxc_preserve_ns(handler->pid, "net");
+@@ -1338,15 +1338,30 @@ static int lxc_spawn(struct lxc_handler *handler)
+               goto out_delete_net;
+       }
+-      if (lxc_sync_barrier_child(handler, LXC_SYNC_CGROUP_UNSHARE))
+-              goto out_delete_net;
+-
+       if (!cgroup_setup_limits(handler, true)) {
+               ERROR("Failed to setup the devices cgroup for container \"%s\".", name);
+               goto out_delete_net;
+       }
+       TRACE("Set up cgroup device limits");
++      if (cgns_supported()) {
++              if (!cgroup_create(handler, true)) {
++                      ERROR("failed to create inner cgroup separation layer");
++                      goto out_delete_net;
++              }
++              if (!cgroup_enter(handler, true)) {
++                      ERROR("failed to enter inner cgroup separation layer");
++                      goto out_delete_net;
++              }
++              if (!cgroup_chown(handler, true)) {
++                      ERROR("failed chown inner cgroup separation layer");
++                      goto out_delete_net;
++              }
++      }
++
++      if (lxc_sync_barrier_child(handler, LXC_SYNC_CGROUP_UNSHARE))
++              goto out_delete_net;
++
+       cgroup_disconnect();
+       cgroups_connected = false;
+-- 
+2.11.0
+
diff --git a/debian/patches/0005-separate-the-limiting-from-the-namespaced-cgroup-roo.patch b/debian/patches/0005-separate-the-limiting-from-the-namespaced-cgroup-roo.patch
deleted file mode 100644 (file)
index 6120cef..0000000
+++ /dev/null
@@ -1,697 +0,0 @@
-From 9152a996a7413e1dc7dc3cb6c64af20cdf0389be Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Tue, 15 Nov 2016 09:20:24 +0100
-Subject: [PATCH 05/10] separate the limiting from the namespaced cgroup root
-
-When cgroup namespaces are enabled a privileged container
-with mixed cgroups has full write access to its own root
-cgroup effectively allowing it to overwrite values written
-from the outside or configured via lxc.cgroup.*.
-
-This patch causes an additional 'ns/' directory to be
-created in all cgroups if cgroup namespaces and cgfsng are
-being used in order to combat this.
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- src/lxc/cgroups/cgfs.c      | 19 ++++++++---
- src/lxc/cgroups/cgfsng.c    | 79 +++++++++++++++++++++++++++++++++++++--------
- src/lxc/cgroups/cgmanager.c | 19 ++++++++---
- src/lxc/cgroups/cgroup.c    | 17 +++++-----
- src/lxc/cgroups/cgroup.h    | 22 ++++++++-----
- src/lxc/commands.c          | 76 ++++++++++++++++++++++++++++++++++---------
- src/lxc/commands.h          |  2 ++
- src/lxc/criu.c              |  4 +--
- src/lxc/start.c             | 21 ++++++++++--
- 9 files changed, 201 insertions(+), 58 deletions(-)
-
-diff --git a/src/lxc/cgroups/cgfs.c b/src/lxc/cgroups/cgfs.c
-index bcbd6613..573ccb25 100644
---- a/src/lxc/cgroups/cgfs.c
-+++ b/src/lxc/cgroups/cgfs.c
-@@ -2387,12 +2387,15 @@ static void cgfs_destroy(void *hdata, struct lxc_conf *conf)
-       free(d);
- }
--static inline bool cgfs_create(void *hdata)
-+static inline bool cgfs_create(void *hdata, bool inner)
- {
-       struct cgfs_data *d = hdata;
-       struct cgroup_process_info *i;
-       struct cgroup_meta_data *md;
-+      if (inner)
-+              return true;
-+
-       if (!d)
-               return false;
-       md = d->meta;
-@@ -2403,12 +2406,15 @@ static inline bool cgfs_create(void *hdata)
-       return true;
- }
--static inline bool cgfs_enter(void *hdata, pid_t pid)
-+static inline bool cgfs_enter(void *hdata, pid_t pid, bool inner)
- {
-       struct cgfs_data *d = hdata;
-       struct cgroup_process_info *i;
-       int ret;
-+      if (inner)
-+              return true;
-+
-       if (!d)
-               return false;
-       i = d->info;
-@@ -2432,10 +2438,12 @@ static inline bool cgfs_create_legacy(void *hdata, pid_t pid)
-       return true;
- }
--static const char *cgfs_get_cgroup(void *hdata, const char *subsystem)
-+static const char *cgfs_get_cgroup(void *hdata, const char *subsystem, bool inner)
- {
-       struct cgfs_data *d = hdata;
-+      (void)inner;
-+
-       if (!d)
-               return NULL;
-       return lxc_cgroup_get_hierarchy_path_data(subsystem, d);
-@@ -2651,13 +2659,16 @@ static bool do_cgfs_chown(char *cgroup_path, struct lxc_conf *conf)
-       return true;
- }
--static bool cgfs_chown(void *hdata, struct lxc_conf *conf)
-+static bool cgfs_chown(void *hdata, struct lxc_conf *conf, bool inner)
- {
-       struct cgfs_data *d = hdata;
-       struct cgroup_process_info *info_ptr;
-       char *cgpath;
-       bool r = true;
-+      if (inner)
-+              return true;
-+
-       if (!d)
-               return false;
-diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
-index fe3fd706..896e6da9 100644
---- a/src/lxc/cgroups/cgfsng.c
-+++ b/src/lxc/cgroups/cgfsng.c
-@@ -77,6 +77,7 @@ struct hierarchy {
-       char *mountpoint;
-       char *base_cgroup;
-       char *fullcgpath;
-+      char *innercgpath;
-       bool is_cgroup_v2;
- };
-@@ -813,6 +814,7 @@ static void add_controller(char **clist, char *mountpoint, char *base_cgroup)
-       new->mountpoint = mountpoint;
-       new->base_cgroup = base_cgroup;
-       new->fullcgpath = NULL;
-+      new->innercgpath = NULL;
-       /* record if this is the cgroup v2 hierarchy */
-       if (!strcmp(base_cgroup, "cgroup2"))
-@@ -1300,6 +1302,8 @@ static void cgfsng_destroy(void *hdata, struct lxc_conf *conf)
-                               free(h->fullcgpath);
-                               h->fullcgpath = NULL;
-                       }
-+                      free(h->innercgpath);
-+                      h->innercgpath = NULL;
-               }
-       }
-@@ -1317,18 +1321,25 @@ struct cgroup_ops *cgfsng_ops_init(void)
-       return &cgfsng_ops;
- }
--static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname)
-+static bool create_path_for_hierarchy(struct hierarchy *h, char *cgname, bool inner)
- {
--      h->fullcgpath = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
--      if (dir_exists(h->fullcgpath)) { /* it must not already exist */
--              ERROR("Path \"%s\" already existed.", h->fullcgpath);
-+      char *path;
-+      if (inner) {
-+              path = must_make_path(h->fullcgpath, CGROUP_NAMESPACE_SUBDIR, NULL);
-+              h->innercgpath = path;
-+      } else {
-+              path = must_make_path(h->mountpoint, h->base_cgroup, cgname, NULL);
-+              h->fullcgpath = path;
-+      }
-+      if (dir_exists(path)) { // it must not already exist
-+              ERROR("Path \"%s\" already existed.", path);
-               return false;
-       }
--      if (!handle_cpuset_hierarchy(h, cgname)) {
-+      if (!inner && !handle_cpuset_hierarchy(h, cgname)) {
-               ERROR("Failed to handle cgroupfs v1 cpuset controller.");
-               return false;
-       }
--      return mkdir_p(h->fullcgpath, 0755) == 0;
-+      return mkdir_p(path, 0755) == 0;
- }
- static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
-@@ -1339,11 +1350,27 @@ static void remove_path_for_hierarchy(struct hierarchy *h, char *cgname)
-       h->fullcgpath = NULL;
- }
-+static inline bool cgfsng_create_inner(struct cgfsng_handler_data *d)
-+{
-+      size_t i;
-+      bool ret = true;
-+      char *cgname = must_make_path(d->container_cgroup, CGROUP_NAMESPACE_SUBDIR, NULL);
-+      for (i = 0; hierarchies[i]; i++) {
-+              if (!create_path_for_hierarchy(hierarchies[i], cgname, true)) {
-+                      SYSERROR("Failed to create %s namespace subdirectory: %s", hierarchies[i]->fullcgpath, strerror(errno));
-+                      ret = false;
-+                      break;
-+              }
-+      }
-+      free(cgname);
-+      return ret;
-+}
-+
- /*
-  * Try to create the same cgroup in all hierarchies.
-  * Start with cgroup_pattern; next cgroup_pattern-1, -2, ..., -999
-  */
--static inline bool cgfsng_create(void *hdata)
-+static inline bool cgfsng_create(void *hdata, bool inner)
- {
-       int i;
-       size_t len;
-@@ -1355,9 +1382,15 @@ static inline bool cgfsng_create(void *hdata)
-               return false;
-       if (d->container_cgroup) {
-+              if (inner)
-+                      return cgfsng_create_inner(d);
-               WARN("cgfsng_create called a second time");
-               return false;
-       }
-+      if (inner) {
-+              ERROR("cgfsng_create called twice for innner cgroup");
-+              return false;
-+      }
-       if (d->cgroup_meta.dir)
-               tmp = lxc_string_join("/", (const char *[]){d->cgroup_meta.dir, d->name, NULL}, false);
-@@ -1393,7 +1426,7 @@ again:
-               }
-       }
-       for (i = 0; hierarchies[i]; i++) {
--              if (!create_path_for_hierarchy(hierarchies[i], cgname)) {
-+              if (!create_path_for_hierarchy(hierarchies[i], cgname, false)) {
-                       int j;
-                       ERROR("Failed to create \"%s\"", hierarchies[i]->fullcgpath);
-                       free(hierarchies[i]->fullcgpath);
-@@ -1413,7 +1446,7 @@ out_free:
-       return false;
- }
--static bool cgfsng_enter(void *hdata, pid_t pid)
-+static bool cgfsng_enter(void *hdata, pid_t pid, bool inner)
- {
-       char pidstr[25];
-       int i, len;
-@@ -1423,7 +1456,13 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
-               return false;
-       for (i = 0; hierarchies[i]; i++) {
--              char *fullpath = must_make_path(hierarchies[i]->fullcgpath,
-+              char *fullpath;
-+              if (inner)
-+                      fullpath = must_make_path(hierarchies[i]->fullcgpath,
-+                                              CGROUP_NAMESPACE_SUBDIR,
-+                                              "cgroup.procs", NULL);
-+              else
-+                      fullpath = must_make_path(hierarchies[i]->fullcgpath,
-                                               "cgroup.procs", NULL);
-               if (lxc_write_to_file(fullpath, pidstr, len, false) != 0) {
-                       SYSERROR("Failed to enter %s", fullpath);
-@@ -1439,6 +1478,7 @@ static bool cgfsng_enter(void *hdata, pid_t pid)
- struct chown_data {
-       struct cgfsng_handler_data *d;
-       uid_t origuid; /* target uid in parent namespace */
-+      bool inner;
- };
- /*
-@@ -1467,13 +1507,20 @@ static int chown_cgroup_wrapper(void *data)
-       for (i = 0; hierarchies[i]; i++) {
-               char *fullpath, *path = hierarchies[i]->fullcgpath;
-+              if (arg->inner)
-+                      path = must_make_path(path, CGROUP_NAMESPACE_SUBDIR, NULL);
-+
-               if (chown(path, destuid, 0) < 0) {
-                       SYSERROR("Error chowning %s to %d", path, (int) destuid);
-+                      if (arg->inner)
-+                              free(path);
-                       return -1;
-               }
-               if (chmod(path, 0775) < 0) {
-                       SYSERROR("Error chmoding %s", path);
-+                      if (arg->inner)
-+                              free(path);
-                       return -1;
-               }
-@@ -1499,12 +1546,14 @@ static int chown_cgroup_wrapper(void *data)
-               if (chmod(fullpath, 0664) < 0)
-                       WARN("Error chmoding %s: %s", path, strerror(errno));
-               free(fullpath);
-+              if (arg->inner)
-+                      free(path);
-       }
-       return 0;
- }
--static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
-+static bool cgfsns_chown(void *hdata, struct lxc_conf *conf, bool inner)
- {
-       struct cgfsng_handler_data *d = hdata;
-       struct chown_data wrap;
-@@ -1517,6 +1566,7 @@ static bool cgfsns_chown(void *hdata, struct lxc_conf *conf)
-       wrap.d = d;
-       wrap.origuid = geteuid();
-+      wrap.inner = inner;
-       if (userns_exec_1(conf, chown_cgroup_wrapper, &wrap,
-                         "chown_cgroup_wrapper") < 0) {
-@@ -1813,12 +1863,15 @@ static bool cgfsng_unfreeze(void *hdata)
-       return true;
- }
--static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem)
-+static const char *cgfsng_get_cgroup(void *hdata, const char *subsystem, bool inner)
- {
-       struct hierarchy *h = get_hierarchy(subsystem);
-       if (!h)
-               return NULL;
-+      if (inner && h->innercgpath)
-+              return h->innercgpath + strlen(h->mountpoint);
-+
-       return h->fullcgpath ? h->fullcgpath + strlen(h->mountpoint) : NULL;
- }
-@@ -1846,7 +1899,7 @@ static bool cgfsng_attach(const char *name, const char *lxcpath, pid_t pid)
-               char *path, *fullpath;
-               struct hierarchy *h = hierarchies[i];
--              path = lxc_cmd_get_cgroup_path(name, lxcpath, h->controllers[0]);
-+              path = lxc_cmd_get_attach_cgroup_path(name, lxcpath, h->controllers[0]);
-               if (!path) /* not running */
-                       continue;
-diff --git a/src/lxc/cgroups/cgmanager.c b/src/lxc/cgroups/cgmanager.c
-index 054eb171..04ae3a16 100644
---- a/src/lxc/cgroups/cgmanager.c
-+++ b/src/lxc/cgroups/cgmanager.c
-@@ -610,7 +610,7 @@ static inline void cleanup_cgroups(char *path)
-               cgm_remove_cgroup(slist[i], path);
- }
--static inline bool cgm_create(void *hdata)
-+static inline bool cgm_create(void *hdata, bool inner)
- {
-       struct cgm_data *d = hdata;
-       char **slist = subsystems;
-@@ -618,6 +618,9 @@ static inline bool cgm_create(void *hdata)
-       int32_t existed;
-       char result[MAXPATHLEN], *tmp, *cgroup_path;
-+      if (inner)
-+              return true;
-+
-       if (!d)
-               return false;
-@@ -710,13 +713,16 @@ static bool lxc_cgmanager_enter(pid_t pid, const char *controller,
-       return true;
- }
--static inline bool cgm_enter(void *hdata, pid_t pid)
-+static inline bool cgm_enter(void *hdata, pid_t pid, bool inner)
- {
-       struct cgm_data *d = hdata;
-       char **slist = subsystems;
-       bool ret = false;
-       int i;
-+      if (inner)
-+              return true;
-+
-       if (!d || !d->cgroup_path)
-               return false;
-@@ -738,10 +744,12 @@ out:
-       return ret;
- }
--static const char *cgm_get_cgroup(void *hdata, const char *subsystem)
-+static const char *cgm_get_cgroup(void *hdata, const char *subsystem, bool inner)
- {
-       struct cgm_data *d = hdata;
-+      (void)inner;
-+
-       if (!d || !d->cgroup_path)
-               return NULL;
-       return d->cgroup_path;
-@@ -1542,10 +1550,13 @@ out:
-       return ret;
- }
--static bool cgm_chown(void *hdata, struct lxc_conf *conf)
-+static bool cgm_chown(void *hdata, struct lxc_conf *conf, bool inner)
- {
-       struct cgm_data *d = hdata;
-+      if (inner)
-+              return true;
-+
-       if (!d || !d->cgroup_path)
-               return false;
-       if (!cgm_dbus_connect()) {
-diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
-index 674e3090..6f0d2fe8 100644
---- a/src/lxc/cgroups/cgroup.c
-+++ b/src/lxc/cgroups/cgroup.c
-@@ -80,19 +80,19 @@ void cgroup_destroy(struct lxc_handler *handler)
- }
- /* Create the container cgroups for all requested controllers. */
--bool cgroup_create(struct lxc_handler *handler)
-+bool cgroup_create(struct lxc_handler *handler, bool inner)
- {
-       if (ops)
--              return ops->create(handler->cgroup_data);
-+              return ops->create(handler->cgroup_data, inner);
-       return false;
- }
- /* Enter the container init into its new cgroups for all requested controllers. */
--bool cgroup_enter(struct lxc_handler *handler)
-+bool cgroup_enter(struct lxc_handler *handler, bool inner)
- {
-       if (ops)
--              return ops->enter(handler->cgroup_data, handler->pid);
-+              return ops->enter(handler->cgroup_data, handler->pid, inner);
-       return false;
- }
-@@ -106,10 +106,11 @@ bool cgroup_create_legacy(struct lxc_handler *handler)
- }
- const char *cgroup_get_cgroup(struct lxc_handler *handler,
--                            const char *subsystem)
-+                            const char *subsystem,
-+                            bool inner)
- {
-       if (ops)
--              return ops->get_cgroup(handler->cgroup_data, subsystem);
-+              return ops->get_cgroup(handler->cgroup_data, subsystem, inner);
-       return NULL;
- }
-@@ -155,10 +156,10 @@ bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices)
-       return false;
- }
--bool cgroup_chown(struct lxc_handler *handler)
-+bool cgroup_chown(struct lxc_handler *handler, bool inner)
- {
-       if (ops && ops->chown)
--              return ops->chown(handler->cgroup_data, handler->conf);
-+              return ops->chown(handler->cgroup_data, handler->conf, inner);
-       return true;
- }
-diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
-index f17a6abe..f05fda4e 100644
---- a/src/lxc/cgroups/cgroup.h
-+++ b/src/lxc/cgroups/cgroup.h
-@@ -28,6 +28,12 @@
- #include <stddef.h>
- #include <sys/types.h>
-+/* When lxc.cgroup.protect_limits is in effect the container's cgroup namespace
-+ * will be moved into an additional subdirectory "cgns/" inside the cgroup in
-+ * order to prevent it from accessing the outer limiting cgroup.
-+ */
-+#define CGROUP_NAMESPACE_SUBDIR "cgns"
-+
- struct lxc_handler;
- struct lxc_conf;
- struct lxc_list;
-@@ -43,10 +49,10 @@ struct cgroup_ops {
-       void *(*init)(struct lxc_handler *handler);
-       void (*destroy)(void *hdata, struct lxc_conf *conf);
--      bool (*create)(void *hdata);
--      bool (*enter)(void *hdata, pid_t pid);
-+      bool (*create)(void *hdata, bool inner);
-+      bool (*enter)(void *hdata, pid_t pid, bool inner);
-       bool (*create_legacy)(void *hdata, pid_t pid);
--      const char *(*get_cgroup)(void *hdata, const char *subsystem);
-+      const char *(*get_cgroup)(void *hdata, const char *subsystem, bool inner);
-       bool (*escape)();
-       int (*num_hierarchies)();
-       bool (*get_hierarchies)(int n, char ***out);
-@@ -54,7 +60,7 @@ struct cgroup_ops {
-       int (*get)(const char *filename, char *value, size_t len, const char *name, const char *lxcpath);
-       bool (*unfreeze)(void *hdata);
-       bool (*setup_limits)(void *hdata, struct lxc_list *cgroup_conf, bool with_devices);
--      bool (*chown)(void *hdata, struct lxc_conf *conf);
-+      bool (*chown)(void *hdata, struct lxc_conf *conf, bool inner);
-       bool (*attach)(const char *name, const char *lxcpath, pid_t pid);
-       bool (*mount_cgroup)(void *hdata, const char *root, int type);
-       int (*nrtasks)(void *hdata);
-@@ -66,14 +72,14 @@ extern bool cgroup_attach(const char *name, const char *lxcpath, pid_t pid);
- extern bool cgroup_mount(const char *root, struct lxc_handler *handler, int type);
- extern void cgroup_destroy(struct lxc_handler *handler);
- extern bool cgroup_init(struct lxc_handler *handler);
--extern bool cgroup_create(struct lxc_handler *handler);
-+extern bool cgroup_create(struct lxc_handler *handler, bool inner);
- extern bool cgroup_setup_limits(struct lxc_handler *handler, bool with_devices);
--extern bool cgroup_chown(struct lxc_handler *handler);
--extern bool cgroup_enter(struct lxc_handler *handler);
-+extern bool cgroup_chown(struct lxc_handler *handler, bool inner);
-+extern bool cgroup_enter(struct lxc_handler *handler, bool inner);
- extern void cgroup_cleanup(struct lxc_handler *handler);
- extern bool cgroup_create_legacy(struct lxc_handler *handler);
- extern int cgroup_nrtasks(struct lxc_handler *handler);
--extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem);
-+extern const char *cgroup_get_cgroup(struct lxc_handler *handler, const char *subsystem, bool inner);
- extern bool cgroup_escape();
- extern int cgroup_num_hierarchies();
- extern bool cgroup_get_hierarchies(int i, char ***out);
-diff --git a/src/lxc/commands.c b/src/lxc/commands.c
-index 68fbd387..ccdbeeba 100644
---- a/src/lxc/commands.c
-+++ b/src/lxc/commands.c
-@@ -410,30 +410,29 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
-       return lxc_cmd_rsp_send(fd, &rsp);
- }
--/*
-- * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
-- * particular subsystem. This is the cgroup path relative to the root
-- * of the cgroup filesystem.
-- *
-- * @name      : name of container to connect to
-- * @lxcpath   : the lxcpath in which the container is running
-- * @subsystem : the subsystem being asked about
-- *
-- * Returns the path on success, NULL on failure. The caller must free() the
-- * returned path.
-- */
--char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
--      const char *subsystem)
-+static char *do_lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
-+      const char *subsystem,
-+      bool inner)
- {
-       int ret, stopped;
-+      size_t subsyslen = strlen(subsystem);
-+
-       struct lxc_cmd_rr cmd = {
-               .req = {
-                       .cmd = LXC_CMD_GET_CGROUP,
--                      .datalen = strlen(subsystem)+1,
-+                      .datalen = subsyslen+1,
-                       .data = subsystem,
-               },
-       };
-+      if (inner) {
-+              char *data = alloca(subsyslen+2);
-+              memcpy(data, subsystem, subsyslen+1);
-+              data[subsyslen+1] = 1;
-+              cmd.req.datalen = subsyslen+2,
-+              cmd.req.data = data;
-+      }
-+
-       ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
-       if (ret < 0) {
-               TRACE("command %s failed for container \"%s\": %s.",
-@@ -458,16 +457,61 @@ char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
-       return cmd.rsp.data;
- }
-+/*
-+ * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
-+ * particular subsystem. This is the cgroup path relative to the root
-+ * of the cgroup filesystem.
-+ *
-+ * @name      : name of container to connect to
-+ * @lxcpath   : the lxcpath in which the container is running
-+ * @subsystem : the subsystem being asked about
-+ *
-+ * Returns the path on success, NULL on failure. The caller must free() the
-+ * returned path.
-+ */
-+char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
-+      const char *subsystem)
-+{
-+      return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, false);
-+}
-+
-+/*
-+ * lxc_cmd_get_attach_cgroup_path: Calculate a container's inner cgroup path
-+ * for a particular subsystem. This is the cgroup path relative to the root
-+ * of the cgroup filesystem.
-+ *
-+ * @name      : name of container to connect to
-+ * @lxcpath   : the lxcpath in which the container is running
-+ * @subsystem : the subsystem being asked about
-+ *
-+ * Returns the path on success, NULL on failure. The caller must free() the
-+ * returned path.
-+ */
-+char *lxc_cmd_get_attach_cgroup_path(const char *name, const char *lxcpath,
-+      const char *subsystem)
-+{
-+      return do_lxc_cmd_get_cgroup_path(name, lxcpath, subsystem, true);
-+}
-+
-+
- static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
-                                      struct lxc_handler *handler)
- {
-       struct lxc_cmd_rsp rsp;
-       const char *path;
-+      const char *subsystem;
-+      size_t subsyslen;
-+      bool inner = false;
-       if (req->datalen < 1)
-               return -1;
--      path = cgroup_get_cgroup(handler, req->data);
-+      subsystem = req->data;
-+      subsyslen = strlen(subsystem);
-+      if (req->datalen == subsyslen+2)
-+              inner = (subsystem[subsyslen+1] == 1);
-+
-+      path = cgroup_get_cgroup(handler, req->data, inner);
-       if (!path)
-               return -1;
-       rsp.datalen = strlen(path) + 1,
-diff --git a/src/lxc/commands.h b/src/lxc/commands.h
-index 28428c77..9557dcaa 100644
---- a/src/lxc/commands.h
-+++ b/src/lxc/commands.h
-@@ -82,6 +82,8 @@ extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
-  */
- extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
-                       const char *subsystem);
-+extern char *lxc_cmd_get_attach_cgroup_path(const char *name,
-+                      const char *lxcpath, const char *subsystem);
- extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
- extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
- extern char *lxc_cmd_get_name(const char *hashed_sock);
-diff --git a/src/lxc/criu.c b/src/lxc/criu.c
-index 676d759d..1dd41473 100644
---- a/src/lxc/criu.c
-+++ b/src/lxc/criu.c
-@@ -324,7 +324,7 @@ static void exec_criu(struct criu_opts *opts)
-               } else {
-                       const char *p;
--                      p = cgroup_get_cgroup(opts->handler, controllers[0]);
-+                      p = cgroup_get_cgroup(opts->handler, controllers[0], false);
-                       if (!p) {
-                               ERROR("failed to get cgroup path for %s", controllers[0]);
-                               goto err;
-@@ -857,7 +857,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
-               goto out_fini_handler;
-       }
--      if (!cgroup_create(handler)) {
-+      if (!cgroup_create(handler, false)) {
-               ERROR("failed creating groups");
-               goto out_fini_handler;
-       }
-diff --git a/src/lxc/start.c b/src/lxc/start.c
-index 1370d681..b653a157 100644
---- a/src/lxc/start.c
-+++ b/src/lxc/start.c
-@@ -1196,7 +1196,7 @@ static int lxc_spawn(struct lxc_handler *handler)
-       cgroups_connected = true;
--      if (!cgroup_create(handler)) {
-+      if (!cgroup_create(handler, false)) {
-               ERROR("Failed creating cgroups.");
-               goto out_delete_net;
-       }
-@@ -1275,10 +1275,10 @@ static int lxc_spawn(struct lxc_handler *handler)
-               goto out_delete_net;
-       }
--      if (!cgroup_enter(handler))
-+      if (!cgroup_enter(handler, false))
-               goto out_delete_net;
--      if (!cgroup_chown(handler))
-+      if (!cgroup_chown(handler, false))
-               goto out_delete_net;
-       if (failed_before_rename)
-@@ -1333,6 +1333,21 @@ static int lxc_spawn(struct lxc_handler *handler)
-       }
-       TRACE("Set up cgroup device limits");
-+      if (cgns_supported()) {
-+              if (!cgroup_create(handler, true)) {
-+                      ERROR("failed to create inner cgroup separation layer");
-+                      goto out_delete_net;
-+              }
-+              if (!cgroup_enter(handler, true)) {
-+                      ERROR("failed to enter inner cgroup separation layer");
-+                      goto out_delete_net;
-+              }
-+              if (!cgroup_chown(handler, true)) {
-+                      ERROR("failed chown inner cgroup separation layer");
-+                      goto out_delete_net;
-+              }
-+      }
-+
-       cgroup_disconnect();
-       cgroups_connected = false;
--- 
-2.11.0
-
diff --git a/debian/patches/0005-start-initutils-make-cgroupns-separation-level-confi.patch b/debian/patches/0005-start-initutils-make-cgroupns-separation-level-confi.patch
new file mode 100644 (file)
index 0000000..01166e3
--- /dev/null
@@ -0,0 +1,97 @@
+From ef58cfcf70fbe666acee0c407f77a22eeb1eec4f Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Wed, 16 Nov 2016 09:53:42 +0100
+Subject: [PATCH 5/8] start/initutils: make cgroupns separation level
+ configurable
+
+Adds a new global config variable `lxc.cgroup.separate`
+which controls whether a separation directory for cgroup
+namespaces should be used.
+Can be empty, "privileged", "unprivileged" or "both".
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ src/lxc/initutils.c | 17 +++++++++--------
+ src/lxc/initutils.h |  1 +
+ src/lxc/start.c     | 25 ++++++++++++++-----------
+ 3 files changed, 24 insertions(+), 19 deletions(-)
+
+diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c
+index c190d6d5..97650e67 100644
+--- a/src/lxc/initutils.c
++++ b/src/lxc/initutils.c
+@@ -88,14 +88,15 @@ static char *copy_global_config_value(char *p)
+ 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.bdev.rbd.rbdpool",   DEFAULT_RBDPOOL },
+-              { "lxc.lxcpath",            NULL            },
+-              { "lxc.default_config",     NULL            },
+-              { "lxc.cgroup.pattern",     NULL            },
+-              { "lxc.cgroup.use",         NULL            },
++              { "lxc.bdev.lvm.vg",           DEFAULT_VG      },
++              { "lxc.bdev.lvm.thin_pool",    DEFAULT_THIN_POOL },
++              { "lxc.bdev.zfs.root",         DEFAULT_ZFSROOT },
++              { "lxc.bdev.rbd.rbdpool",      DEFAULT_RBDPOOL },
++              { "lxc.lxcpath",               NULL            },
++              { "lxc.default_config",        NULL            },
++              { "lxc.cgroup.pattern",        NULL            },
++              { "lxc.cgroup.use",            NULL            },
++              { "lxc.cgroup.protect_limits", DEFAULT_CGPROTECT },
+               { NULL, NULL },
+       };
+diff --git a/src/lxc/initutils.h b/src/lxc/initutils.h
+index c021fd61..443ad026 100644
+--- a/src/lxc/initutils.h
++++ b/src/lxc/initutils.h
+@@ -43,6 +43,7 @@
+ #define DEFAULT_THIN_POOL "lxc"
+ #define DEFAULT_ZFSROOT "lxc"
+ #define DEFAULT_RBDPOOL "lxc"
++#define DEFAULT_CGPROTECT "privileged"
+ extern void lxc_setup_fs(void);
+ extern const char *lxc_global_config_value(const char *option_name);
+diff --git a/src/lxc/start.c b/src/lxc/start.c
+index 920f3c23..89e9be96 100644
+--- a/src/lxc/start.c
++++ b/src/lxc/start.c
+@@ -1345,17 +1345,20 @@ static int lxc_spawn(struct lxc_handler *handler)
+       TRACE("Set up cgroup device limits");
+       if (cgns_supported()) {
+-              if (!cgroup_create(handler, true)) {
+-                      ERROR("failed to create inner cgroup separation layer");
+-                      goto out_delete_net;
+-              }
+-              if (!cgroup_enter(handler, true)) {
+-                      ERROR("failed to enter inner cgroup separation layer");
+-                      goto out_delete_net;
+-              }
+-              if (!cgroup_chown(handler, true)) {
+-                      ERROR("failed chown inner cgroup separation layer");
+-                      goto out_delete_net;
++              const char *tmp = lxc_global_config_value("lxc.cgroup.protect_limits");
++              if (!strcmp(tmp, "both") || !strcmp(tmp, wants_to_map_ids ? "unprivileged" : "privileged")) {
++                      if (!cgroup_create(handler, true)) {
++                              ERROR("failed to create inner cgroup separation layer");
++                              goto out_delete_net;
++                      }
++                      if (!cgroup_enter(handler, true)) {
++                              ERROR("failed to enter inner cgroup separation layer");
++                              goto out_delete_net;
++                      }
++                      if (!cgroup_chown(handler, true)) {
++                              ERROR("failed chown inner cgroup separation layer");
++                              goto out_delete_net;
++                      }
+               }
+       }
+-- 
+2.11.0
+
diff --git a/debian/patches/0006-rename-cgroup-namespace-directory-to-ns.patch b/debian/patches/0006-rename-cgroup-namespace-directory-to-ns.patch
new file mode 100644 (file)
index 0000000..3f5a5c8
--- /dev/null
@@ -0,0 +1,26 @@
+From 1341290e8af87aab15e844abb1a1451cb21ec275 Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Fri, 23 Dec 2016 15:57:24 +0100
+Subject: [PATCH 6/8] rename cgroup namespace directory to ns
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ src/lxc/cgroups/cgroup.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
+index f05fda4e..34c9d89c 100644
+--- a/src/lxc/cgroups/cgroup.h
++++ b/src/lxc/cgroups/cgroup.h
+@@ -32,7 +32,7 @@
+  * will be moved into an additional subdirectory "cgns/" inside the cgroup in
+  * order to prevent it from accessing the outer limiting cgroup.
+  */
+-#define CGROUP_NAMESPACE_SUBDIR "cgns"
++#define CGROUP_NAMESPACE_SUBDIR "ns"
+ struct lxc_handler;
+ struct lxc_conf;
+-- 
+2.11.0
+
diff --git a/debian/patches/0006-start-initutils-make-cgroupns-separation-level-confi.patch b/debian/patches/0006-start-initutils-make-cgroupns-separation-level-confi.patch
deleted file mode 100644 (file)
index 64aefaf..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-From 3ec7cf35c1ca98f976a2c39cd58287d8137d0269 Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Wed, 16 Nov 2016 09:53:42 +0100
-Subject: [PATCH 06/10] start/initutils: make cgroupns separation level
- configurable
-
-Adds a new global config variable `lxc.cgroup.separate`
-which controls whether a separation directory for cgroup
-namespaces should be used.
-Can be empty, "privileged", "unprivileged" or "both".
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- src/lxc/initutils.c | 17 +++++++++--------
- src/lxc/initutils.h |  1 +
- src/lxc/start.c     | 25 ++++++++++++++-----------
- 3 files changed, 24 insertions(+), 19 deletions(-)
-
-diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c
-index c190d6d5..97650e67 100644
---- a/src/lxc/initutils.c
-+++ b/src/lxc/initutils.c
-@@ -88,14 +88,15 @@ static char *copy_global_config_value(char *p)
- 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.bdev.rbd.rbdpool",   DEFAULT_RBDPOOL },
--              { "lxc.lxcpath",            NULL            },
--              { "lxc.default_config",     NULL            },
--              { "lxc.cgroup.pattern",     NULL            },
--              { "lxc.cgroup.use",         NULL            },
-+              { "lxc.bdev.lvm.vg",           DEFAULT_VG      },
-+              { "lxc.bdev.lvm.thin_pool",    DEFAULT_THIN_POOL },
-+              { "lxc.bdev.zfs.root",         DEFAULT_ZFSROOT },
-+              { "lxc.bdev.rbd.rbdpool",      DEFAULT_RBDPOOL },
-+              { "lxc.lxcpath",               NULL            },
-+              { "lxc.default_config",        NULL            },
-+              { "lxc.cgroup.pattern",        NULL            },
-+              { "lxc.cgroup.use",            NULL            },
-+              { "lxc.cgroup.protect_limits", DEFAULT_CGPROTECT },
-               { NULL, NULL },
-       };
-diff --git a/src/lxc/initutils.h b/src/lxc/initutils.h
-index c021fd61..443ad026 100644
---- a/src/lxc/initutils.h
-+++ b/src/lxc/initutils.h
-@@ -43,6 +43,7 @@
- #define DEFAULT_THIN_POOL "lxc"
- #define DEFAULT_ZFSROOT "lxc"
- #define DEFAULT_RBDPOOL "lxc"
-+#define DEFAULT_CGPROTECT "privileged"
- extern void lxc_setup_fs(void);
- extern const char *lxc_global_config_value(const char *option_name);
-diff --git a/src/lxc/start.c b/src/lxc/start.c
-index b653a157..4fec27b9 100644
---- a/src/lxc/start.c
-+++ b/src/lxc/start.c
-@@ -1334,17 +1334,20 @@ static int lxc_spawn(struct lxc_handler *handler)
-       TRACE("Set up cgroup device limits");
-       if (cgns_supported()) {
--              if (!cgroup_create(handler, true)) {
--                      ERROR("failed to create inner cgroup separation layer");
--                      goto out_delete_net;
--              }
--              if (!cgroup_enter(handler, true)) {
--                      ERROR("failed to enter inner cgroup separation layer");
--                      goto out_delete_net;
--              }
--              if (!cgroup_chown(handler, true)) {
--                      ERROR("failed chown inner cgroup separation layer");
--                      goto out_delete_net;
-+              const char *tmp = lxc_global_config_value("lxc.cgroup.protect_limits");
-+              if (!strcmp(tmp, "both") || !strcmp(tmp, wants_to_map_ids ? "unprivileged" : "privileged")) {
-+                      if (!cgroup_create(handler, true)) {
-+                              ERROR("failed to create inner cgroup separation layer");
-+                              goto out_delete_net;
-+                      }
-+                      if (!cgroup_enter(handler, true)) {
-+                              ERROR("failed to enter inner cgroup separation layer");
-+                              goto out_delete_net;
-+                      }
-+                      if (!cgroup_chown(handler, true)) {
-+                              ERROR("failed chown inner cgroup separation layer");
-+                              goto out_delete_net;
-+                      }
-               }
-       }
--- 
-2.11.0
-
diff --git a/debian/patches/0007-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch b/debian/patches/0007-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch
new file mode 100644 (file)
index 0000000..63ef5d2
--- /dev/null
@@ -0,0 +1,194 @@
+From 6811fb42be10c4eaf026be35914c546a95520b9e Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Mon, 20 Nov 2017 10:49:41 +0100
+Subject: [PATCH 7/8] possibility to run lxc-monitord as a regular daemon
+
+lxc-monitord instances are spawned on demand and, if this
+happens from a service, the daemon is considered part of
+it by systemd, as it is running in the same cgroups. This
+can be avoided by leaving it running permanently.
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ config/init/systemd/Makefile.am             | 10 +++--
+ config/init/systemd/lxc-monitord.service.in | 12 ++++++
+ configure.ac                                |  1 +
+ lxc.spec.in                                 |  1 +
+ src/lxc/lxc_monitord.c                      | 60 +++++++++++++++++++++--------
+ 5 files changed, 63 insertions(+), 21 deletions(-)
+ create mode 100644 config/init/systemd/lxc-monitord.service.in
+
+diff --git a/config/init/systemd/Makefile.am b/config/init/systemd/Makefile.am
+index c448850d..4a4fde5e 100644
+--- a/config/init/systemd/Makefile.am
++++ b/config/init/systemd/Makefile.am
+@@ -2,19 +2,21 @@ EXTRA_DIST = \
+       lxc-apparmor-load \
+       lxc.service.in \
+       lxc@.service.in \
+-      lxc-net.service.in
++      lxc-net.service.in \
++      lxc-monitord.service.in
+ if INIT_SCRIPT_SYSTEMD
+-BUILT_SOURCES = lxc.service lxc@.service lxc-net.service
++BUILT_SOURCES = lxc.service lxc@.service lxc-net.service lxc-monitord.service
+-install-systemd: lxc.service lxc@.service lxc-net.service lxc-apparmor-load
++install-systemd: lxc.service lxc@.service lxc-net.service lxc-monitord.service lxc-apparmor-load
+       $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
+-      $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/
++      $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service lxc-monitord.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/
+ uninstall-systemd:
+       rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc.service
+       rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc@.service
+       rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-net.service
++      rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-monitord.service
+       rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || :
+ pkglibexec_SCRIPTS = lxc-apparmor-load
+diff --git a/config/init/systemd/lxc-monitord.service.in b/config/init/systemd/lxc-monitord.service.in
+new file mode 100644
+index 00000000..40635168
+--- /dev/null
++++ b/config/init/systemd/lxc-monitord.service.in
+@@ -0,0 +1,12 @@
++[Unit]
++Description=LXC Container Monitoring Daemon
++After=syslog.service network.target
++
++[Service]
++Type=simple
++ExecStart=@LIBEXECDIR@/lxc/lxc-monitord --daemon
++StandardOutput=syslog
++StandardError=syslog
++
++[Install]
++WantedBy=multi-user.target
+diff --git a/configure.ac b/configure.ac
+index 5566d298..31822e58 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -709,6 +709,7 @@ AC_CONFIG_FILES([
+       config/init/systemd/lxc.service
+       config/init/systemd/lxc@.service
+       config/init/systemd/lxc-net.service
++      config/init/systemd/lxc-monitord.service
+       config/init/sysvinit/Makefile
+       config/init/sysvinit/lxc-containers
+       config/init/sysvinit/lxc-net
+diff --git a/lxc.spec.in b/lxc.spec.in
+index e31115de..36ab7d9d 100644
+--- a/lxc.spec.in
++++ b/lxc.spec.in
+@@ -260,6 +260,7 @@ fi
+ %{_unitdir}/lxc-net.service
+ %{_unitdir}/lxc.service
+ %{_unitdir}/lxc@.service
++%{_unitdir}/lxc-monitord.service
+ %else
+ %{_sysconfdir}/rc.d/init.d/lxc
+ %{_sysconfdir}/rc.d/init.d/lxc-net
+diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
+index c4c2ba0d..c3534e3d 100644
+--- a/src/lxc/lxc_monitord.c
++++ b/src/lxc/lxc_monitord.c
+@@ -345,17 +345,44 @@ static void lxc_monitord_sig_handler(int sig)
+ int main(int argc, char *argv[])
+ {
+-      int ret, pipefd;
++      int ret, pipefd = -1;
+       char logpath[PATH_MAX];
+       sigset_t mask;
+-      char *lxcpath = argv[1];
++      const char *lxcpath = NULL;
+       bool mainloop_opened = false;
+       bool monitord_created = false;
++      bool persistent = false;
+       struct lxc_log log;
+-      if (argc != 3) {
++      if (argc > 1 && !strcmp(argv[1], "--daemon")) {
++              persistent = true;
++              --argc;
++              ++argv;
++      }
++
++      if (argc > 1) {
++              lxcpath = argv[1];
++              --argc;
++              ++argv;
++      } else {
++              lxcpath = lxc_global_config_value("lxc.lxcpath");
++              if (!lxcpath) {
++                      ERROR("Out of memory getting lxcpath");
++                      exit(EXIT_FAILURE);
++              }
++      }
++
++      if (argc > 1) {
++              if (lxc_safe_int(argv[1], &pipefd) < 0)
++                      exit(EXIT_FAILURE);
++              --argc;
++              ++argv;
++      }
++
++      if (argc != 1 || (persistent != (pipefd == -1))) {
+               fprintf(stderr,
+-                      "Usage: lxc-monitord lxcpath sync-pipe-fd\n\n"
++                      "Usage: lxc-monitord lxcpath sync-pipe-fd\n"
++                      "       lxc-monitord --daemon lxcpath\n\n"
+                       "NOTE: lxc-monitord is intended for use by lxc internally\n"
+                       "      and does not need to be run by hand\n\n");
+               exit(EXIT_FAILURE);
+@@ -377,9 +404,6 @@ int main(int argc, char *argv[])
+               INFO("Failed to open log file %s, log will be lost.", lxcpath);
+       lxc_log_options_no_override();
+-      if (lxc_safe_int(argv[2], &pipefd) < 0)
+-              exit(EXIT_FAILURE);
+-
+       if (sigfillset(&mask) ||
+           sigdelset(&mask, SIGILL)  ||
+           sigdelset(&mask, SIGSEGV) ||
+@@ -411,15 +435,17 @@ int main(int argc, char *argv[])
+               goto on_error;
+       monitord_created = true;
+-      /* sync with parent, we're ignoring the return from write
+-       * because regardless if it works or not, the following
+-       * close will sync us with the parent process. the
+-       * if-empty-statement construct is to quiet the
+-       * warn-unused-result warning.
+-       */
+-      if (write(pipefd, "S", 1))
+-              ;
+-      close(pipefd);
++      if (pipefd != -1) {
++              /* sync with parent, we're ignoring the return from write
++               * because regardless if it works or not, the following
++               * close will sync us with the parent process. the
++               * if-empty-statement construct is to quiet the
++               * warn-unused-result warning.
++               */
++              if (write(pipefd, "S", 1))
++                      ;
++              close(pipefd);
++      }
+       if (lxc_monitord_mainloop_add(&mon)) {
+               ERROR("Failed to add mainloop handlers.");
+@@ -429,7 +455,7 @@ int main(int argc, char *argv[])
+       NOTICE("lxc-monitord with pid %d is now monitoring lxcpath %s.",
+              getpid(), mon.lxcpath);
+       for (;;) {
+-              ret = lxc_mainloop(&mon.descr, 1000 * 30);
++              ret = lxc_mainloop(&mon.descr, persistent ? -1 : 1000 * 30);
+               if (ret) {
+                       ERROR("mainloop returned an error");
+                       break;
+-- 
+2.11.0
+
diff --git a/debian/patches/0007-rename-cgroup-namespace-directory-to-ns.patch b/debian/patches/0007-rename-cgroup-namespace-directory-to-ns.patch
deleted file mode 100644 (file)
index de90acb..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-From d80258c750c52470389056c212a0eb5f0901dd7b Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Fri, 23 Dec 2016 15:57:24 +0100
-Subject: [PATCH 07/10] rename cgroup namespace directory to ns
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- src/lxc/cgroups/cgroup.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
-index f05fda4e..34c9d89c 100644
---- a/src/lxc/cgroups/cgroup.h
-+++ b/src/lxc/cgroups/cgroup.h
-@@ -32,7 +32,7 @@
-  * will be moved into an additional subdirectory "cgns/" inside the cgroup in
-  * order to prevent it from accessing the outer limiting cgroup.
-  */
--#define CGROUP_NAMESPACE_SUBDIR "cgns"
-+#define CGROUP_NAMESPACE_SUBDIR "ns"
- struct lxc_handler;
- struct lxc_conf;
--- 
-2.11.0
-
diff --git a/debian/patches/0008-Make-lxc-.service-forking.patch b/debian/patches/0008-Make-lxc-.service-forking.patch
new file mode 100644 (file)
index 0000000..7431ca1
--- /dev/null
@@ -0,0 +1,40 @@
+From 2001f560675efca7d6dcabe8fb8b376442d5d6d0 Mon Sep 17 00:00:00 2001
+From: Wolfgang Bumiller <w.bumiller@proxmox.com>
+Date: Mon, 20 Nov 2017 10:51:36 +0100
+Subject: [PATCH 8/8] Make lxc@.service forking
+
+Previously the init process' output was dumped into the log
+files since the service used Type=simple and
+StandardOutput/Error=syslog.
+
+Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+---
+ config/init/systemd/lxc@.service.in | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/config/init/systemd/lxc@.service.in b/config/init/systemd/lxc@.service.in
+index a2aa2211..f312763c 100644
+--- a/config/init/systemd/lxc@.service.in
++++ b/config/init/systemd/lxc@.service.in
+@@ -1,15 +1,15 @@
+ [Unit]
+ Description=LXC Container: %i
+ # This pulls in apparmor, dev-setup, lxc-net
+-After=lxc.service
++After=lxc.service lxc-monitord.service
+ Wants=lxc.service
+ Documentation=man:lxc-start man:lxc
+ [Service]
+-Type=simple
++Type=forking
+ KillMode=mixed
+ TimeoutStopSec=120s
+-ExecStart=@BINDIR@/lxc-start -F -n %i
++ExecStart=@BINDIR@/lxc-start -n %i
+ ExecStop=@BINDIR@/lxc-stop -n %i
+ # Environment=BOOTUP=serial
+ # Environment=CONSOLETYPE=serial
+-- 
+2.11.0
+
diff --git a/debian/patches/0008-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch b/debian/patches/0008-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch
deleted file mode 100644 (file)
index e589e88..0000000
+++ /dev/null
@@ -1,229 +0,0 @@
-From 9f5dc10171f3546530a326b8d427683109fd2818 Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Fri, 10 Feb 2017 10:23:36 +0100
-Subject: [PATCH 08/10] possibility to run lxc-monitord as a regular daemon
-
-This includes an lxc-monitord.service, required by
-lxc@.service which is now of Type=forking.
-
-Previously the init process' output was dumped into the log
-files since the service used Type=simple and
-StandardOutput/Error=syslog. Using lxc-start's daemon mode
-on the other hand used a wait call spawning an lxc-monitord
-in the background which could potentially stick around
-forever if there were clients connected to it. Since it was
-considered part of the lxc@foo.service unit by systemd this
-also meant the unit was considered active until not only the
-container but also lxc-monitord exited.
-This is now corrected by creating a separate lxc-monitord
-unit which lxc@.service depends on.
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- config/init/systemd/Makefile.am             | 10 +++--
- config/init/systemd/lxc-monitord.service.in | 12 ++++++
- config/init/systemd/lxc@.service.in         |  7 ++--
- configure.ac                                |  1 +
- lxc.spec.in                                 |  1 +
- src/lxc/lxc_monitord.c                      | 60 +++++++++++++++++++++--------
- 6 files changed, 67 insertions(+), 24 deletions(-)
- create mode 100644 config/init/systemd/lxc-monitord.service.in
-
-diff --git a/config/init/systemd/Makefile.am b/config/init/systemd/Makefile.am
-index c448850d..4a4fde5e 100644
---- a/config/init/systemd/Makefile.am
-+++ b/config/init/systemd/Makefile.am
-@@ -2,19 +2,21 @@ EXTRA_DIST = \
-       lxc-apparmor-load \
-       lxc.service.in \
-       lxc@.service.in \
--      lxc-net.service.in
-+      lxc-net.service.in \
-+      lxc-monitord.service.in
- if INIT_SCRIPT_SYSTEMD
--BUILT_SOURCES = lxc.service lxc@.service lxc-net.service
-+BUILT_SOURCES = lxc.service lxc@.service lxc-net.service lxc-monitord.service
--install-systemd: lxc.service lxc@.service lxc-net.service lxc-apparmor-load
-+install-systemd: lxc.service lxc@.service lxc-net.service lxc-monitord.service lxc-apparmor-load
-       $(MKDIR_P) $(DESTDIR)$(SYSTEMD_UNIT_DIR)
--      $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/
-+      $(INSTALL_DATA) lxc.service lxc@.service lxc-net.service lxc-monitord.service $(DESTDIR)$(SYSTEMD_UNIT_DIR)/
- uninstall-systemd:
-       rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc.service
-       rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc@.service
-       rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-net.service
-+      rm -f $(DESTDIR)$(SYSTEMD_UNIT_DIR)/lxc-monitord.service
-       rmdir $(DESTDIR)$(SYSTEMD_UNIT_DIR) || :
- pkglibexec_SCRIPTS = lxc-apparmor-load
-diff --git a/config/init/systemd/lxc-monitord.service.in b/config/init/systemd/lxc-monitord.service.in
-new file mode 100644
-index 00000000..40635168
---- /dev/null
-+++ b/config/init/systemd/lxc-monitord.service.in
-@@ -0,0 +1,12 @@
-+[Unit]
-+Description=LXC Container Monitoring Daemon
-+After=syslog.service network.target
-+
-+[Service]
-+Type=simple
-+ExecStart=@LIBEXECDIR@/lxc/lxc-monitord --daemon
-+StandardOutput=syslog
-+StandardError=syslog
-+
-+[Install]
-+WantedBy=multi-user.target
-diff --git a/config/init/systemd/lxc@.service.in b/config/init/systemd/lxc@.service.in
-index 98d5a3a7..4ee90b21 100644
---- a/config/init/systemd/lxc@.service.in
-+++ b/config/init/systemd/lxc@.service.in
-@@ -1,15 +1,16 @@
- [Unit]
- Description=LXC Container: %i
- # This pulls in apparmor, dev-setup, lxc-net
--After=lxc.service
-+After=lxc.service lxc-monitord.service
- Wants=lxc.service
-+Requires=lxc-monitord.service
- Documentation=man:lxc-start man:lxc
- [Service]
--Type=simple
-+Type=forking
- KillMode=mixed
- TimeoutStopSec=120s
--ExecStart=@BINDIR@/lxc-start -F -n %i
-+ExecStart=@BINDIR@/lxc-start -n %i
- ExecStop=@BINDIR@/lxc-stop -n %i
- # Environment=BOOTUP=serial
- # Environment=CONSOLETYPE=serial
-diff --git a/configure.ac b/configure.ac
-index 35fe7964..d34eda1e 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -709,6 +709,7 @@ AC_CONFIG_FILES([
-       config/init/systemd/lxc.service
-       config/init/systemd/lxc@.service
-       config/init/systemd/lxc-net.service
-+      config/init/systemd/lxc-monitord.service
-       config/init/sysvinit/Makefile
-       config/init/sysvinit/lxc-containers
-       config/init/sysvinit/lxc-net
-diff --git a/lxc.spec.in b/lxc.spec.in
-index e31115de..36ab7d9d 100644
---- a/lxc.spec.in
-+++ b/lxc.spec.in
-@@ -260,6 +260,7 @@ fi
- %{_unitdir}/lxc-net.service
- %{_unitdir}/lxc.service
- %{_unitdir}/lxc@.service
-+%{_unitdir}/lxc-monitord.service
- %else
- %{_sysconfdir}/rc.d/init.d/lxc
- %{_sysconfdir}/rc.d/init.d/lxc-net
-diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c
-index c4c2ba0d..c3534e3d 100644
---- a/src/lxc/lxc_monitord.c
-+++ b/src/lxc/lxc_monitord.c
-@@ -345,17 +345,44 @@ static void lxc_monitord_sig_handler(int sig)
- int main(int argc, char *argv[])
- {
--      int ret, pipefd;
-+      int ret, pipefd = -1;
-       char logpath[PATH_MAX];
-       sigset_t mask;
--      char *lxcpath = argv[1];
-+      const char *lxcpath = NULL;
-       bool mainloop_opened = false;
-       bool monitord_created = false;
-+      bool persistent = false;
-       struct lxc_log log;
--      if (argc != 3) {
-+      if (argc > 1 && !strcmp(argv[1], "--daemon")) {
-+              persistent = true;
-+              --argc;
-+              ++argv;
-+      }
-+
-+      if (argc > 1) {
-+              lxcpath = argv[1];
-+              --argc;
-+              ++argv;
-+      } else {
-+              lxcpath = lxc_global_config_value("lxc.lxcpath");
-+              if (!lxcpath) {
-+                      ERROR("Out of memory getting lxcpath");
-+                      exit(EXIT_FAILURE);
-+              }
-+      }
-+
-+      if (argc > 1) {
-+              if (lxc_safe_int(argv[1], &pipefd) < 0)
-+                      exit(EXIT_FAILURE);
-+              --argc;
-+              ++argv;
-+      }
-+
-+      if (argc != 1 || (persistent != (pipefd == -1))) {
-               fprintf(stderr,
--                      "Usage: lxc-monitord lxcpath sync-pipe-fd\n\n"
-+                      "Usage: lxc-monitord lxcpath sync-pipe-fd\n"
-+                      "       lxc-monitord --daemon lxcpath\n\n"
-                       "NOTE: lxc-monitord is intended for use by lxc internally\n"
-                       "      and does not need to be run by hand\n\n");
-               exit(EXIT_FAILURE);
-@@ -377,9 +404,6 @@ int main(int argc, char *argv[])
-               INFO("Failed to open log file %s, log will be lost.", lxcpath);
-       lxc_log_options_no_override();
--      if (lxc_safe_int(argv[2], &pipefd) < 0)
--              exit(EXIT_FAILURE);
--
-       if (sigfillset(&mask) ||
-           sigdelset(&mask, SIGILL)  ||
-           sigdelset(&mask, SIGSEGV) ||
-@@ -411,15 +435,17 @@ int main(int argc, char *argv[])
-               goto on_error;
-       monitord_created = true;
--      /* sync with parent, we're ignoring the return from write
--       * because regardless if it works or not, the following
--       * close will sync us with the parent process. the
--       * if-empty-statement construct is to quiet the
--       * warn-unused-result warning.
--       */
--      if (write(pipefd, "S", 1))
--              ;
--      close(pipefd);
-+      if (pipefd != -1) {
-+              /* sync with parent, we're ignoring the return from write
-+               * because regardless if it works or not, the following
-+               * close will sync us with the parent process. the
-+               * if-empty-statement construct is to quiet the
-+               * warn-unused-result warning.
-+               */
-+              if (write(pipefd, "S", 1))
-+                      ;
-+              close(pipefd);
-+      }
-       if (lxc_monitord_mainloop_add(&mon)) {
-               ERROR("Failed to add mainloop handlers.");
-@@ -429,7 +455,7 @@ int main(int argc, char *argv[])
-       NOTICE("lxc-monitord with pid %d is now monitoring lxcpath %s.",
-              getpid(), mon.lxcpath);
-       for (;;) {
--              ret = lxc_mainloop(&mon.descr, 1000 * 30);
-+              ret = lxc_mainloop(&mon.descr, persistent ? -1 : 1000 * 30);
-               if (ret) {
-                       ERROR("mainloop returned an error");
-                       break;
--- 
-2.11.0
-
diff --git a/debian/patches/0009-network-add-missing-checks-for-empty-links.patch b/debian/patches/0009-network-add-missing-checks-for-empty-links.patch
deleted file mode 100644 (file)
index ee3966e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-From c1c1e55305a06786ee3dd938e421ca413db73dd1 Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Wed, 6 Sep 2017 11:51:03 +0200
-Subject: [PATCH 09/10] network: add missing checks for empty links
-
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- src/lxc/network.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/lxc/network.c b/src/lxc/network.c
-index 3c0597c7..0ad42318 100644
---- a/src/lxc/network.c
-+++ b/src/lxc/network.c
-@@ -2355,7 +2355,7 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler)
-               if (netdev->type != LXC_NET_VETH)
-                       continue;
--              if (!is_ovs_bridge(netdev->link))
-+              if (netdev->link[0] == '\0' || !is_ovs_bridge(netdev->link))
-                       continue;
-               if (netdev->priv.veth_attr.pair[0] != '\0')
-@@ -2564,7 +2564,7 @@ bool lxc_delete_network_priv(struct lxc_handler *handler)
-               }
-               INFO("Removed interface \"%s\" from \"%s\"", hostveth, netdev->link);
--              if (!is_ovs_bridge(netdev->link)) {
-+              if (netdev->link[0] == '\0' || !is_ovs_bridge(netdev->link)) {
-                       netdev->priv.veth_attr.veth1[0] = '\0';
-                       continue;
-               }
--- 
-2.11.0
-
diff --git a/debian/patches/0010-start-unshare-cgroup-after-setting-up-device-limits.patch b/debian/patches/0010-start-unshare-cgroup-after-setting-up-device-limits.patch
deleted file mode 100644 (file)
index 065a38b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 7f3ecf9291a8bca0e60f6611206608d0644e73bf Mon Sep 17 00:00:00 2001
-From: Wolfgang Bumiller <w.bumiller@proxmox.com>
-Date: Tue, 19 Sep 2017 10:00:43 +0200
-Subject: [PATCH 10/10] start: unshare cgroup after setting up device limits
-
-Commit f4152036dd29 ("start: lxc_setup() after unshare(CLONE_NEWCGROUP)"
-introduced another sync step before the cgroup device
-limits, but in order for cgroup namespace separation to work
-these limits must be setup before creating the separation
-directory, which means we need to move the unshare to after
-setting up the limits.
-
-Fixup-for: separate the limiting from the namespaced cgroup root
-Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
----
- src/lxc/start.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/src/lxc/start.c b/src/lxc/start.c
-index 4fec27b9..7715f64f 100644
---- a/src/lxc/start.c
-+++ b/src/lxc/start.c
-@@ -1324,9 +1324,6 @@ static int lxc_spawn(struct lxc_handler *handler)
-               goto out_delete_net;
-       }
--      if (lxc_sync_barrier_child(handler, LXC_SYNC_CGROUP_UNSHARE))
--              goto out_delete_net;
--
-       if (!cgroup_setup_limits(handler, true)) {
-               ERROR("Failed to setup the devices cgroup for container \"%s\".", name);
-               goto out_delete_net;
-@@ -1351,6 +1348,9 @@ static int lxc_spawn(struct lxc_handler *handler)
-               }
-       }
-+      if (lxc_sync_barrier_child(handler, LXC_SYNC_CGROUP_UNSHARE))
-+              goto out_delete_net;
-+
-       cgroup_disconnect();
-       cgroups_connected = false;
--- 
-2.11.0
-
index 1e860ae07e887b4db5c61d4d83e5390ffa99e132..3ff7181ea0cc2d6456ca6338ae0e13b6d9783b2c 100644 (file)
@@ -1,10 +1,8 @@
 0001-lxc.service-start-after-a-potential-syslog.service.patch
-0002-jessie-systemd-remove-Delegate-flag-to-silence-warni.patch
-0003-pve-run-lxcnetaddbr-when-instantiating-veths.patch
-0004-deny-rw-mounting-of-sys-and-proc.patch
-0005-separate-the-limiting-from-the-namespaced-cgroup-roo.patch
-0006-start-initutils-make-cgroupns-separation-level-confi.patch
-0007-rename-cgroup-namespace-directory-to-ns.patch
-0008-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch
-0009-network-add-missing-checks-for-empty-links.patch
-0010-start-unshare-cgroup-after-setting-up-device-limits.patch
+0002-pve-run-lxcnetaddbr-when-instantiating-veths.patch
+0003-deny-rw-mounting-of-sys-and-proc.patch
+0004-separate-the-limiting-from-the-namespaced-cgroup-roo.patch
+0005-start-initutils-make-cgroupns-separation-level-confi.patch
+0006-rename-cgroup-namespace-directory-to-ns.patch
+0007-possibility-to-run-lxc-monitord-as-a-regular-daemon.patch
+0008-Make-lxc-.service-forking.patch
diff --git a/lxc b/lxc
new file mode 160000 (submodule)
index 0000000..31546ce
--- /dev/null
+++ b/lxc
@@ -0,0 +1 @@
+Subproject commit 31546ced8a4cbed1455568934b59e3ba64bfcb63
diff --git a/lxc.tgz b/lxc.tgz
deleted file mode 100644 (file)
index 2171b21..0000000
Binary files a/lxc.tgz and /dev/null differ