[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[atomic-devel] [demo patch] Changing the host's mount namespace from a container



Currently Atomic doesn't include either the Gluster or Ceph client tools.  It's possible to use the "nsenter" and "mount" binaries together to run code on the host, like:

host$ sudo docker run --privileged -ti --pid=host --rm centos /bin/bash
container# nsenter --mount=/proc/1/ns/mnt -- mount
... print host mounts ..

But here we're running the *host's* /usr/sbin/mount. That makes it harder to run custom agents.

Here's a demo patch for util-linux's mount.c which shows how we can call setns() directly in the same binary before executing mount system calls, and affect the host (or in general, another mount namespace), while still operating after the dynamic linker has run, etc.

I patched util-linux and wrote a quick Dockerfile that pulls in a patched util-linux RPM:

FROM centos
ADD *.rpm /root/
RUN rpm -Fvh /root/*.rpm

host$ sudo docker build -t cgwalters/mount-on-host .
host$ docker run --privileged -ti --pid=host --rm cgwalters/centos-with-patched-mount /bin/bash
container# mount --in-ns-of /proc/1/ns/mnt
... print host mounts ...

I think tools like Ceph/Gluster that want to operate in a container would need to operate this way:
- Ensure that we have both --privileged and --pid=host, or -v /proc:/hostproc or similar
- Inside the code, before calling mount(), use setns() (if running in a container)
From 55f056993f8bec71b8a3e1d9b9139cd3a55a5a73 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters verbum org>
Date: Mon, 23 Feb 2015 15:02:48 -0500
Subject: [PATCH] mount: Add -P/--in-ns-of to perform operation in different
 namespace

For Project Atomic, a model that's being investigated is "super
privileged" containers that operate on the host - here, management
code lives in a container, but it affects the host.

This option makes it convenient for these containers to read/write the
host's mount table, distinct from the mount namespace in which they
run.
---
 sys-utils/mount.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/sys-utils/mount.c b/sys-utils/mount.c
index 1410985..1989e79 100644
--- a/sys-utils/mount.c
+++ b/sys-utils/mount.c
@@ -30,6 +30,7 @@
 #include <sys/stat.h>
 #include <stdarg.h>
 #include <libmount.h>
+#include <sched.h>
 #include <ctype.h>
 
 #include "nls.h"
@@ -52,6 +53,7 @@
  */
 
 static int readwrite;
+static char *in_ns_of;
 
 static int mk_exit_code(struct libmnt_context *cxt, int rc);
 
@@ -95,6 +97,18 @@ static void __attribute__((__noreturn__)) print_version(void)
 	exit(MOUNT_EX_SUCCESS);
 }
 
+/* Copied from sys-utils/nsenter.c */
+static void open_target_fd(int *fd, const char *path)
+{
+	if (*fd >= 0)
+		close(*fd);
+
+	*fd = open(path, O_RDONLY);
+	if (*fd < 0)
+		err(EXIT_FAILURE, _("cannot open %s"), path);
+}
+
+
 static int table_parser_errcb(struct libmnt_table *tb __attribute__((__unused__)),
 			const char *filename, int line)
 {
@@ -731,6 +745,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
 	fprintf(out, _(
 	" -h, --help              display this help text and exit\n"
 	" -i, --internal-only     don't call the mount.<type> helpers\n"
+	" -P, --in-ns-of <pid>    Perform the mount in the namespace of <pid>\n"
 	" -l, --show-labels       lists all mounts with LABELs\n"
 	" -n, --no-mtab           don't write to /etc/mtab\n"));
 	fprintf(out, _(
@@ -839,6 +854,7 @@ int main(int argc, char **argv)
 		{ "make-runbindable", 0, 0, MOUNT_OPT_RUNBINDABLE },
 		{ "no-canonicalize", 0, 0, 'c' },
 		{ "internal-only", 0, 0, 'i' },
+		{ "in-ns-of", 1, 0, 'P' },
 		{ "show-labels", 0, 0, 'l' },
 		{ "target", 1, 0, MOUNT_OPT_TARGET },
 		{ "source", 1, 0, MOUNT_OPT_SOURCE },
@@ -865,7 +881,7 @@ int main(int argc, char **argv)
 
 	mnt_context_set_tables_errcb(cxt, table_parser_errcb);
 
-	while ((c = getopt_long(argc, argv, "aBcfFhilL:Mno:O:rRsU:vVwt:T:",
+	while ((c = getopt_long(argc, argv, "aBcfFPhilL:Mno:O:rRsU:vVwt:T:",
 					longopts, NULL)) != -1) {
 
 		/* only few options are allowed for non-root users */
@@ -899,6 +915,9 @@ int main(int argc, char **argv)
 		case 'n':
 			mnt_context_disable_mtab(cxt, TRUE);
 			break;
+		case 'P':
+			in_ns_of = optarg;
+			break;
 		case 'r':
 			append_option(cxt, "ro");
 			readwrite = 0;
@@ -1011,6 +1030,16 @@ int main(int argc, char **argv)
 		mnt_table_set_cache(fstab, mnt_context_get_cache(cxt));
 	}
 
+	/* Enter the namespace now, so that print works */
+	if (in_ns_of) {
+		int targetfd = -1;
+		open_target_fd(&targetfd, in_ns_of);
+		if (setns(targetfd, CLONE_NEWNS))
+			err(EXIT_FAILURE,
+			    _("reassociate to namespace '%s' failed"),
+			    "ns/mnt");
+	}
+
 	if (!mnt_context_get_source(cxt) &&
 	    !mnt_context_get_target(cxt) &&
 	    !argc &&
-- 
1.8.3.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]