[pkg-lxc-devel] Bug#875733: lxc.mount.auto = cgroup:mixed doesn't seem to work in Stretch anymore

Matthijs Kooijman matthijs at stdin.nl
Sun Jan 14 16:22:24 UTC 2018


Package: lxc
Version: 1:2.0.7-2+deb9u1
Followup-For: Bug #875733

Hi folks,

I also ran into this exact issue. It seems upstream fixed this bug, see
https://github.com/lxc/lxc/issues/1737

I've backported this fix (along with some other commits it needs) to the
Debian stretch version, which works as expected. I've attached a patch
to the Debian packaging that does this. Since this is a regression from
earlier Debian versions, I guess this would be worth including in
stretch update?

One caveat to note: In my setup, I had `lxc.cgroup.use=@all` in my
`lxc.conf` file, which prevented this fix from working. See
https://github.com/lxc/lxc/issues/2084 for more details.

Gr.

Matthijs
-------------- next part --------------
From f1aa85a4b1c1c38211a9fa15afac72b3df142b3d Mon Sep 17 00:00:00 2001
From: Matthijs Kooijman <matthijs at stdin.nl>
Date: Sun, 14 Jan 2018 15:47:31 +0100
Subject: [PATCH] Backport upstream commits to fix running without
 CAP_SYS_ADMIN

Closes: #875733
---
 .../0011-lxc-cgroups-move-helper-functions.patch   | 166 ++++++++++
 .../0012-lxc-cgroups-handle-hubrid-layouts.patch   | 358 +++++++++++++++++++++
 .../0013-lxc-cgroups-without-cap-sys-admin.patch   | 157 +++++++++
 debian/patches/series                              |   3 +
 4 files changed, 684 insertions(+)
 create mode 100644 debian/patches/0011-lxc-cgroups-move-helper-functions.patch
 create mode 100644 debian/patches/0012-lxc-cgroups-handle-hubrid-layouts.patch
 create mode 100644 debian/patches/0013-lxc-cgroups-without-cap-sys-admin.patch

diff --git a/debian/patches/0011-lxc-cgroups-move-helper-functions.patch b/debian/patches/0011-lxc-cgroups-move-helper-functions.patch
new file mode 100644
index 0000000..b1e7cea
--- /dev/null
+++ b/debian/patches/0011-lxc-cgroups-move-helper-functions.patch
@@ -0,0 +1,166 @@
+commit 04ad7ffe2a42fb2fa2e78e694990b385fd2dd5e0
+Author: Christian Brauner <christian.brauner at ubuntu.com>
+Date:   Wed Jul 26 14:57:35 2017 +0200
+
+    utils: move helpers from cgfsng.c to utils.{c,h}
+    
+    Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
+
+---
+
+This commit was backported from upstream to Debian without changes, to
+make the patch 0013-lxc-cgroups-without-cap-sys-admin.patch apply.
+
+--- a/src/lxc/cgroups/cgfsng.c
++++ b/src/lxc/cgroups/cgfsng.c
+@@ -112,36 +112,12 @@ static void free_string_list(char **clis
+ 	}
+ }
+ 
+-/* Re-alllocate a pointer, do not fail */
+-static void *must_realloc(void *orig, size_t sz)
+-{
+-	void *ret;
+-
+-	do {
+-		ret = realloc(orig, sz);
+-	} while (!ret);
+-	return ret;
+-}
+-
+ /* Allocate a pointer, do not fail */
+ static void *must_alloc(size_t sz)
+ {
+ 	return must_realloc(NULL, sz);
+ }
+ 
+-/* return copy of string @entry;  do not fail. */
+-static char *must_copy_string(const char *entry)
+-{
+-	char *ret;
+-
+-	if (!entry)
+-		return NULL;
+-	do {
+-		ret = strdup(entry);
+-	} while (!ret);
+-	return ret;
+-}
+-
+ /*
+  * This is a special case - return a copy of @entry
+  * prepending 'name='.  I.e. turn systemd into name=systemd.
+@@ -253,8 +229,6 @@ struct hierarchy *get_hierarchy(const ch
+ 	return NULL;
+ }
+ 
+-static char *must_make_path(const char *first, ...) __attribute__((sentinel));
+-
+ #define BATCH_SIZE 50
+ static void batch_realloc(char **mem, size_t oldlen, size_t newlen)
+ {
+@@ -1165,33 +1139,6 @@ out_free:
+ 	return NULL;
+ }
+ 
+-/*
+- * Concatenate all passed-in strings into one path.  Do not fail.  If any piece is
+- * not prefixed with '/', add a '/'.
+- */
+-static char *must_make_path(const char *first, ...)
+-{
+-	va_list args;
+-	char *cur, *dest;
+-	size_t full_len = strlen(first);
+-
+-	dest = must_copy_string(first);
+-
+-	va_start(args, first);
+-	while ((cur = va_arg(args, char *)) != NULL) {
+-		full_len += strlen(cur);
+-		if (cur[0] != '/')
+-			full_len++;
+-		dest = must_realloc(dest, full_len + 1);
+-		if (cur[0] != '/')
+-			strcat(dest, "/");
+-		strcat(dest, cur);
+-	}
+-	va_end(args);
+-
+-	return dest;
+-}
+-
+ static int cgroup_rmdir(char *dirname)
+ {
+ 	struct dirent *direntp;
+--- a/src/lxc/utils.c
++++ b/src/lxc/utils.c
+@@ -2083,3 +2083,50 @@ int lxc_setgroups(int size, gid_t list[]
+ 
+ 	return 0;
+ }
++
++char *must_make_path(const char *first, ...)
++{
++	va_list args;
++	char *cur, *dest;
++	size_t full_len = strlen(first);
++
++	dest = must_copy_string(first);
++
++	va_start(args, first);
++	while ((cur = va_arg(args, char *)) != NULL) {
++		full_len += strlen(cur);
++		if (cur[0] != '/')
++			full_len++;
++		dest = must_realloc(dest, full_len + 1);
++		if (cur[0] != '/')
++			strcat(dest, "/");
++		strcat(dest, cur);
++	}
++	va_end(args);
++
++	return dest;
++}
++
++char *must_copy_string(const char *entry)
++{
++	char *ret;
++
++	if (!entry)
++		return NULL;
++	do {
++		ret = strdup(entry);
++	} while (!ret);
++
++	return ret;
++}
++
++void *must_realloc(void *orig, size_t sz)
++{
++	void *ret;
++
++	do {
++		ret = realloc(orig, sz);
++	} while (!ret);
++
++	return ret;
++}
+--- a/src/lxc/utils.h
++++ b/src/lxc/utils.h
+@@ -331,4 +331,15 @@ int lxc_safe_long(const char *numstr, lo
+ int lxc_switch_uid_gid(uid_t uid, gid_t gid);
+ int lxc_setgroups(int size, gid_t list[]);
+ 
++/* Concatenate all passed-in strings into one path. Do not fail. If any piece
++ * is not prefixed with '/', add a '/'.
++ */
++char *must_make_path(const char *first, ...) __attribute__((sentinel));
++
++/* return copy of string @entry;  do not fail. */
++char *must_copy_string(const char *entry);
++
++/* Re-alllocate a pointer, do not fail */
++void *must_realloc(void *orig, size_t sz);
++
+ #endif /* __LXC_UTILS_H */
diff --git a/debian/patches/0012-lxc-cgroups-handle-hubrid-layouts.patch b/debian/patches/0012-lxc-cgroups-handle-hubrid-layouts.patch
new file mode 100644
index 0000000..9d37525
--- /dev/null
+++ b/debian/patches/0012-lxc-cgroups-handle-hubrid-layouts.patch
@@ -0,0 +1,358 @@
+commit 6328fd9c05d2730182eb738ffd320de716f062bb
+Author: Christian Brauner <christian.brauner at ubuntu.com>
+Date:   Wed Jul 26 15:15:27 2017 +0200
+
+    cgroups: handle hybrid cgroup layouts
+    
+    Closes #1669.
+    Closes #1678.
+    Relates to https://github.com/systemd/systemd/issues/6408.
+    
+    Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
+
+---
+
+This commit was backported from upstream to Debian without changes, to
+make the patch 0013-lxc-cgroups-without-cap-sys-admin.patch apply.
+
+--- a/src/lxc/Makefile.am
++++ b/src/lxc/Makefile.am
+@@ -18,6 +18,7 @@ noinst_HEADERS = \
+ 	bdev/lxcrsync.h \
+ 	bdev/lxczfs.h \
+ 	cgroups/cgroup.h \
++	cgroups/cgroup_utils.h \
+ 	caps.h \
+ 	conf.h \
+ 	console.h \
+@@ -82,6 +83,7 @@ liblxc_la_SOURCES = \
+ 	bdev/lxczfs.c bdev/lxczfs.h \
+ 	cgroups/cgfs.c \
+ 	cgroups/cgfsng.c \
++	cgroups/cgroup_utils.c cgroups/cgroup_utils.h \
+ 	cgroups/cgroup.c cgroups/cgroup.h \
+ 	commands.c commands.h \
+ 	start.c start.h \
+--- a/src/lxc/cgroups/cgfsng.c
++++ b/src/lxc/cgroups/cgfsng.c
+@@ -49,6 +49,7 @@
+ 
+ #include "bdev.h"
+ #include "cgroup.h"
++#include "cgroup_utils.h"
+ #include "commands.h"
+ #include "log.h"
+ #include "utils.h"
+@@ -72,6 +73,7 @@ struct hierarchy {
+ 	char *mountpoint;
+ 	char *base_cgroup;
+ 	char *fullcgpath;
++	bool is_cgroup_v2;
+ };
+ 
+ /*
+@@ -594,7 +596,8 @@ static bool handle_cpuset_hierarchy(stru
+ 	}
+ 
+ 	clonechildrenpath = must_make_path(cgpath, "cgroup.clone_children", NULL);
+-	if (!file_exists(clonechildrenpath)) { /* unified hierarchy doesn't have clone_children */
++	/* unified hierarchy doesn't have clone_children */
++	if (!file_exists(clonechildrenpath)) {
+ 		free(clonechildrenpath);
+ 		free(cgpath);
+ 		return true;
+@@ -736,10 +739,14 @@ static bool is_lxcfs(const char *line)
+  */
+ static char **get_controllers(char **klist, char **nlist, char *line)
+ {
+-	// the fourth field is /sys/fs/cgroup/comma-delimited-controller-list
++	/* the fourth field is /sys/fs/cgroup/comma-delimited-controller-list */
+ 	int i;
+ 	char *p = line, *p2, *tok, *saveptr = NULL;
+ 	char **aret = NULL;
++	bool is_cgroup_v2;
++
++	/* handle cgroup v2 */
++	is_cgroup_v2 = is_cgroupfs_v2(line);
+ 
+ 	for (i = 0; i < 4; i++) {
+ 		p = strchr(p, ' ');
+@@ -760,6 +767,13 @@ static char **get_controllers(char **kli
+ 		return NULL;
+ 	}
+ 	*p2 = '\0';
++
++	/* cgroup v2 does not have separate mountpoints for controllers */
++	if (is_cgroup_v2) {
++		must_append_controller(klist, nlist, &aret, "cgroup2");
++		return aret;
++	}
++
+ 	for (tok = strtok_r(p, ",", &saveptr); tok;
+ 			tok = strtok_r(NULL, ",", &saveptr)) {
+ 		must_append_controller(klist, nlist, &aret, tok);
+@@ -768,15 +782,6 @@ static char **get_controllers(char **kli
+ 	return aret;
+ }
+ 
+-/* return true if the fstype is cgroup */
+-static bool is_cgroupfs(char *line)
+-{
+-	char *p = strstr(line, " - ");
+-	if (!p)
+-		return false;
+-	return strncmp(p, " - cgroup ", 10) == 0;
+-}
+-
+ /* Add a controller to our list of hierarchies */
+ static void add_controller(char **clist, char *mountpoint, char *base_cgroup)
+ {
+@@ -789,6 +794,12 @@ static void add_controller(char **clist,
+ 	new->base_cgroup = base_cgroup;
+ 	new->fullcgpath = NULL;
+ 
++	/* record if this is the cgroup v2 hierarchy */
++	if (!strcmp(base_cgroup, "cgroup2"))
++		new->is_cgroup_v2 = true;
++	else
++		new->is_cgroup_v2 = false;
++
+ 	newentry = append_null_to_list((void ***)&hierarchies);
+ 	hierarchies[newentry] = new;
+ }
+@@ -870,13 +881,21 @@ static bool controller_in_clist(char *cg
+ static char *get_current_cgroup(char *basecginfo, char *controller)
+ {
+ 	char *p = basecginfo;
++	bool is_cgroup_v2;
++	bool is_cgroup_v2_base_cgroup;
++
++	is_cgroup_v2 = !strcmp(controller, "cgroup2");
++	while (true) {
++		is_cgroup_v2_base_cgroup = false;
++		/* cgroup v2 entry in "/proc/<pid>/cgroup": "0::/some/path" */
++		if (is_cgroup_v2 && (*p == '0'))
++			is_cgroup_v2_base_cgroup = true;
+ 
+-	while (1) {
+ 		p = strchr(p, ':');
+ 		if (!p)
+ 			return NULL;
+ 		p++;
+-		if (controller_in_clist(p, controller)) {
++		if (is_cgroup_v2_base_cgroup || controller_in_clist(p, controller)) {
+ 			p = strchr(p, ':');
+ 			if (!p)
+ 				return NULL;
+@@ -891,20 +910,6 @@ static char *get_current_cgroup(char *ba
+ 	}
+ }
+ 
+-/*
+- * Given a hierarchy @mountpoint and base @path, verify that we can create
+- * directories underneath it.
+- */
+-static bool test_writeable(char *mountpoint, char *path)
+-{
+-	char *fullpath = must_make_path(mountpoint, path, NULL);
+-	int ret;
+-
+-	ret = access(fullpath, W_OK);
+-	free(fullpath);
+-	return ret == 0;
+-}
+-
+ static void must_append_string(char ***list, char *entry)
+ {
+ 	int newentry = append_null_to_list((void ***)list);
+@@ -933,16 +938,17 @@ static void get_existing_subsystems(char
+ 			continue;
+ 		*p2 = '\0';
+ 
+-		/* If we have a mixture between cgroup v1 and cgroup v2
+-		 * hierarchies, then /proc/self/cgroup contains entries of the
+-		 * form:
++		/* If the kernel has cgroup v2 support, then /proc/self/cgroup
++		 * contains an entry of the form:
+ 		 *
+ 		 *	0::/some/path
+ 		 *
+-		 * We need to skip those.
++		 * In this case we use "cgroup2" as controller name.
+ 		 */
+-		if ((p2 - p) == 0)
++		if ((p2 - p) == 0) {
++			must_append_string(klist, "cgroup2");
+ 			continue;
++		}
+ 
+ 		for (tok = strtok_r(p, ",", &saveptr); tok;
+ 				tok = strtok_r(NULL, ",", &saveptr)) {
+@@ -1044,8 +1050,10 @@ static bool parse_hierarchies(void)
+ 	while (getline(&line, &len, f) != -1) {
+ 		char **controller_list = NULL;
+ 		char *mountpoint, *base_cgroup;
++		bool is_cgroup_v2, writeable;
+ 
+-		if (!is_lxcfs(line) && !is_cgroupfs(line))
++		is_cgroup_v2 = is_cgroupfs_v2(line);
++		if (!is_lxcfs(line) && !is_cgroupfs_v1(line) && !is_cgroup_v2)
+ 			continue;
+ 
+ 		controller_list = get_controllers(klist, nlist, line);
+@@ -1071,9 +1079,14 @@ static bool parse_hierarchies(void)
+ 			free(mountpoint);
+ 			continue;
+ 		}
++
+ 		trim(base_cgroup);
+ 		prune_init_scope(base_cgroup);
+-		if (!test_writeable(mountpoint, base_cgroup)) {
++		if (is_cgroup_v2)
++			writeable = test_writeable_v2(mountpoint, base_cgroup);
++		else
++			writeable = test_writeable_v1(mountpoint, base_cgroup);
++		if (!writeable) {
+ 			free_string_list(controller_list);
+ 			free(mountpoint);
+ 			free(base_cgroup);
+--- /dev/null
++++ b/src/lxc/cgroups/cgroup_utils.c
+@@ -0,0 +1,86 @@
++/*
++ * lxc: linux Container library
++ *
++ * Copyright ? 2017 Canonical Ltd.
++ *
++ * Authors:
++ * Serge Hallyn <serge.hallyn at ubuntu.com>
++ * Christian Brauner <christian.brauner at ubuntu.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#include "config.h"
++
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++
++#include "cgroup_utils.h"
++#include "utils.h"
++
++bool is_cgroupfs_v1(char *line)
++{
++	char *p = strstr(line, " - ");
++	if (!p)
++		return false;
++	return strncmp(p, " - cgroup ", 10) == 0;
++}
++
++bool is_cgroupfs_v2(char *line)
++{
++	char *p = strstr(line, " - ");
++	if (!p)
++		return false;
++
++	return strncmp(p, " - cgroup2 ", 11) == 0;
++}
++
++bool test_writeable_v1(char *mountpoint, char *path)
++{
++	char *fullpath = must_make_path(mountpoint, path, NULL);
++	int ret;
++
++	ret = access(fullpath, W_OK);
++	free(fullpath);
++	return ret == 0;
++}
++
++bool test_writeable_v2(char *mountpoint, char *path)
++{
++	/* In order to move ourselves into an appropriate sub-cgroup we need to
++	 * have write access to the parent cgroup's "cgroup.procs" file, i.e. we
++	 * need to have write access to the our current cgroups's "cgroup.procs"
++	 * file.
++	 */
++	int ret;
++	char *cgroup_path, *cgroup_procs_file;
++
++	cgroup_path = must_make_path(mountpoint, path, NULL);
++	cgroup_procs_file = must_make_path(cgroup_path, "cgroup.procs", NULL);
++
++	ret = access(cgroup_path, W_OK);
++	free(cgroup_path);
++	if (ret < 0) {
++		free(cgroup_procs_file);
++		return false;
++	}
++
++	ret = access(cgroup_procs_file, W_OK);
++	free(cgroup_procs_file);
++
++	return ret == 0;
++}
+--- /dev/null
++++ b/src/lxc/cgroups/cgroup_utils.h
+@@ -0,0 +1,48 @@
++/*
++ * lxc: linux Container library
++ *
++ * Copyright ? 2017 Canonical Ltd.
++ *
++ * Authors:
++ * Serge Hallyn <serge.hallyn at ubuntu.com>
++ * Christian Brauner <christian.brauner at ubuntu.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
++ */
++
++#ifndef __LXC_CGROUP_UTILS_H
++#define __LXC_CGROUP_UTILS_H
++
++#include <stdbool.h>
++#include <stdio.h>
++
++/* Check if given entry from /proc/<pid>/mountinfo is a cgroupfs v1 mount. */
++extern bool is_cgroupfs_v1(char *line);
++
++/* Check if given entry from /proc/<pid>/mountinfo is a cgroupfs v2 mount. */
++extern bool is_cgroupfs_v2(char *line);
++
++/* Given a v1 hierarchy @mountpoint and base @path, verify that we can create
++ * directories underneath it.
++ */
++extern bool test_writeable_v1(char *mountpoint, char *path);
++
++/* Given a v2 hierarchy @mountpoint and base @path, verify that we can create
++ * directories underneath it and that we have write access to the cgroup's
++ * "cgroup.procs" file.
++ */
++extern bool test_writeable_v2(char *mountpoint, char *path);
++
++#endif /* __LXC_CGROUP_UTILS_H */
diff --git a/debian/patches/0013-lxc-cgroups-without-cap-sys-admin.patch b/debian/patches/0013-lxc-cgroups-without-cap-sys-admin.patch
new file mode 100644
index 0000000..a56b38b
--- /dev/null
+++ b/debian/patches/0013-lxc-cgroups-without-cap-sys-admin.patch
@@ -0,0 +1,157 @@
+From: Matthijs Kooijman <matthijs at stdin.nl>
+Date: Sun, 14 Jan 2018 15:38:49 +0100
+Subject: lxc-start: Support containers withoug cap_sys_admin on kernel 4.6 and above
+
+When running systemd in a container running on kernel 4.6 or newer, it
+requires some additional cgroup filesystems to be mounted. When running
+without cap_sys_admin, systemd cannot mount these itself, and thus
+fails on startup saying "Failed to mount API filesystems, freezing.".
+
+This bug is reported as https://bugs.debian.org/875733 and
+https://github.com/lxc/lxc/issues/1737 and fixed upstream by
+https://github.com/lxc/lxc/pull/1888
+
+This backports the two commits from that PR:
+cdfe90a49f516b0f1210d181980f14a4765e10da and
+b635e92d21d2a4d71a553388f18cfa08f44bf1ba (with some trivial changes to
+make it merge).
+
+--- a/src/lxc/cgroups/cgfs.c
++++ b/src/lxc/cgroups/cgfs.c
+@@ -1418,11 +1418,12 @@ static bool cgroupfs_mount_cgroup(void *
+ 	struct cgfs_data *cgfs_d;
+ 	struct cgroup_process_info *info, *base_info;
+ 	int r, saved_errno = 0;
++	struct lxc_handler *handler = hdata;
+ 
+ 	if (cgns_supported())
+ 		return true;
+ 
+-	cgfs_d = hdata;
++	cgfs_d = handler->cgroup_data;
+ 	if (!cgfs_d)
+ 		return false;
+ 	base_info = cgfs_d->info;
+--- a/src/lxc/cgroups/cgfsng.c
++++ b/src/lxc/cgroups/cgfsng.c
+@@ -48,6 +48,7 @@
+ #include <sys/types.h>
+ 
+ #include "bdev.h"
++#include "caps.h"
+ #include "cgroup.h"
+ #include "cgroup_utils.h"
+ #include "commands.h"
+@@ -795,7 +796,7 @@ static void add_controller(char **clist,
+ 	new->fullcgpath = NULL;
+ 
+ 	/* record if this is the cgroup v2 hierarchy */
+-	if (!strcmp(base_cgroup, "cgroup2"))
++	if (clist && !strcmp(*clist, "cgroup2"))
+ 		new->is_cgroup_v2 = true;
+ 	else
+ 		new->is_cgroup_v2 = false;
+@@ -1535,17 +1536,49 @@ do_secondstage_mounts_if_needed(int type
+ 	return 0;
+ }
+ 
++static int mount_cgroup_cgns_supported(struct hierarchy *h, const char *controllerpath)
++{
++	 int ret;
++	 char *controllers = NULL;
++	 char *type = "cgroup2";
++
++	if (!h->is_cgroup_v2) {
++		controllers = lxc_string_join(",", (const char **)h->controllers, false);
++		if (!controllers)
++			return -ENOMEM;
++		type = "cgroup";
++	}
++
++	ret = mount("cgroup", controllerpath, type, MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RELATIME, controllers);
++	free(controllers);
++	if (ret < 0) {
++		SYSERROR("Failed to mount %s with cgroup filesystem type %s", controllerpath, type);
++		return -1;
++	}
++
++	DEBUG("Mounted %s with cgroup filesystem type %s", controllerpath, type);
++	return 0;
++}
++
+ static bool cgfsng_mount(void *hdata, const char *root, int type)
+ {
+-	struct cgfsng_handler_data *d = hdata;
++	int i;
+ 	char *tmpfspath = NULL;
+ 	bool retval = false;
+-	int i;
++	struct lxc_handler *handler = hdata;
++	struct cgfsng_handler_data *d = handler->cgroup_data;
++	bool has_cgns = false, has_sys_admin = true;
+ 
+ 	if ((type & LXC_AUTO_CGROUP_MASK) == 0)
+ 		return true;
+ 
+-	if (cgns_supported())
++	has_cgns = cgns_supported();
++	if (!lxc_list_empty(&handler->conf->keepcaps))
++		has_sys_admin = in_caplist(CAP_SYS_ADMIN, &handler->conf->keepcaps);
++	else
++		has_sys_admin = !in_caplist(CAP_SYS_ADMIN, &handler->conf->caps);
++
++	if (has_cgns && has_sys_admin)
+ 		return true;
+ 
+ 	tmpfspath = must_make_path(root, "/sys/fs/cgroup", NULL);
+@@ -1581,6 +1614,19 @@ static bool cgfsng_mount(void *hdata, co
+ 			free(controllerpath);
+ 			goto bad;
+ 		}
++
++		if (has_cgns && !has_sys_admin) {
++			/* If cgroup namespaces are supported but the container
++			 * will not have CAP_SYS_ADMIN after it has started we
++			 * need to mount the cgroups manually.
++			 */
++			r = mount_cgroup_cgns_supported(h, controllerpath);
++			free(controllerpath);
++			if (r < 0)
++				goto bad;
++			continue;
++		}
++
+ 		if (mount_cgroup_full(type, h, controllerpath, d->container_cgroup) < 0) {
+ 			free(controllerpath);
+ 			goto bad;
+--- a/src/lxc/cgroups/cgroup.c
++++ b/src/lxc/cgroups/cgroup.c
+@@ -160,7 +160,7 @@ bool cgroup_chown(struct lxc_handler *ha
+ bool cgroup_mount(const char *root, struct lxc_handler *handler, int type)
+ {
+ 	if (ops) {
+-		return ops->mount_cgroup(handler->cgroup_data, root, type);
++		return ops->mount_cgroup(handler, root, type);
+ 	}
+ 	return false;
+ }
+--- a/src/lxc/conf.c
++++ b/src/lxc/conf.c
+@@ -252,9 +252,6 @@ __thread struct lxc_conf *current_config
+ struct lxc_conf *current_config;
+ #endif
+ 
+-/* Declare this here, since we don't want to reshuffle the whole file. */
+-static int in_caplist(int cap, struct lxc_list *caps);
+-
+ static int instantiate_veth(struct lxc_handler *, struct lxc_netdev *);
+ static int instantiate_macvlan(struct lxc_handler *, struct lxc_netdev *);
+ static int instantiate_vlan(struct lxc_handler *, struct lxc_netdev *);
+--- a/src/lxc/conf.h
++++ b/src/lxc/conf.h
+@@ -447,4 +447,5 @@ void remount_all_slave(void);
+ extern void suggest_default_idmap(void);
+ FILE *make_anonymous_mount_file(struct lxc_list *mount);
+ struct lxc_list *sort_cgroup_settings(struct lxc_list* cgroup_settings);
++extern int in_caplist(int cap, struct lxc_list *caps);
+ #endif
diff --git a/debian/patches/series b/debian/patches/series
index 5e0bb25..8cf2130 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,6 @@
 lxc-2.0-CVE-2017-5985-Ensure-target-netns-is-caller-owned.patch
 0003-lxc-debian-don-t-hardcode-valid-releases.patch
 0004-lxc-debian-don-t-write-C.-locales-to-etc-locale.gen.patch
+0011-lxc-cgroups-move-helper-functions.patch
+0012-lxc-cgroups-handle-hubrid-layouts.patch
+0013-lxc-cgroups-without-cap-sys-admin.patch
-- 
2.11.0



More information about the Pkg-lxc-devel mailing list