summaryrefslogtreecommitdiffstats
path: root/sys-utils/unshare.c
diff options
context:
space:
mode:
authorLaurent Vivier2018-10-05 13:09:29 +0200
committerKarel Zak2018-11-12 11:52:14 +0100
commitbf8834d4f43e39c4212e1974cee4a76c1a8ba545 (patch)
tree995b4b8f0e00579251d37348a502142d97b2def0 /sys-utils/unshare.c
parentagetty: fix output of escaped characters (diff)
downloadkernel-qcow2-util-linux-bf8834d4f43e39c4212e1974cee4a76c1a8ba545.tar.gz
kernel-qcow2-util-linux-bf8834d4f43e39c4212e1974cee4a76c1a8ba545.tar.xz
kernel-qcow2-util-linux-bf8834d4f43e39c4212e1974cee4a76c1a8ba545.zip
unshare: allow to set a new root
This patch instroduces two new parameters to set the new root and the new working directory in this new root. This allows to combine "unshare chroot" in one command, and doing like this the /proc filesystem is correctly mounted in the new root with "--mount-proc". The new parameters are -R, --root and -w, --wd. The names are the same as for nsenter, except for "-r" that is already used by "--map-root-user" and replaced by "-R". Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Diffstat (limited to 'sys-utils/unshare.c')
-rw-r--r--sys-utils/unshare.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index 661665aeb..12ef044f8 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -269,6 +269,9 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" --propagation slave|shared|private|unchanged\n"
" modify mount propagation in mount namespace\n"), out);
fputs(_(" --setgroups allow|deny control the setgroups syscall in user namespaces\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_(" -R, --root=<dir> run the command with root directory set to <dir>\n"), out);
+ fputs(_(" -w, --wd=<dir> change working directory to <dir>\n"), out);
fputs(USAGE_SEPARATOR, out);
printf(USAGE_HELP_OPTIONS(27));
@@ -283,7 +286,7 @@ int main(int argc, char *argv[])
OPT_MOUNTPROC = CHAR_MAX + 1,
OPT_PROPAGATION,
OPT_SETGROUPS,
- OPT_KILLCHILD
+ OPT_KILLCHILD,
};
static const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
@@ -303,6 +306,8 @@ int main(int argc, char *argv[])
{ "map-root-user", no_argument, NULL, 'r' },
{ "propagation", required_argument, NULL, OPT_PROPAGATION },
{ "setgroups", required_argument, NULL, OPT_SETGROUPS },
+ { "root", required_argument, NULL, 'R' },
+ { "wd", required_argument, NULL, 'w' },
{ NULL, 0, NULL, 0 }
};
@@ -311,6 +316,8 @@ int main(int argc, char *argv[])
int c, forkit = 0, maproot = 0;
int kill_child_signo = 0; /* 0 means --kill-child was not used */
const char *procmnt = NULL;
+ const char *newroot = NULL;
+ const char *newdir = NULL;
pid_t pid = 0;
int fds[2];
int status;
@@ -323,7 +330,7 @@ int main(int argc, char *argv[])
textdomain(PACKAGE);
atexit(close_stdout);
- while ((c = getopt_long(argc, argv, "+fhVmuinpCUr", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "+fhVmuinpCUrR:w:", longopts, NULL)) != -1) {
switch (c) {
case 'f':
forkit = 1;
@@ -392,6 +399,12 @@ int main(int argc, char *argv[])
kill_child_signo = SIGKILL;
}
break;
+ case 'R':
+ newroot = optarg;
+ break;
+ case 'w':
+ newdir = optarg;
+ break;
default:
errtryhelp(EXIT_FAILURE);
}
@@ -471,10 +484,21 @@ int main(int argc, char *argv[])
if ((unshare_flags & CLONE_NEWNS) && propagation)
set_propagation(propagation);
- if (procmnt &&
- (mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0 ||
- mount("proc", procmnt, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0))
+ if (newroot) {
+ if (chroot(newroot) != 0)
+ err(EXIT_FAILURE,
+ _("cannot change root directory to '%s'"), newroot);
+ newdir = newdir ?: "/";
+ }
+ if (newdir && chdir(newdir))
+ err(EXIT_FAILURE, _("cannot chdir to '%s'"), newdir);
+
+ if (procmnt) {
+ if (!newroot && mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0)
+ err(EXIT_FAILURE, _("umount %s failed"), procmnt);
+ if (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);