[lxc-devel] [PATCH 2/2] setup cgroups from parent

Serge Hallyn serge.hallyn at ubuntu.com
Mon Jan 14 23:32:44 UTC 2013


This is a first step to enabling user namespaces.  When starting a
container in a new user namespace, the child will not have the
rights to write to the cgroup fs.  (We can give it that right, but
don't always want to have to).

At the parent, we don't want to setup_cgroups() before the child
has set itself up.  But we also don't want to wait until it has
started running it's init, since that is racy.

Therefore introduce a new sync point.  The child will let the
parent know when it is ready to be confined, and wait for the
parent to respond that it has done so.  Then the child will finish
constraining itself with LSM and seccomp and execute init.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/conf.c  |  5 -----
 src/lxc/start.c | 26 ++++++++++++++++++++++++--
 src/lxc/sync.h  |  2 ++
 3 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index d448d59..b516d7d 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2594,11 +2594,6 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
 		}
 	}
 
-	if (setup_cgroup(name, &lxc_conf->cgroup)) {
-		ERROR("failed to setup the cgroups for '%s'", name);
-		return -1;
-	}
-
 	if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
 		ERROR("failed to setup the console for '%s'", name);
 		return -1;
diff --git a/src/lxc/start.c b/src/lxc/start.c
index 2eb17d8..ccec9ef 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -597,6 +597,10 @@ static int do_start(void *data)
 		goto out_warn_father;
 	}
 
+	/* ask father to setup cgroups and wait for him to finish */
+	if (lxc_sync_barrier_parent(handler, LXC_SYNC_CGROUP))
+		return -1;
+
 	if (apparmor_load(handler) < 0)
 		goto out_warn_father;
 
@@ -630,6 +634,8 @@ static int do_start(void *data)
 	handler->ops->start(handler, handler->data);
 
 out_warn_father:
+	/* we want the parent to know something went wrong, so any
+	 * value other than what it expects is ok. */
 	lxc_sync_wake_parent(handler, LXC_SYNC_POST_CONFIGURE);
 	return -1;
 }
@@ -741,10 +747,26 @@ int lxc_spawn(struct lxc_handler *handler)
 		}
 	}
 
-	/* Tell the child to continue its initialization and wait for
-	 * it to exec or return an error
+	/* Tell the child to continue its initialization.  we'll get
+	 * LXC_SYNC_CGROUP when it is ready for us to setup cgroups
 	 */
 	if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CONFIGURE))
+		goto out_delete_net;
+
+	if (setup_cgroup(name, &handler->conf->cgroup)) {
+		ERROR("failed to setup the cgroups for '%s'", name);
+		goto out_delete_net;
+	}
+
+
+	/* Tell the child to complete its initialization and wait for
+	 * it to exec or return an error.  (the child will never
+	 * return LXC_SYNC_POST_CGROUP+1.  It will either close the
+	 * sync pipe, causign lxc_sync_barrier_child to return
+	 * success, or return a different value, causing us to error
+	 * out).
+	 */
+	if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CGROUP))
 		return -1;
 
 	if (detect_shared_rootfs())
diff --git a/src/lxc/sync.h b/src/lxc/sync.h
index a733d2e..fbf126e 100644
--- a/src/lxc/sync.h
+++ b/src/lxc/sync.h
@@ -28,6 +28,8 @@ struct lxc_handler;
 enum {
 	LXC_SYNC_CONFIGURE,
 	LXC_SYNC_POST_CONFIGURE,
+	LXC_SYNC_CGROUP,
+	LXC_SYNC_POST_CGROUP,
 	LXC_SYNC_RESTART,
 	LXC_SYNC_POST_RESTART,
 };
-- 
1.8.0





More information about the lxc-devel mailing list