[lxc-devel] [lxc/master] confile: add lxc.cgroup.keep

brauner on Github lxc-bot at linuxcontainers.org
Mon Aug 27 00:58:13 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1148 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180827/3e643a33/attachment.bin>
-------------- next part --------------
From a7c4ddea9f4677f65012502905842b9a9f26966c Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 26 Aug 2018 18:49:21 +0200
Subject: [PATCH 1/3] start: do not initialize cgroup_ops twice

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
 src/lxc/start.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/lxc/start.c b/src/lxc/start.c
index 6b66e4fb5..c9200f49b 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1694,11 +1694,6 @@ static int lxc_spawn(struct lxc_handler *handler)
 		}
 	}
 
-	if (!cgroup_init(handler)) {
-		ERROR("Failed initializing cgroup support");
-		goto out_delete_net;
-	}
-
 	if (!cgroup_ops->create(cgroup_ops, handler)) {
 		ERROR("Failed creating cgroups");
 		goto out_delete_net;

From 9530b30cb8987fbd5d322fe3b0b69f7f9ff4ba5d Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 18 May 2018 16:16:22 +0200
Subject: [PATCH 2/3] confile: add lxc.cgroup.keep

This adds the new lxc.cgroup.keep config key. The key can be used to instruct
LXC to not escape to never escape to the root cgroup. This makes it easy for
users to adhere to restrictions enforced by cgroup2 and systemd. Specifically,
this makes it possible to run LXC containers as systemd services.

Note that cgroup v1 is considered legacy and will not see additional
controllers being added to it. This means that it is safe to use
lxc.cgroup.keep as config key since there is no "keep" controller. The only way
a conflict can be introduced is if the user is creating a named controller. I
think this case can be safely ignored since it is super rare and also the users
problem.

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
Cc: Felix Abecassis <fabecassis at nvidia.com>
Cc: Jonathan Calmels <jcalmels at nvidia.com>
---
 src/lxc/conf.h    |  1 +
 src/lxc/confile.c | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index c68108d83..070dd2292 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -76,6 +76,7 @@ struct lxc_cgroup {
 		struct /* meta */ {
 			char *controllers;
 			char *dir;
+			bool keep;
 		};
 	};
 };
diff --git a/src/lxc/confile.c b/src/lxc/confile.c
index 326782eac..a2fe1d896 100644
--- a/src/lxc/confile.c
+++ b/src/lxc/confile.c
@@ -92,6 +92,7 @@ lxc_config_define(cap_keep);
 lxc_config_define(cgroup_controller);
 lxc_config_define(cgroup2_controller);
 lxc_config_define(cgroup_dir);
+lxc_config_define(cgroup_keep);
 lxc_config_define(console_buffer_size);
 lxc_config_define(console_logfile);
 lxc_config_define(console_path);
@@ -167,6 +168,7 @@ static struct lxc_config_t config[] = {
 	{ "lxc.cap.keep",                  set_config_cap_keep,                    get_config_cap_keep,                    clr_config_cap_keep,                  },
 	{ "lxc.cgroup2",                   set_config_cgroup2_controller,          get_config_cgroup2_controller,          clr_config_cgroup2_controller,        },
 	{ "lxc.cgroup.dir",                set_config_cgroup_dir,                  get_config_cgroup_dir,                  clr_config_cgroup_dir,                },
+	{ "lxc.cgroup.keep",               set_config_cgroup_keep,                 get_config_cgroup_keep,                 clr_config_cgroup_keep,               },
 	{ "lxc.cgroup",                    set_config_cgroup_controller,           get_config_cgroup_controller,           clr_config_cgroup_controller,         },
 	{ "lxc.console.buffer.size",       set_config_console_buffer_size,         get_config_console_buffer_size,         clr_config_console_buffer_size,       },
 	{ "lxc.console.logfile",           set_config_console_logfile,             get_config_console_logfile,             clr_config_console_logfile,           },
@@ -1395,6 +1397,31 @@ static int set_config_cgroup_dir(const char *key, const char *value,
 	return set_config_string_item(&lxc_conf->cgroup_meta.dir, value);
 }
 
+static int set_config_cgroup_keep(const char *key, const char *value,
+				  struct lxc_conf *lxc_conf, void *data)
+{
+	int ret, converted;
+
+	if (lxc_config_value_empty(value))
+		return clr_config_cgroup_keep(key, lxc_conf, NULL);
+
+	ret = lxc_safe_uint(value, &converted);
+	if (ret < 0)
+		return -ret;
+
+	if (converted == 1) {
+		lxc_conf->cgroup_meta.keep = true;
+		return 0;
+	}
+
+	if (converted == 0) {
+		lxc_conf->cgroup_meta.keep = false;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
 static int set_config_prlimit(const char *key, const char *value,
 			    struct lxc_conf *lxc_conf, void *data)
 {
@@ -3187,6 +3214,13 @@ static int get_config_cgroup_dir(const char *key, char *retv, int inlen,
 	return fulllen;
 }
 
+static inline int get_config_cgroup_keep(const char *key, char *retv, int inlen,
+					 struct lxc_conf *lxc_conf, void *data)
+{
+	return lxc_get_conf_int(lxc_conf, retv, inlen,
+				lxc_conf->cgroup_meta.keep);
+}
+
 static int get_config_idmaps(const char *key, char *retv, int inlen,
 			     struct lxc_conf *c, void *data)
 {
@@ -3927,6 +3961,13 @@ static int clr_config_cgroup_dir(const char *key, struct lxc_conf *lxc_conf,
 	return 0;
 }
 
+static inline int clr_config_cgroup_keep(const char *key,
+					 struct lxc_conf *lxc_conf, void *data)
+{
+	lxc_conf->cgroup_meta.keep = false;
+	return 0;
+}
+
 static inline int clr_config_idmaps(const char *key, struct lxc_conf *c,
 				    void *data)
 {

From 7e9688010a8cea1d7d7b317b8c63b0855c17a7c9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Sun, 26 Aug 2018 18:59:01 +0200
Subject: [PATCH 3/3] cgroups: don't escape if lxc.cgroup.keep is true

Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
Cc: Felix Abecassis <fabecassis at nvidia.com>
Cc: Jonathan Calmels <jcalmels at nvidia.com>
---
 src/lxc/attach.c         |  2 +-
 src/lxc/cgroups/cgfsng.c | 31 ++++++++++++++-----------------
 src/lxc/cgroups/cgroup.c |  6 +++---
 src/lxc/cgroups/cgroup.h |  4 ++--
 src/lxc/criu.c           |  6 +++---
 src/lxc/freezer.c        | 13 +++++++------
 src/lxc/lxc.h            |  6 ++++--
 src/lxc/lxccontainer.c   |  8 ++++----
 src/lxc/start.c          |  2 +-
 9 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 2218a3492..87f14398f 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -1261,7 +1261,7 @@ int lxc_attach(const char *name, const char *lxcpath,
 		if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
 			struct cgroup_ops *cgroup_ops;
 
-			cgroup_ops = cgroup_init(NULL);
+			cgroup_ops = cgroup_init(conf);
 			if (!cgroup_ops)
 				goto on_error;
 
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index 56c8db544..e7a242910 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1742,11 +1742,11 @@ static int cgfsng_nrtasks(struct cgroup_ops *ops)
 }
 
 /* Only root needs to escape to the cgroup of its init. */
-static bool cgfsng_escape(const struct cgroup_ops *ops)
+static bool cgfsng_escape(const struct cgroup_ops *ops, struct lxc_conf *conf)
 {
 	int i;
 
-	if (geteuid())
+	if (conf->cgroup_meta.keep || geteuid())
 		return true;
 
 	for (i = 0; ops->hierarchies[i]; i++) {
@@ -2278,11 +2278,10 @@ static bool cgroup_use_wants_controllers(const struct cgroup_ops *ops,
 /* At startup, parse_hierarchies finds all the info we need about cgroup
  * mountpoints and current cgroups, and stores it in @d.
  */
-static bool cg_hybrid_init(struct cgroup_ops *ops)
+static bool cg_hybrid_init(struct cgroup_ops *ops, bool keep)
 {
 	int ret;
 	char *basecginfo;
-	bool will_escape;
 	FILE *f;
 	size_t len = 0;
 	char *line = NULL;
@@ -2291,8 +2290,7 @@ static bool cg_hybrid_init(struct cgroup_ops *ops)
 	/* Root spawned containers escape the current cgroup, so use init's
 	 * cgroups as our base in that case.
 	 */
-	will_escape = (geteuid() == 0);
-	if (will_escape)
+	if (!keep && (geteuid() == 0))
 		basecginfo = read_file("/proc/1/cgroup");
 	else
 		basecginfo = read_file("/proc/self/cgroup");
@@ -2443,14 +2441,12 @@ static int cg_is_pure_unified(void)
 }
 
 /* Get current cgroup from /proc/self/cgroup for the cgroupfs v2 hierarchy. */
-static char *cg_unified_get_current_cgroup(void)
+static char *cg_unified_get_current_cgroup(bool keep)
 {
 	char *basecginfo, *base_cgroup;
-	bool will_escape;
 	char *copy = NULL;
 
-	will_escape = (geteuid() == 0);
-	if (will_escape)
+	if (!keep && (geteuid() == 0))
 		basecginfo = read_file("/proc/1/cgroup");
 	else
 		basecginfo = read_file("/proc/self/cgroup");
@@ -2474,7 +2470,7 @@ static char *cg_unified_get_current_cgroup(void)
 	return copy;
 }
 
-static int cg_unified_init(struct cgroup_ops *ops)
+static int cg_unified_init(struct cgroup_ops *ops, bool keep)
 {
 	int ret;
 	char *mountpoint, *subtree_path;
@@ -2488,7 +2484,7 @@ static int cg_unified_init(struct cgroup_ops *ops)
 	if (ret != CGROUP2_SUPER_MAGIC)
 		return 0;
 
-	base_cgroup = cg_unified_get_current_cgroup();
+	base_cgroup = cg_unified_get_current_cgroup(keep);
 	if (!base_cgroup)
 		return -EINVAL;
 	prune_init_scope(base_cgroup);
@@ -2520,10 +2516,11 @@ static int cg_unified_init(struct cgroup_ops *ops)
 	return CGROUP2_SUPER_MAGIC;
 }
 
-static bool cg_init(struct cgroup_ops *ops)
+static bool cg_init(struct cgroup_ops *ops, struct lxc_conf *conf)
 {
 	int ret;
 	const char *tmp;
+	bool keep = conf->cgroup_meta.keep;
 
 	tmp = lxc_global_config_value("lxc.cgroup.use");
 	if (tmp) {
@@ -2539,14 +2536,14 @@ static bool cg_init(struct cgroup_ops *ops)
 		free(pin);
 	}
 
-	ret = cg_unified_init(ops);
+	ret = cg_unified_init(ops, keep);
 	if (ret < 0)
 		return false;
 
 	if (ret == CGROUP2_SUPER_MAGIC)
 		return true;
 
-	return cg_hybrid_init(ops);
+	return cg_hybrid_init(ops, keep);
 }
 
 static bool cgfsng_data_init(struct cgroup_ops *ops)
@@ -2565,7 +2562,7 @@ static bool cgfsng_data_init(struct cgroup_ops *ops)
 	return true;
 }
 
-struct cgroup_ops *cgfsng_ops_init(void)
+struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf)
 {
 	struct cgroup_ops *cgfsng_ops;
 
@@ -2576,7 +2573,7 @@ struct cgroup_ops *cgfsng_ops_init(void)
 	memset(cgfsng_ops, 0, sizeof(struct cgroup_ops));
 	cgfsng_ops->cgroup_layout = CGROUP_LAYOUT_UNKNOWN;
 
-	if (!cg_init(cgfsng_ops)) {
+	if (!cg_init(cgfsng_ops, conf)) {
 		free(cgfsng_ops);
 		return NULL;
 	}
diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index f86bd9be8..7dffeb0cc 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -33,13 +33,13 @@
 
 lxc_log_define(cgroup, lxc);
 
-extern struct cgroup_ops *cgfsng_ops_init(void);
+extern struct cgroup_ops *cgfsng_ops_init(struct lxc_conf *conf);
 
-struct cgroup_ops *cgroup_init(struct lxc_handler *handler)
+struct cgroup_ops *cgroup_init(struct lxc_conf *conf)
 {
 	struct cgroup_ops *cgroup_ops;
 
-	cgroup_ops = cgfsng_ops_init();
+	cgroup_ops = cgfsng_ops_init(conf);
 	if (!cgroup_ops) {
 		ERROR("Failed to initialize cgroup driver");
 		return NULL;
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index 8f4af06c1..0c8b2ea88 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -127,7 +127,7 @@ struct cgroup_ops {
 	bool (*create)(struct cgroup_ops *ops, struct lxc_handler *handler);
 	bool (*enter)(struct cgroup_ops *ops, pid_t pid);
 	const char *(*get_cgroup)(struct cgroup_ops *ops, const char *controller);
-	bool (*escape)(const struct cgroup_ops *ops);
+	bool (*escape)(const struct cgroup_ops *ops, struct lxc_conf *conf);
 	int (*num_hierarchies)(struct cgroup_ops *ops);
 	bool (*get_hierarchies)(struct cgroup_ops *ops, int n, char ***out);
 	int (*set)(struct cgroup_ops *ops, const char *filename,
@@ -145,7 +145,7 @@ struct cgroup_ops {
 	int (*nrtasks)(struct cgroup_ops *ops);
 };
 
-extern struct cgroup_ops *cgroup_init(struct lxc_handler *handler);
+extern struct cgroup_ops *cgroup_init(struct lxc_conf *conf);
 extern void cgroup_exit(struct cgroup_ops *ops);
 
 extern void prune_init_scope(char *cg);
diff --git a/src/lxc/criu.c b/src/lxc/criu.c
index 1c2f61547..db9101b0f 100644
--- a/src/lxc/criu.c
+++ b/src/lxc/criu.c
@@ -190,7 +190,7 @@ static void exec_criu(struct cgroup_ops *cgroup_ops, struct criu_opts *opts)
 	 * /actual/ root cgroup so that lxcfs thinks criu has enough rights to
 	 * see all cgroups.
 	 */
-	if (!cgroup_ops->escape(cgroup_ops)) {
+	if (!cgroup_ops->escape(cgroup_ops, opts->handler->conf)) {
 		ERROR("failed to escape cgroups");
 		return;
 	}
@@ -967,7 +967,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_
 	if (lxc_init(c->name, handler) < 0)
 		goto out;
 
-	cgroup_ops = cgroup_init(NULL);
+	cgroup_ops = cgroup_init(c->lxc_conf);
 	if (!cgroup_ops)
 		goto out_fini_handler;
 	handler->cgroup_ops = cgroup_ops;
@@ -1272,7 +1272,7 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op
 
 		h.name = c->name;
 
-		cgroup_ops = cgroup_init(NULL);
+		cgroup_ops = cgroup_init(c->lxc_conf);
 		if (!cgroup_ops) {
 			ERROR("failed to cgroup_init()");
 			_exit(EXIT_FAILURE);
diff --git a/src/lxc/freezer.c b/src/lxc/freezer.c
index a6b9da061..b6caec178 100644
--- a/src/lxc/freezer.c
+++ b/src/lxc/freezer.c
@@ -42,7 +42,8 @@
 
 lxc_log_define(freezer, lxc);
 
-static int do_freeze_thaw(bool freeze, const char *name, const char *lxcpath)
+static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name,
+			  const char *lxcpath)
 {
 	int ret;
 	char v[100];
@@ -51,7 +52,7 @@ static int do_freeze_thaw(bool freeze, const char *name, const char *lxcpath)
 	size_t state_len = 6;
 	lxc_state_t new_state = freeze ? FROZEN : THAWED;
 
-	cgroup_ops = cgroup_init(NULL);
+	cgroup_ops = cgroup_init(conf);
 	if (!cgroup_ops)
 		return -1;
 
@@ -85,14 +86,14 @@ static int do_freeze_thaw(bool freeze, const char *name, const char *lxcpath)
 	}
 }
 
-int lxc_freeze(const char *name, const char *lxcpath)
+int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
 {
 	lxc_cmd_serve_state_clients(name, lxcpath, FREEZING);
 	lxc_monitor_send_state(name, FREEZING, lxcpath);
-	return do_freeze_thaw(true, name, lxcpath);
+	return do_freeze_thaw(true, conf, name, lxcpath);
 }
 
-int lxc_unfreeze(const char *name, const char *lxcpath)
+int lxc_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
 {
-	return do_freeze_thaw(false, name, lxcpath);
+	return do_freeze_thaw(false, conf, name, lxcpath);
 }
diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
index 8ae8c717d..c2a150cf4 100644
--- a/src/lxc/lxc.h
+++ b/src/lxc/lxc.h
@@ -81,14 +81,16 @@ extern int lxc_monitor_close(int fd);
  * @name : the container name
  * Returns 0 on success, < 0 otherwise
  */
-extern int lxc_freeze(const char *name, const char *lxcpath);
+extern int lxc_freeze(struct lxc_conf *conf, const char *name,
+		      const char *lxcpath);
 
 /*
  * Unfreeze all previously frozen tasks.
  * @name : the name of the container
  * Return 0 on success, < 0 otherwise
  */
-extern int lxc_unfreeze(const char *name, const char *lxcpath);
+extern int lxc_unfreeze(struct lxc_conf *conf, const char *name,
+			const char *lxcpath);
 
 /*
  * Retrieve the container state
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 6c0620d8f..2c37caefd 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -529,7 +529,7 @@ static bool do_lxcapi_freeze(struct lxc_container *c)
 	if (!c)
 		return false;
 
-	ret = lxc_freeze(c->name, c->config_path);
+	ret = lxc_freeze(c->lxc_conf, c->name, c->config_path);
 	if (ret < 0)
 		return false;
 
@@ -545,7 +545,7 @@ static bool do_lxcapi_unfreeze(struct lxc_container *c)
 	if (!c)
 		return false;
 
-	ret = lxc_unfreeze(c->name, c->config_path);
+	ret = lxc_unfreeze(c->lxc_conf, c->name, c->config_path);
 	if (ret < 0)
 		return false;
 
@@ -3263,7 +3263,7 @@ static bool do_lxcapi_set_cgroup_item(struct lxc_container *c, const char *subsy
 	if (is_stopped(c))
 		return false;
 
-	cgroup_ops = cgroup_init(NULL);
+	cgroup_ops = cgroup_init(c->lxc_conf);
 	if (!cgroup_ops)
 		return false;
 
@@ -3292,7 +3292,7 @@ static int do_lxcapi_get_cgroup_item(struct lxc_container *c, const char *subsys
 	if (is_stopped(c))
 		return -1;
 
-	cgroup_ops = cgroup_init(NULL);
+	cgroup_ops = cgroup_init(c->lxc_conf);
 	if (!cgroup_ops)
 		return -1;
 
diff --git a/src/lxc/start.c b/src/lxc/start.c
index c9200f49b..086a874f0 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -856,7 +856,7 @@ int lxc_init(const char *name, struct lxc_handler *handler)
 	}
 	TRACE("Chowned console");
 
-	handler->cgroup_ops = cgroup_init(handler);
+	handler->cgroup_ops = cgroup_init(handler->conf);
 	if (!handler->cgroup_ops) {
 		ERROR("Failed to initialize cgroup driver");
 		goto out_delete_terminal;


More information about the lxc-devel mailing list