Re: [PATCH] sys-tools: Add setns utility to sys-tools

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

 



On Wed, Dec 19, 2012 at 9:01 PM, Neil Horman <nhorman@xxxxxxxxxxxxx> wrote:
>>>On 2012-12-19 21:06, Neil Horman wrote:
>>> ...
>>> +.BR \-u\ <pid> , " \-\-uts=<pid>"
>>> +Migrate to the uts namespace of <pid>
>>> +.TP
>>> +.BR \-i\ <pid> , " \-\-ipc=<pid>"
>>> +Migrate to the ipc namespace of <pid>
>>> +.TP
>>> +.BR \-n\ <pid> , " \-\-net\<pid>"
>>> +Migrate to the net namespace of <pid>
>>
>>Wouldn't it be more useful to accept an arbitrary path, and just hand it
>>to setns(2)? That way, the utility would automatically gain support for
>>new namespace types (for example `setns /proc/$pid/ns/mount`), and would
>>allow joining namespaces that are linked outside /proc.
>>
>>For example, I seem to remember someone saying that `mount --bind
>>/proc/$pid/ns/net /tmp/foo-namespace` can be used to make that
>>particular namespace persist even after the process quits. Then `setns
>>/tmp/foo-namespace someprogram` could be used to join that namespace again.
>
> Yeah, that makes sense, I'll respin this tomorrow, and repost.  I'm also going
> to batch the namespace switches, by opening all the file descriptors first, then
> calling setns on them.  It was pointed out to me by doing them one by one like
> this, if you setns the mount namespace you might loose access to the paths that
> were specified.

Hi Neil, and others,

I reviewed patch, and altered it to match with util-linux
Documentation/howto-* stuff. While doing that I notice two bugs. Short
option made cores to be dropped, as the long option index was zero.
The command also tried to parse options of command it later executed.
Short option string got + character to fix that. I also included man
page to be part of distribution package.

p.s. See attachent for the modified patch. I know I should in-line it,
but the gmail is not making it easy.

-- 
   Sami Kerola
   http://www.iki.fi/kerolasa/
From 632c7e16a199c053f94709ab5e00d3531b86e081 Mon Sep 17 00:00:00 2001
From: Neil Horman <nhorman@xxxxxxxxxxxxx>
Date: Wed, 19 Dec 2012 14:06:46 -0500
Subject: [PATCH] setns: add new command
Organization: Lastminute.com

Like the unshare command, which lets a user from the command line detach
from specific namespaces of the parent process, and execute a command,
setns provides a frontend to the setns(2) syscall, which allows a user to
migrate a process to the namespaces of other processes, prior to calling
exec on a command.

CC: Karel Zak <kzak@xxxxxxxxxx>
Reviewed-by: Sami Kerola <kerolasa@xxxxxx>
Signed-off-by: Neil Horman <nhorman@xxxxxxxxxxxxx>
---
 .gitignore              |   1 +
 configure.ac            |  11 +++++
 sys-utils/Makemodule.am |   7 +++
 sys-utils/setns.1       |  51 +++++++++++++++++++
 sys-utils/setns.c       | 127 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 197 insertions(+)
 create mode 100644 sys-utils/setns.1
 create mode 100644 sys-utils/setns.c

diff --git a/.gitignore b/.gitignore
index e85eb07..63f77c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -146,6 +146,7 @@ tests/run.sh.trs
 /script
 /scriptreplay
 /setarch
+/setns
 /setsid
 /setterm
 /sfdisk
diff --git a/configure.ac b/configure.ac
index 9c08fc0..829594d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -862,6 +862,17 @@ if test "x$build_unshare" = xyes; then
   AC_CHECK_FUNCS([unshare])
 fi
 
+AC_ARG_ENABLE([setns],
+  AS_HELP_STRING([--disable-setns], [do not build setns]),
+  [], enable_unshare=check
+)
+UL_BUILD_INIT([setns])
+UL_REQUIRES_LINUX([setns])
+UL_REQUIRES_SYSCALL_CHECK([setns], [UL_CHECK_SYSCALL([setns])])
+AM_CONDITIONAL(BUILD_SETNS, test "x$build_setns" = xyes)
+if test "x$build_setns" = xyes; then
+  AC_CHECK_FUNCS([setns])
+fi
 
 AC_ARG_ENABLE([arch],
   AS_HELP_STRING([--enable-arch], [do build arch]),
diff --git a/sys-utils/Makemodule.am b/sys-utils/Makemodule.am
index 33112fb..e517c93 100644
--- a/sys-utils/Makemodule.am
+++ b/sys-utils/Makemodule.am
@@ -283,6 +283,13 @@ dist_man_MANS += sys-utils/switch_root.8
 switch_root_SOURCES = sys-utils/switch_root.c
 endif
 
+if BUILD_SETNS
+usrbin_exec_PROGRAMS += setns
+setns_SOURCES = sys-utils/setns.c
+setns_LDADD = $(LDADD) libcommon.la
+dist_man_MANS += sys-utils/setns.1
+endif
+
 if BUILD_UNSHARE
 usrbin_exec_PROGRAMS += unshare
 dist_man_MANS += sys-utils/unshare.1
diff --git a/sys-utils/setns.1 b/sys-utils/setns.1
new file mode 100644
index 0000000..7e492ff
--- /dev/null
+++ b/sys-utils/setns.1
@@ -0,0 +1,51 @@
+.TH SETNS 1 "December 2012" "util-linux" "User Commands"
+.SH NAME
+setns \- run program with namespaces of another process
+.SH SYNOPSIS
+.B setns
+.RI [ options ]
+program
+.RI [ arguments ]
+.SH DESCRIPTION
+Migrates to the namespaces of the specified pid/\:namespace pairs, and executes
+a child process.
+.SH OPTIONS
+.TP
+\fB\-u\fR, \fB\-\-uts\fR \fIpid\fR
+Migrate to the
+.B uts
+namespace of
+.IR pid .
+.TP
+\fB\-i\fR, \fB\-\-ipc\fR \fIpid\fR
+Migrate to the
+.B ipc
+namespace of
+.IR pid .
+.TP
+\fB\-n\fR, \fB\-\-net\fR \fIpid\fR
+Migrate to the
+.B net
+namespace of
+.IR pid .
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Display version information and exit.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display help and exit.
+.SH SEE ALSO
+.BR unshare (2),
+.BR setns (2),
+.BR clone (2),
+.UR http://lwn.net\:/Articles\:/407495/
+.UE
+.SH AUTHOR
+.MT nhorman@xxxxxxxxxxxxx
+Neil Horman
+.ME
+.SH AVAILABILITY
+The setns command is part of the util-linux package and is available from
+.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+Linux Kernel Archive
+.UE .
diff --git a/sys-utils/setns.c b/sys-utils/setns.c
new file mode 100644
index 0000000..8ac9309
--- /dev/null
+++ b/sys-utils/setns.c
@@ -0,0 +1,127 @@
+/*
+ * setns - command-line interface for setns(2)
+ *
+ * Copyright (C) 2012 Neil Horman <nhorman@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sched.h>
+
+#include "nls.h"
+#include "c.h"
+#include "strutils.h"
+#include "xalloc.h"
+
+static void __attribute__((__noreturn__)) usage(FILE *out)
+{
+	fputs(USAGE_HEADER, out);
+	fprintf(out, " %s [options] [command]\n", program_invocation_short_name);
+	fputs(USAGE_OPTIONS, out);
+	fputs(_(" -i, --ipc <pid>   migrate to the ipc namespace\n"), out);
+	fputs(_(" -n, --net <pid>   migrate to the net namespace\n"), out);
+	fputs(_(" -u, --uts <pid>   migrate to the uts namespace\n"), out);
+	fputs(USAGE_SEPARATOR, out);
+	fputs(USAGE_HELP, out);
+	fputs(USAGE_VERSION, out);
+	fprintf(out, USAGE_MAN_TAIL("setns(1)"));
+	exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+static void switch_namespace(const char *name, unsigned long pid)
+{
+	int fd;
+	char *path;
+
+	xasprintf(&path, "/proc/%lu/ns/%s", pid, name);
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		err(EXIT_FAILURE, _("cannot open %s"), path);
+
+	if (setns(fd, 0) < 0)
+		err(EXIT_FAILURE, _("setns failed for %s on pid %lu"), name, pid);
+}
+
+int main(int argc, char **argv)
+{
+	int opt;
+	int execind = argc + 1;
+	unsigned long pid;
+	const char *target;
+
+	static const struct option lopts[] = {
+		{"help", no_argument, NULL, 'h'},
+		{"version", no_argument, NULL, 'V'},
+		{"ipc", required_argument, NULL, 'i'},
+		{"net", required_argument, NULL, 'n'},
+		{"uts", required_argument, NULL, 'u'},
+		{NULL, 0, NULL, 0}
+	};
+	enum {
+		SETNS_IPC = 0,
+		SETNS_NET,
+		SETNS_UTS
+	};
+	const char *setns_types[] = {
+		[SETNS_IPC] = "ipc",
+		[SETNS_NET] = "net",
+		[SETNS_UTS] = "uts"
+	};
+
+	while ((opt = getopt_long(argc, argv,
+				  "+hVi:n:u:", lopts, NULL)) != -1) {
+		switch (opt) {
+		case 'h':
+			usage(stdout);
+		case 'V':
+			printf(UTIL_LINUX_VERSION);
+			return EXIT_SUCCESS;
+		case 'i':
+			target = setns_types[SETNS_IPC];
+			goto parse_opt;
+		case 'n':
+			target = setns_types[SETNS_NET];
+			goto parse_opt;
+		case 'u':
+			target = setns_types[SETNS_UTS];
+ parse_opt:
+			pid = strtoul_or_err(optarg,
+					     _("failed to parse argument"));
+			switch_namespace(target, pid);
+			break;
+		default:
+			usage(stderr);
+		}
+	}
+
+	if (optind == argc)
+		errx(EXIT_FAILURE, _("no executable specified"));
+
+	execind = optind;
+
+	if (execvp(argv[execind], &argv[execind]) < 0)
+		err(EXIT_FAILURE, _("executing %s failed"), argv[execind]);
+
+	return EXIT_SUCCESS;
+}
-- 
1.8.0.2


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux