changeset 1675:435f91d71898

Merge unshare and nsenter (promoting and cleaning up nsenter). Needs more testing, don't have a test environment set up for this yet...
author Rob Landley <rob@landley.net>
date Sat, 07 Feb 2015 15:32:22 -0600
parents 39b5bc4e1853
children cbb1aca81eca
files toys/other/nsenter.c toys/other/unshare.c toys/pending/nsenter.c
diffstat 3 files changed, 116 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/nsenter.c	Sat Feb 07 15:32:22 2015 -0600
@@ -0,0 +1,116 @@
+/* nsenter.c - Enter existing namespaces
+ *
+ * Copyright 2014 andy Lutomirski <luto@amacapital.net>
+ *
+ * No standard
+ *
+ * unshare.c - run command in new context
+ *
+ * Copyright 2011 Rob Landley <rob@landley.net>
+ *
+ * No Standard
+ *
+
+// Note: flags go in same order (right to left) for shared subset
+USE_NSENTER(NEWTOY(nsenter, "<1F(no-fork)t#<1(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
+USE_UNSHARE(NEWTOY(unshare, "<1^imnpuU", TOYFLAG_USR|TOYFLAG_BIN))
+
+config UNSHARE
+  bool "unshare"
+  default y
+  depends on TOYBOX_CONTAINER
+  help
+    usage: unshare [-imnpuU] COMMAND...
+
+    Create new namespace(s) for this process and its children, so some
+    attribute is not shared with the parent process.  This is part of
+    Linux Containers.  Each process can have its own:
+
+    -i	SysV IPC (message queues, semaphores, shared memory)
+    -m	Mount/unmount tree
+    -n	Network address, sockets, routing, iptables
+    -p	Process IDs and init
+    -u	Host and domain names
+    -U	UIDs, GIDs, capabilities
+
+config NSENTER
+  bool "nsenter"
+  default n
+  help
+    usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...
+
+    Run COMMAND in a different set of namespaces.
+
+    -t  PID to take namespaces from    (--target)
+    -F  don't fork, even if -p is used (--no-fork)
+
+    The namespaces to switch are:
+
+    -i	SysV IPC: message queues, semaphores, shared memory (--ipc)
+    -m	Mount/unmount tree (--mnt)
+    -n	Network address, sockets, routing, iptables (--net)
+    -p	Process IDs and init, will fork unless -F is used (--pid)
+    -u	Host and domain names (--uts)
+    -U	UIDs, GIDs, capabilities (--user)
+
+    If -t isn't specified, each namespace argument must provide a path
+    to a namespace file, ala "-i=/proc/$PID/ns/ipc"
+*/
+
+#define FOR_nsenter
+#include "toys.h"
+#include <linux/sched.h>
+int unshare(int flags);
+int setns(int fd, int nstype); 
+
+GLOBALS(
+  char *nsnames[6];
+  long targetpid;
+)
+
+void unshare_main(void)
+{
+  unsigned flags[]={CLONE_NEWUSER, CLONE_NEWUTS, CLONE_NEWPID, CLONE_NEWNET,
+                    CLONE_NEWNS, CLONE_NEWIPC}, f = 0;
+  int i, fd;
+
+  // Create new namespace(s)?
+  if (CFG_UNSHARE && toys.which->name[0]) {
+    for (i = 0; i<ARRAY_LEN(flags); i++)
+      if (toys.optflags & (1<<i)) f |= flags[i];
+
+    if (unshare(f)) perror_exit(0);
+
+  // Bind to existing namespace(s)?
+  } else if (CFG_NSENTER) {
+    char *nsnames = "user\0uts\0pid\0net\0mnt\0ipc";
+
+    for (i = 0; i<ARRAY_LEN(flags); i++) {
+      char *filename = TT.nsnames[i];
+
+      if (toys.optflags & (1<<i)) {
+        if (!filename || !*filename) {
+          if (!(toys.optflags & FLAG_t)) error_exit("need -t or =filename");
+          sprintf(toybuf, "/proc/%ld/ns/%s", TT.targetpid, nsnames);
+          filename = toybuf;
+        }
+
+        if (setns(fd = xopen(filename, O_RDONLY), flags[i]))
+          perror_exit("setns");
+        close(fd);
+      }
+      nsnames += strlen(nsnames)+1;
+    }
+
+    if ((toys.optflags & FLAG_p) && !(toys.optflags & FLAG_F)) {
+      pid_t pid = xfork();
+
+      if (pid) {
+        while (waitpid(pid, 0, 0) == -1 && errno == EINTR);
+        return;
+      }
+    }
+  }
+
+  xexec_optargs(0);
+}
--- a/toys/other/unshare.c	Fri Feb 06 17:31:52 2015 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* unshare.c - run command in new context
- *
- * Copyright 2011 Rob Landley <rob@landley.net>
-
-USE_UNSHARE(NEWTOY(unshare, "<1^imnpuU", TOYFLAG_USR|TOYFLAG_BIN))
-
-config UNSHARE
-  bool "unshare"
-  default y
-  depends on TOYBOX_CONTAINER
-  help
-    usage: unshare [-imnpuU] COMMAND...
-
-    Create new namespace(s) for this process and its children, so some
-    attribute is not shared with the parent process.  This is part of
-    Linux Containers.  Each process can have its own:
-
-    -i	SysV IPC (message queues, semaphores, shared memory)
-    -m	Mount/unmount tree
-    -n	Network address, sockets, routing, iptables
-    -p	Process IDs and init
-    -u	Host and domain names
-    -U	UIDs, GIDs, capabilities
-*/
-
-#include "toys.h"
-#include <linux/sched.h>
-extern int unshare (int __flags);
-
-void unshare_main(void)
-{
-  unsigned flags[]={CLONE_NEWUSER, CLONE_NEWUTS, CLONE_NEWPID, CLONE_NEWNET,
-                    CLONE_NEWNS, CLONE_NEWIPC, 0};
-  unsigned f=0;
-  int i;
-
-  for (i=0; flags[i]; i++) if (toys.optflags & (1<<i)) f |= flags[i];
-
-  if (unshare(f)) perror_exit("failed");
-
-  xexec_optargs(0);
-}
--- a/toys/pending/nsenter.c	Fri Feb 06 17:31:52 2015 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/* nsenter.c - Enter existing namespaces
- *
- * Copyright 2014 andy Lutomirski <luto@amacapital.net>
-
-USE_NSENTER(NEWTOY(nsenter, "<1F(no-fork)t#(target)i:(ipc);m:(mount);n:(net);p:(pid);u:(uts);U:(user);", TOYFLAG_USR|TOYFLAG_BIN))
-
-config NSENTER
-  bool "nsenter"
-  default n
-  help
-    usage: nsenter [-t pid] [-F] [-i] [-m] [-n] [-p] [-u] [-U] COMMAND...
-
-    Run COMMAND in a different set of namespaces.
-
-    -T  PID to take namespaces from
-    -F  don't fork, even if -p is set
-
-    The namespaces to switch are:
-
-    -i	SysV IPC (message queues, semaphores, shared memory)
-    -m	Mount/unmount tree
-    -n	Network address, sockets, routing, iptables
-    -p	Process IDs and init (will fork unless -F is used)
-    -u	Host and domain names
-    -U	UIDs, GIDs, capabilities
-
-    Each of those options takes an optional argument giving the path of
-    the namespace file (usually in /proc).  This optional argument is
-    mandatory unless -t is used.
-*/
-
-#define FOR_nsenter
-#define _GNU_SOURCE
-#include "toys.h"
-#include <errno.h>
-#include <sched.h>
-#include <linux/sched.h>
-
-#define NUM_NSTYPES 6
-
-struct nstype {
-  int type;
-  const char *name;
-};
-
-struct nstype nstypes[NUM_NSTYPES] = {
-  {CLONE_NEWUSER, "user"}, /* must be first to allow non-root operation */
-  {CLONE_NEWUTS,  "uts"},
-  {CLONE_NEWPID,  "pid"},
-  {CLONE_NEWNET,  "net"},
-  {CLONE_NEWNS,   "mnt"},
-  {CLONE_NEWIPC,  "ipc"},
-};
-
-GLOBALS(
-  char *nsnames[6];
-  long targetpid;
-)
-
-static void enter_by_name(int idx)
-{
-  int fd, rc;
-  char buf[64];
-  char *filename = TT.nsnames[idx];
-
-  if (!(toys.optflags & (1<<idx))) return;
-
-  if (!filename || !*filename) {
-    if (!(toys.optflags & (1<<NUM_NSTYPES)))
-      error_exit("either -t or an ns filename is required");
-    sprintf(buf, "/proc/%ld/ns/%s", TT.targetpid, nstypes[idx].name);
-    filename = buf;
-  }
-
-  fd = open(filename, O_RDONLY | O_CLOEXEC);
-  if (fd == -1) perror_exit(filename);
-
-  rc = setns(fd, nstypes[idx].type);
-  if (CFG_TOYBOX_FREE) close(fd);
-  if (rc != 0) perror_exit("setns");
-}
-
-void nsenter_main(void)
-{
-  int i;
-
-  for (i = 0; i < NUM_NSTYPES; i++)
-    enter_by_name(i);
-
-  if ((toys.optflags & (1<<2)) && !(toys.optflags & 1<<(NUM_NSTYPES+1))) {
-    /* changed PID ns and --no-fork wasn't set, so fork. */
-    pid_t pid = fork();
-
-    if (pid == -1) {
-      perror_exit("fork");
-    } else if (pid != 0) {
-      while (waitpid(pid, 0, 0) == -1 && errno == EINTR)
-        ;
-      return;
-    }
-  }
-
-  xexec_optargs(0);
-}