summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2014-05-13 15:56:34 +0100
committerPádraig Brady <P@draigBrady.com>2014-05-16 22:01:31 +0100
commit99960eeab9bf7fb479ab9f5342fc12a1fae629e6 (patch)
tree451f8fc6ba8c3ce9214d14eb24bd848c86b15597 /src
parentffd1a1d8dee921e20db515e7d4b3c3e47006c8b4 (diff)
downloadcoreutils-99960eeab9bf7fb479ab9f5342fc12a1fae629e6.tar.xz
chroot: don't chdir() if not changing root
This allows chroot to be used as a light weight tool to change user identification for a command, while not changing the current working directory. It also makes `chroot / true` consistently succeed on all platforms for non root users. * src/chroot.c (main): If the same root is specified. i.e. '/' then don't change the current working directory, and avoid the overhead of the other redundant calls. * tests/misc/chroot-fail.sh: Remove failure guard previously needed on some systems. Also add an explicit case to ensure we don't change directory. * NEWS: Mention the change in behavior.
Diffstat (limited to 'src')
-rw-r--r--src/chroot.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/src/chroot.c b/src/chroot.c
index 8b08b84ea..a2debac1c 100644
--- a/src/chroot.c
+++ b/src/chroot.c
@@ -225,21 +225,27 @@ main (int argc, char **argv)
usage (EXIT_CANCELED);
}
- /* We have to look up users and groups twice.
- - First, outside the chroot to load potentially necessary passwd/group
- parsing plugins (e.g. NSS);
- - Second, inside chroot to redo the parsing in case IDs are different. */
- if (userspec)
- ignore_value (parse_user_spec (userspec, &uid, &gid, NULL, NULL));
- if (groups && *groups)
- ignore_value (parse_additional_groups (groups, &out_gids, &n_gids, false));
-
- if (chroot (argv[optind]) != 0)
- error (EXIT_CANCELED, errno, _("cannot change root directory to %s"),
- argv[optind]);
-
- if (chdir ("/"))
- error (EXIT_CANCELED, errno, _("cannot chdir to root directory"));
+ /* Only do chroot specific actions if actually changing root.
+ The main difference here is that we don't change working dir. */
+ if (! STREQ (argv[optind], "/"))
+ {
+ /* We have to look up users and groups twice.
+ - First, outside the chroot to load potentially necessary passwd/group
+ parsing plugins (e.g. NSS);
+ - Second, inside chroot to redo parsing in case IDs are different. */
+ if (userspec)
+ ignore_value (parse_user_spec (userspec, &uid, &gid, NULL, NULL));
+ if (groups && *groups)
+ ignore_value (parse_additional_groups (groups, &out_gids, &n_gids,
+ false));
+
+ if (chroot (argv[optind]) != 0)
+ error (EXIT_CANCELED, errno, _("cannot change root directory to %s"),
+ argv[optind]);
+
+ if (chdir ("/"))
+ error (EXIT_CANCELED, errno, _("cannot chdir to root directory"));
+ }
if (argc == optind + 1)
{