From 5b1e83cbc498cd3edeaf13afa987d530299a35a7 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Mon, 9 May 2016 15:30:46 -0500 Subject: [PATCH] Unshare netns after setting the userns mappings so that there is a root uid mapping for the /proc/net files. Signed-off-by: Serge Hallyn --- src/lxc/start.c | 48 ++++++++++++++++++++++++++++++++++++------------ src/lxc/sync.c | 5 +++++ src/lxc/sync.h | 2 ++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index d9d5814b5..54372066b 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -736,6 +736,20 @@ static int do_start(void *data) close(handler->pinfd); } + if (lxc_sync_wait_parent(handler, LXC_SYNC_STARTUP)) + return -1; + + /* Unshare CLONE_NEWNET after CLONE_NEWUSER - see + https://github.com/lxc/lxd/issues/1978 */ + if ((handler->clone_flags & (CLONE_NEWNET | CLONE_NEWUSER)) == + (CLONE_NEWNET | CLONE_NEWUSER)) { + ret = unshare(CLONE_NEWNET); + if (ret < 0) { + SYSERROR("Error unsharing network namespace"); + goto out_warn_father; + } + } + /* Tell the parent task it can begin to configure the * container and wait for it to finish */ @@ -1027,7 +1041,7 @@ static int lxc_spawn(struct lxc_handler *handler) char *errmsg = NULL; bool cgroups_connected = false; int saved_ns_fd[LXC_NS_MAX]; - int preserve_mask = 0, i; + int preserve_mask = 0, i, flags; int netpipepair[2], nveths; netpipe = -1; @@ -1118,6 +1132,9 @@ static int lxc_spawn(struct lxc_handler *handler) } /* Create a process in a new set of namespaces */ + flags = handler->clone_flags; + if (handler->clone_flags & CLONE_NEWUSER) + flags &= ~CLONE_NEWNET; handler->pid = lxc_clone(do_start, handler, handler->clone_flags); if (handler->pid < 0) { SYSERROR("failed to fork into a new namespace"); @@ -1135,8 +1152,25 @@ static int lxc_spawn(struct lxc_handler *handler) lxc_sync_fini_child(handler); - if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) + /* map the container uids - the container became an invalid + * userid the moment it was cloned with CLONE_NEWUSER - this + * call doesn't change anything immediately, but allows the + * container to setuid(0) (0 being mapped to something else on + * the host) later to become a valid uid again */ + if (lxc_map_ids(&handler->conf->id_map, handler->pid)) { + ERROR("failed to set up id mapping"); + goto out_delete_net; + } + + if (lxc_sync_wake_child(handler, LXC_SYNC_STARTUP)) { failed_before_rename = 1; + goto out_delete_net; + } + + if (lxc_sync_wait_child(handler, LXC_SYNC_CONFIGURE)) { + failed_before_rename = 1; + goto out_delete_net; + } if (!cgroup_create_legacy(handler)) { ERROR("failed to setup the legacy cgroups for %s", name); @@ -1182,16 +1216,6 @@ static int lxc_spawn(struct lxc_handler *handler) close(netpipepair[1]); } - /* map the container uids - the container became an invalid - * userid the moment it was cloned with CLONE_NEWUSER - this - * call doesn't change anything immediately, but allows the - * container to setuid(0) (0 being mapped to something else on - * the host) later to become a valid uid again */ - if (lxc_map_ids(&handler->conf->id_map, handler->pid)) { - ERROR("failed to set up id mapping"); - goto out_delete_net; - } - /* Tell the child to continue its initialization. we'll get * LXC_SYNC_CGROUP when it is ready for us to setup cgroups */ diff --git a/src/lxc/sync.c b/src/lxc/sync.c index c9fbcd934..7f23622eb 100644 --- a/src/lxc/sync.c +++ b/src/lxc/sync.c @@ -99,6 +99,11 @@ int lxc_sync_wake_parent(struct lxc_handler *handler, int sequence) return __sync_wake(handler->sv[0], sequence); } +int lxc_sync_wait_parent(struct lxc_handler *handler, int sequence) +{ + return __sync_wait(handler->sv[0], sequence); +} + int lxc_sync_wait_child(struct lxc_handler *handler, int sequence) { return __sync_wait(handler->sv[1], sequence); diff --git a/src/lxc/sync.h b/src/lxc/sync.h index d0aee6fe9..12a8b9592 100644 --- a/src/lxc/sync.h +++ b/src/lxc/sync.h @@ -26,6 +26,7 @@ struct lxc_handler; enum { + LXC_SYNC_STARTUP, LXC_SYNC_CONFIGURE, LXC_SYNC_POST_CONFIGURE, LXC_SYNC_CGROUP, @@ -42,6 +43,7 @@ void lxc_sync_fini_child(struct lxc_handler *); int lxc_sync_wake_child(struct lxc_handler *, int); int lxc_sync_wait_child(struct lxc_handler *, int); int lxc_sync_wake_parent(struct lxc_handler *, int); +int lxc_sync_wait_parent(struct lxc_handler *, int); int lxc_sync_barrier_parent(struct lxc_handler *, int); int lxc_sync_barrier_child(struct lxc_handler *, int); -- 2.47.2