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@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
- 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;
if (setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) {
ERROR("failed to setup the console for '%s'", name);
return -1;
+ /* 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;
if (apparmor_load(handler) < 0)
goto out_warn_father;
handler->ops->start(handler, handler->data);
out_warn_father:
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;
}
lxc_sync_wake_parent(handler, LXC_SYNC_POST_CONFIGURE);
return -1;
}
- /* 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))
*/
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, causing 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())
return -1;
if (detect_shared_rootfs())
enum {
LXC_SYNC_CONFIGURE,
LXC_SYNC_POST_CONFIGURE,
enum {
LXC_SYNC_CONFIGURE,
LXC_SYNC_POST_CONFIGURE,
+ LXC_SYNC_CGROUP,
+ LXC_SYNC_POST_CGROUP,
LXC_SYNC_RESTART,
LXC_SYNC_POST_RESTART,
};
LXC_SYNC_RESTART,
LXC_SYNC_POST_RESTART,
};