1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-20 02:36:16 +02:00

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.
This commit is contained in:
Pádraig Brady
2014-05-13 15:56:34 +01:00
parent ffd1a1d8de
commit 99960eeab9
3 changed files with 35 additions and 24 deletions

3
NEWS
View File

@@ -82,6 +82,9 @@ GNU coreutils NEWS -*- outline -*-
** Changes in behavior
chroot with an argument of "/" no longer implicitly changes the current
directory to "/", allowing changing only user credentials for a command.
ls with none of LS_COLORS or COLORTERM environment variables set,
will now honor an empty or unknown TERM environment variable,
and not output colors even with --colors=always.

View File

@@ -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));
/* 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 (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 (chdir ("/"))
error (EXIT_CANCELED, errno, _("cannot chdir to root directory"));
}
if (argc == optind + 1)
{

View File

@@ -28,16 +28,18 @@ test $? = 125 || fail=1
chroot --- / true # unknown option
test $? = 125 || fail=1
# chroot("/") succeeds for non-root users on some systems, but not all.
if chroot / true ; then
chroot / sh -c 'exit 2' # exit status propagation
test $? = 2 || fail=1
chroot / . # invalid command
test $? = 126 || fail=1
chroot / no_such # no such command
test $? = 127 || fail=1
else
test $? = 125 || fail=1
fi
# Note chroot("/") succeeds for non-root users on some systems, but not all,
# however we avoid the chroot() with "/" to have common behvavior.
chroot / sh -c 'exit 2' # exit status propagation
test $? = 2 || fail=1
chroot / . # invalid command
test $? = 126 || fail=1
chroot / no_such # no such command
test $? = 127 || fail=1
# Ensure we don't chdir("/") when not changing root
# to allow only changing user ids for a command.
curdir=$(chroot / env pwd) || fail=1
test "$curdir" = '/' && fail=1
Exit $fail