[lxc-devel] [lxc/master] attach: handle namespace inheritance
brauner on Github
lxc-bot at linuxcontainers.org
Wed Nov 1 09:47:06 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 673 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171101/d605edd4/attachment.bin>
-------------- next part --------------
From 683a9ee930a283d0a73869909ec719fe589ccfe9 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 1 Nov 2017 10:44:18 +0100
Subject: [PATCH] attach: handle namespace inheritance
We need to have lxc_attach() distinguish between a caller specifying specific
namespaces to attach to and a caller not requesting specific namespaces. The
latter is taken by lxc_attach() to mean that all namespaces will be attached.
This also needs to include all inherited namespaces.
Closes #1890.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/attach.c | 84 +++++++++++++++++++++++++++++++++-----------------------
src/lxc/attach.h | 6 ++++
2 files changed, 56 insertions(+), 34 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 5a42cc29e..6d36d9b69 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -300,10 +300,11 @@ static int in_same_namespace(pid_t pid1, pid_t pid2, const char *ns)
return ret;
}
-static int lxc_attach_to_ns(pid_t pid, int which)
+static int lxc_attach_to_ns(pid_t pid, int which, bool attach_all_namespaces)
{
int fd[LXC_NS_MAX];
int i, j, ret, saved_errno;
+ pid_t self;
ret = access("/proc/self/ns", X_OK);
if (ret) {
@@ -311,48 +312,55 @@ static int lxc_attach_to_ns(pid_t pid, int which)
return -1;
}
+ self = getpid();
for (i = 0; i < LXC_NS_MAX; i++) {
- fd[i] = -EINVAL;
-
- /* Ignore if we are not supposed to attach to that namespace. */
- if (which != -1 && !(which & ns_info[i].clone_flag)) {
- /* We likely inherited the namespace from someone. We
- * need to check whether we are already in the same
- * namespace. If we are then there's nothing for us to
- * do. If we are not then we need to attach to it.
- */
- fd[i] = in_same_namespace(getpid(), pid, ns_info[i].proc_name);
- /* we are in the same namespace */
- if (fd[i] == -EINVAL) {
- DEBUG("Inheriting %s namespace from %d",
- ns_info[i].proc_name, pid);
- continue;
- }
- }
+ /* Ignore if we are not supposed to attach to that namespace and
+ * if the caller did specify specific namespaces to attach to.
+ */
+ fd[i] = -1;
+ if (which != -1 && !(which & ns_info[i].clone_flag) &&
+ !attach_all_namespaces)
+ continue;
- if (fd[i] == -EINVAL)
+ /* If the container was clone()ed with that flag there's likely
+ * no need to check if we are in the same namespace so simply
+ * preserve the namespace.
+ */
+ if ((which & ns_info[i].clone_flag))
fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
- if (fd[i] < 0) {
- saved_errno = errno;
-
- /* Close all already opened file descriptors before we
- * return an error, so we don't leak them.
- */
- for (j = 0; j < i; j++)
- close(fd[j]);
+ else
+ fd[i] = in_same_namespace(self, pid, ns_info[i].proc_name);
+ if (fd[i] >= 0)
+ continue;
- errno = saved_errno;
- SYSERROR("Failed to attach to %s namespace of %d",
- ns_info[i].proc_name, pid);
- return -1;
+ /* This is the caller's own namespaces. */
+ if (fd[i] == -EINVAL) {
+ DEBUG("Inheriting %s namespace from %d",
+ ns_info[i].proc_name, pid);
+ continue;
}
+
+ /* We failed to preserve the namespace. */
+ saved_errno = errno;
+
+ /* Close all already opened file descriptors before we
+ * return an error, so we don't leak them.
+ */
+ for (j = 0; j < i; j++)
+ close(fd[j]);
+
+ errno = saved_errno;
+ SYSERROR("Failed to attach to %s namespace of %d",
+ ns_info[i].proc_name, pid);
+ return -1;
}
for (i = 0; i < LXC_NS_MAX; i++) {
if (fd[i] < 0)
continue;
- if (setns(fd[i], 0) < 0) {
+ ret = setns(fd[i], ns_info[i].clone_flag);
+ if (ret < 0) {
saved_errno = errno;
for (j = i; j < LXC_NS_MAX; j++)
@@ -365,7 +373,6 @@ static int lxc_attach_to_ns(pid_t pid, int which)
}
DEBUG("Attached to %s namespace of %d", ns_info[i].proc_name, pid);
-
close(fd[i]);
}
@@ -889,6 +896,7 @@ int lxc_attach(const char *name, const char *lxcpath,
/* Determine which namespaces the container was created with
* by asking lxc-start, if necessary.
*/
+ init_ctx->attach_all_namespaces = false;
if (options->namespaces == -1) {
options->namespaces = lxc_cmd_get_clone_flags(name, lxcpath);
/* call failed */
@@ -899,6 +907,13 @@ int lxc_attach(const char *name, const char *lxcpath,
lxc_proc_put_context_info(init_ctx);
return -1;
}
+
+ /* In case callers didn't specify specific namespaces to attach
+ * to we retrieve the flags the container was clone()ed.
+ * However, these flags do not include inherited namespaces. But
+ * we need to attach to those to.
+ */
+ init_ctx->attach_all_namespaces = true;
}
/* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order
@@ -1134,7 +1149,8 @@ int lxc_attach(const char *name, const char *lxcpath,
/* Attach now, create another subprocess later, since pid namespaces
* only really affect the children of the current process.
*/
- ret = lxc_attach_to_ns(init_pid, options->namespaces);
+ ret = lxc_attach_to_ns(init_pid, options->namespaces,
+ init_ctx->attach_all_namespaces);
if (ret < 0) {
ERROR("Failed to enter namespaces.");
shutdown(ipc_sockets[1], SHUT_RDWR);
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
index fb6bc5a07..4256fb1e2 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -24,6 +24,7 @@
#ifndef __LXC_ATTACH_H
#define __LXC_ATTACH_H
+#include <stdbool.h>
#include <lxc/attach_options.h>
#include <sys/types.h>
@@ -34,6 +35,11 @@ struct lxc_proc_context_info {
struct lxc_container *container;
signed long personality;
unsigned long long capability_mask;
+
+ /* Indicator whether we are supposed to attach to all
+ * namespaces of the container.
+ */
+ bool attach_all_namespaces;
};
extern int lxc_attach(const char *name, const char *lxcpath,
More information about the lxc-devel
mailing list