unshare: new command

New utility allows to run process with separate mount, UTC, IPC or
network namespaces.

[kzak@redhat.com: - some cosmetic changes in usage() and err() usage
                  - move "if BUILD_UNSHARE" to separate place in Makefile.am
                  - add unshare to .gitignore]

Signed-off-by: Mikhail Gusarov <dottedmag@dottedmag.net>
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Mikhail Gusarov 2009-10-04 02:42:08 +07:00 committed by Karel Zak
parent 4629c03d34
commit 4205f1fda1
6 changed files with 201 additions and 4 deletions

4
TODO
View File

@ -41,10 +41,6 @@ fdisk(s)
misc misc
---- ----
* add a new command (unshare, clone, or so...) with all kinds of
clone(2) options.
http://thread.gmane.org/gmane.linux.utilities.util-linux-ng/2178
* add to lib/blkdev.c code for /proc/partitions parsing -- unfortunate we * add to lib/blkdev.c code for /proc/partitions parsing -- unfortunate we
duplicate this code in many places. The parser has to support unlimited duplicate this code in many places. The parser has to support unlimited
size (or 4096 bytes) of partition name. size (or 4096 bytes) of partition name.

View File

@ -372,6 +372,20 @@ AM_CONDITIONAL(HAVE_BLKID, test "x$have_blkid" = xyes)
AC_ARG_VAR([BLKID_LIBS_STATIC], [-l options for linking statically with blkid]) AC_ARG_VAR([BLKID_LIBS_STATIC], [-l options for linking statically with blkid])
AC_ARG_ENABLE([unshare],
AS_HELP_STRING([--disable-unshare], [do not build unshare]),
[], enable_unshare=check
)
build_unshare=yes
if test "x$enable_unshare" = xcheck; then
if test "x$linux_os" = xno; then
AC_MSG_WARN([non-linux system; do not build unshare])
build_unshare=no
fi
elif test "x$enable_unshare" = xno; then
build_unshare=no
fi
AM_CONDITIONAL(BUILD_UNSHARE, test "x$build_unshare" = xyes)
UTIL_CHECK_LIB(util, openpty) UTIL_CHECK_LIB(util, openpty)
UTIL_CHECK_LIB(termcap, tgetnum) UTIL_CHECK_LIB(termcap, tgetnum)
@ -563,6 +577,10 @@ dnl fallocate could be available as libc function or as syscall only
UTIL_CHECK_SYSCALL([fallocate]) UTIL_CHECK_SYSCALL([fallocate])
AC_CHECK_FUNCS([fallocate]) AC_CHECK_FUNCS([fallocate])
dnl unshare could be available as libc function or as syscall only
UTIL_CHECK_SYSCALL([unshare])
AC_CHECK_FUNCS([unshare])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>

View File

@ -39,5 +39,6 @@ sparc64.8
sparc.8 sparc.8
switch_root switch_root
tunelp tunelp
unshare
vidmode.8 vidmode.8
x86_64.8 x86_64.8

View File

@ -38,6 +38,11 @@ sbin_PROGRAMS += switch_root
dist_man_MANS += switch_root.8 dist_man_MANS += switch_root.8
endif endif
if BUILD_UNSHARE
usrbin_exec_PROGRAMS += unshare
dist_man_MANS += unshare.1
endif
if BUILD_ARCH if BUILD_ARCH
bin_PROGRAMS += arch bin_PROGRAMS += arch
dist_man_MANS += arch.1 dist_man_MANS += arch.1

58
sys-utils/unshare.1 Normal file
View File

@ -0,0 +1,58 @@
.\" Process this file with
.\" groff -man -Tascii lscpu.1
.\"
.TH UNSHARE 1 "OCTOBER 2008" Linux "User Manuals"
.SH NAME
unshare \- run program with some namespaces unshared from parent
.SH SYNOPSIS
.B unshare
.RI [ options ]
program
.RI [ arguments ]
.SH DESCRIPTION
Unshares specified namespaces from parent process and then executes specified
program. Unshareable namespaces are:
.TP
.BR "mount namespace"
mounting and unmounting filesystems will not affect rest of the system
(\fBCLONE_NEWNS\fP flag),
.TP
.BR "UTS namespace"
setting hostname, domainname will not affect rest of the system
(\fBCLONE_NEWUTS\fP flag),
.TP
.BR "IPC namespace"
process will have indpendent namespace for System V message queues, semaphore
sets and shared memory segments (\fBCLONE_NEWIPC\fP flag),
.TP
.BR "network namespace"
process will have independent IPv4 and IPv6 stacks, IP routing tables, firewall
rules, the \fI/proc/net\fP and \fI/sys/class/net\fP directory trees, sockets
etc. (\fBCLONE_NEWNET\fP flag).
.TP
See the clone(2) for exact semantics of the flags.
.SH OPTIONS
.TP
.BR \-h , " \-\-help"
Print a help message,
.TP
.BR \-m , " \-\-mount"
Unshare the mount namespace,
.TP
.BR \-u , " \-\-uts"
Unshare the UTC namespace,
.TP
.BR \-i , " \-\-ipc"
Unshare the IPC namespace,
.TP
.BR \-n , " \-\-net"
Unshare the network namespace.
.SH SEE ALSO
unshare(2), clone(2)
.SH BUGS
None known so far.
.SH AUTHOR
Mikhail Gusarov <dottedmag@dottedmag.net>
.SH AVAILABILITY
The unshare command is part of the util-linux-ng package and is available from
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/.

119
sys-utils/unshare.c Normal file
View File

@ -0,0 +1,119 @@
/*
* unshare(1) - command-line interface for unshare(2)
*
* Copyright (C) 2009 Mikhail Gusarov <dottedmag@dottedmag.net>
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "nls.h"
#ifndef CLONE_NEWSNS
# define CLONE_NEWNS 0x00020000
#endif
#ifndef CLONE_NEWUTS
# define CLONE_NEWUTS 0x04000000
#endif
#ifndef CLONE_NEWIPC
# define CLONE_NEWIPC 0x08000000
#endif
#ifndef CLONE_NEWNET
# define CLONE_NEWNET 0x40000000
#endif
#ifndef HAVE_UNSHARE
# include <sys/syscall.h>
static int unshare(int flags)
{
return syscall(SYS_unshare, flags);
}
#endif
static void usage(int status)
{
FILE *out = status == EXIT_SUCCESS ? stdout : stderr;
fprintf(out, _("Usage: %s [options] <program> [args...]\n"),
program_invocation_short_name);
fputs(_("Run program with some namespaces unshared from parent\n\n"
" -h, --help usage information (this)\n"
" -m, --mount unshare mounts namespace\n"
" -u, --uts unshare UTS namespace (hostname etc)\n"
" -i, --ipc unshare System V IPC namespace\n"
" -n, --net unshare network namespace\n"), out);
fprintf(out, _("\nFor more information see unshare(1).\n"));
exit(status);
}
int main(int argc, char *argv[])
{
struct option longopts[] = {
{ "help", no_argument, 0, 'h' },
{ "mount", no_argument, 0, 'm' },
{ "uts", no_argument, 0, 'u' },
{ "ipc", no_argument, 0, 'i' },
{ "net", no_argument, 0, 'n' },
};
int unshare_flags = 0;
int c;
setlocale(LC_MESSAGES, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
while((c = getopt_long(argc, argv, "hmuin", longopts, NULL)) != -1) {
switch(c) {
case 'h':
usage(EXIT_SUCCESS);
case 'm':
unshare_flags |= CLONE_NEWNS;
break;
case 'u':
unshare_flags |= CLONE_NEWUTS;
break;
case 'i':
unshare_flags |= CLONE_NEWIPC;
break;
case 'n':
unshare_flags |= CLONE_NEWNET;
break;
default:
usage(EXIT_FAILURE);
}
}
if(optind >= argc)
usage(EXIT_FAILURE);
if(-1 == unshare(unshare_flags))
err(EXIT_FAILURE, _("unshare failed"));
execvp(argv[optind], argv + optind);
err(EXIT_FAILURE, _("exec %s failed"), argv[optind]);
}