[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