]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
unshare: add --mount-proc for pid namespaces
authorKarel Zak <kzak@redhat.com>
Wed, 3 Jul 2013 10:28:16 +0000 (12:28 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 9 Jul 2013 09:02:48 +0000 (11:02 +0200)
Based on patch from Mike Frysinger <vapier@gentoo.org>.

Mike Frysinger wrote:
 When it comes to pid namespaces, it's also useful for /proc to reflect
 the current namespace.  Again, this is easy to pull off, but annoying
 to force everyone to do it themselves.  So let's add a --mount-proc to
 do the magic for us.  The downside is that this also implies creating
 a mount namespace as mounting the new pid namespace /proc over top the
 system one will quickly break all other processes on the system.

Signed-off-by: Karel Zak <kzak@redhat.com>
Acked-by: Mike Frysinger <vapier@gentoo.or>
sys-utils/unshare.1
sys-utils/unshare.c

index c387cebfd01edc3a7ca98b2e4b6771c58c29bd62..dfd418919a85e061a2e57696811ee4c70812e3ad 100644 (file)
@@ -56,7 +56,7 @@ Unshare the mount namespace.
 Unshare the network namespace.
 .TP
 .BR \-p , " \-\-pid"
-Unshare the pid namespace. See also \fB--fork\fP option.
+Unshare the pid namespace. See also \fB--fork\fP and \fB--mount-proc\fP options.
 .TP
 .BR \-u , " \-\-uts"
 Unshare the UTS namespace.
@@ -67,6 +67,12 @@ Unshare the user namespace.
 .BR \-f , " \-\-fork"
 Fork the specified process as a child of unshare rather than running it
 directly.  This is useful when creating a new pid namespace.
+.TP
+.BR "\fB\-\-mount-proc\fR [=\fImountpoint\fP]"
+Just before running the program, mount the proc filesystem at the \fImountpoint\fP
+(default is /proc).  This is useful when creating a new pid namespace.  It also
+implies creating a new mount namespace since the /proc mount would otherwise
+mess up existing programs on the system.
 .SH SEE ALSO
 .BR unshare (2),
 .BR clone (2)
index a889eee9f944c3f9598b6320ced5407d479c6262..a64b776e807b42e37af89a85e0c034f8cb749de7 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/wait.h>
+#include <sys/mount.h>
 
 #include "nls.h"
 #include "c.h"
@@ -41,13 +42,14 @@ static void usage(int status)
              _(" %s [options] <program> [args...]\n"), program_invocation_short_name);
 
        fputs(USAGE_OPTIONS, out);
-       fputs(_(" -m, --mount       unshare mounts namespace\n"), out);
-       fputs(_(" -u, --uts         unshare UTS namespace (hostname etc)\n"), out);
-       fputs(_(" -i, --ipc         unshare System V IPC namespace\n"), out);
-       fputs(_(" -n, --net         unshare network namespace\n"), out);
-       fputs(_(" -p, --pid         unshare pid namespace\n"), out);
-       fputs(_(" -U, --user        unshare user namespace\n"), out);
-       fputs(_(" -f, --fork        fork before launching <program>\n"), out);
+       fputs(_(" -m, --mount               unshare mounts namespace\n"), out);
+       fputs(_(" -u, --uts                 unshare UTS namespace (hostname etc)\n"), out);
+       fputs(_(" -i, --ipc                 unshare System V IPC namespace\n"), out);
+       fputs(_(" -n, --net                 unshare network namespace\n"), out);
+       fputs(_(" -p, --pid                 unshare pid namespace\n"), out);
+       fputs(_(" -U, --user                unshare user namespace\n"), out);
+       fputs(_(" -f, --fork                fork before launching <program>\n"), out);
+       fputs(_("     --mount-proc[=<dir>]  mount proc filesystem first (implies --mount)\n"), out);
 
        fputs(USAGE_SEPARATOR, out);
        fputs(USAGE_HELP, out);
@@ -59,6 +61,9 @@ static void usage(int status)
 
 int main(int argc, char *argv[])
 {
+       enum {
+               OPT_MOUNTPROC = CHAR_MAX + 1
+       };
        static const struct option longopts[] = {
                { "help", no_argument, 0, 'h' },
                { "version", no_argument, 0, 'V'},
@@ -69,11 +74,13 @@ int main(int argc, char *argv[])
                { "pid", no_argument, 0, 'p' },
                { "user", no_argument, 0, 'U' },
                { "fork", no_argument, 0, 'f' },
+               { "mount-proc", optional_argument, 0, OPT_MOUNTPROC },
                { NULL, 0, 0, 0 }
        };
 
        int unshare_flags = 0;
        int c, forkit = 0;
+       const char *procmnt = NULL;
 
        setlocale(LC_MESSAGES, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
@@ -108,6 +115,10 @@ int main(int argc, char *argv[])
                case 'U':
                        unshare_flags |= CLONE_NEWUSER;
                        break;
+               case OPT_MOUNTPROC:
+                       unshare_flags |= CLONE_NEWNS;
+                       procmnt = optarg ? optarg : "/proc";
+                       break;
                default:
                        usage(EXIT_FAILURE);
                }
@@ -136,6 +147,11 @@ int main(int argc, char *argv[])
                }
        }
 
+       if (procmnt &&
+           (mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0 ||
+            mount("proc", procmnt, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0))
+                       err(EXIT_FAILURE, _("mount %s failed"), procmnt);
+
        if (optind < argc) {
                execvp(argv[optind], argv + optind);
                err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]);