mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-21 11:16:16 +02:00
chmod: add support for -h, -H,-L,-P, --dereference options
There have been various requests to add -h to avoid following symlinks for security reasons. This wasn't provided previously as chmod(1) already ignored symlinks unless specified on the command line. Note chmod defaults to -H mode rather than the chown default of -P, as usually chown can work directly on symlinks and so defaults to not traversing those specified on the command line. Note FreeBSD chmod does default to -P mode, but we retain the -H mode default also for compatibility with existing chmod behavior. Adding -HLP will allow chmod to disable traversing CLI symlinks to dirs. Adding -h will allow to disable following CLI symlinks to files/dirs, also operating on all symlinks on systems that support that. Adding --dereference will be significant with -H (the default). I.e. symlinks to dirs not recursed, but symlinks are dereferenced. Adding these options will also be consistent with chown(1), chgrp(1), and chmod(1) on other systems. Note since chmod(1) currently ignores symlinks by default, and -h is primarily a mechanism to avoid following symlinks, rather than for operating on the symlink itself, we make -h try to chmod a symlink, but ignore ENOTSUP. In that way we're consistent with chown(1) where it also ignores ENOTSUP for symlinks, and we don't fail when trying to be extra secure with command line params. * doc/coreutils.texi (chmod invocation): Reference the -H,-L,-P descriptions, and adjust the corresponding macros to say the default is -H or -P as appropriate. Add --dereference and -h,--no-dereference descriptions. * man/chmod.x: Adjust discussion of symlink handling. * src/chmod.c (main): Accept new options and set fts flags appropriately. (process_file): Process / dereference symlinks as necessary. * src/system.h (emit_symlink_recurse_options): A new function refactored from chown.c and chmod.c usage(). * tests/chmod/symlinks.sh: New test for the new options. * tests/local.mk: Reference the new test. * NEWS: Mention the new feature.
This commit is contained in:
87
tests/chmod/symlinks.sh
Executable file
87
tests/chmod/symlinks.sh
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/bin/sh
|
||||
# Verify chmod symlink handling options
|
||||
|
||||
# Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
|
||||
# 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
|
||||
print_ver_ chmod
|
||||
|
||||
#dirs
|
||||
mkdir -p a/b a/c || framework_failure_
|
||||
#files
|
||||
touch a/b/file a/c/file || framework_failure_
|
||||
#dangling link
|
||||
ln -s foo a/dangle || framework_failure_
|
||||
#link to file
|
||||
ln -s ../b/file a/c/link || framework_failure_
|
||||
#link to dir
|
||||
ln -s b a/dirlink || framework_failure_
|
||||
|
||||
# tree -F a
|
||||
# a/
|
||||
# |-- b/
|
||||
# | '-- file
|
||||
# |-- c/
|
||||
# | |-- file
|
||||
# | '-- link -> ../b/file
|
||||
# |-- dangle -> foo
|
||||
# '-- dirlink -> b/
|
||||
|
||||
reset_modes() { chmod 777 a/b a/c a/b/file a/c/file || fail=1; }
|
||||
count_755() { test "$(grep 'rwxr-xr-x' 'out' | wc -l)" = "$1"; }
|
||||
|
||||
reset_modes
|
||||
# -R (with default -H) does not deref traversed symlinks (only cli args)
|
||||
chmod 755 -R a/c || fail=1
|
||||
ls -l a/b > out || framework_failure_
|
||||
count_755 0 || fail=1
|
||||
ls -lR a/c > out || framework_failure_
|
||||
count_755 1 || fail=1
|
||||
|
||||
reset_modes
|
||||
# set a/c a/c/file and a/b/file (through symlink) to 755
|
||||
chmod 755 -LR a/c || fail=1
|
||||
ls -ld a/c a/c/file a/b/file > out || framework_failure_
|
||||
count_755 3 || { cat out; fail=1; }
|
||||
|
||||
reset_modes
|
||||
# do not set /a/b/file through symlink (should try to chmod the link itself)
|
||||
chmod 755 -RP a/c/ || fail=1
|
||||
ls -l a/b > out || framework_failure_
|
||||
count_755 0 || fail=1
|
||||
|
||||
reset_modes
|
||||
# set /a/b/file through symlink
|
||||
chmod 755 --dereference a/c/link || fail=1
|
||||
ls -l a/b > out || framework_failure_
|
||||
count_755 1 || fail=1
|
||||
|
||||
reset_modes
|
||||
# do not set /a/b/file through symlink (should try to chmod the link itself)
|
||||
chmod 755 --no-dereference a/c/link 2>err || fail=1
|
||||
ls -l a/b > out || framework_failure_
|
||||
count_755 0 || fail=1
|
||||
|
||||
# Dangling links should not induce an error if not dereferencing
|
||||
for noderef in '-h' '-RP' '-P'; do
|
||||
chmod 755 --no-dereference a/dangle 2>err || fail=1
|
||||
done
|
||||
# Dangling links should induce an error if dereferencing
|
||||
for deref in '' '--deref' '-R'; do
|
||||
returns_ 1 chmod 755 $deref a/dangle 2>err || fail=1
|
||||
done
|
||||
|
||||
Exit $fail
|
||||
Reference in New Issue
Block a user