diff options
author | Pádraig Brady <P@draigBrady.com> | 2014-05-13 15:56:34 +0100 |
---|---|---|
committer | Pádraig Brady <P@draigBrady.com> | 2014-05-16 22:01:31 +0100 |
commit | 99960eeab9bf7fb479ab9f5342fc12a1fae629e6 (patch) | |
tree | 451f8fc6ba8c3ce9214d14eb24bd848c86b15597 /src | |
parent | ffd1a1d8dee921e20db515e7d4b3c3e47006c8b4 (diff) | |
download | coreutils-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.c | 36 |
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) { |