diff options
Diffstat (limited to 'tests/cp/cp-a-selinux.sh')
-rwxr-xr-x | tests/cp/cp-a-selinux.sh | 121 |
1 files changed, 106 insertions, 15 deletions
diff --git a/tests/cp/cp-a-selinux.sh b/tests/cp/cp-a-selinux.sh index e7bdcf1d..58887d27 100755 --- a/tests/cp/cp-a-selinux.sh +++ b/tests/cp/cp-a-selinux.sh @@ -1,10 +1,10 @@ #!/bin/sh -# Ensure that cp -a and cp --preserve=context work properly. +# Ensure that cp -Z, -a and cp --preserve=context work properly. # In particular, test on a writable NFS partition. # Check also locally if --preserve=context, -a and --preserve=all # does work -# Copyright (C) 2007-2013 Free Software Foundation, Inc. +# Copyright (C) 2007-2014 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 @@ -37,9 +37,66 @@ cp -a c d 2>err || framework_failure_ cp --preserve=context c e || framework_failure_ cp --preserve=all c f || framework_failure_ ls -Z d | grep $ctx || fail=1 -test -s err && fail=1 #there must be no stderr output for -a +# there must be no stderr output for -a +compare /dev/null err || fail=1 ls -Z e | grep $ctx || fail=1 ls -Z f | grep $ctx || fail=1 +rm -f f + +# Check handling of existing dirs which requires specific handling +# due to recursion, and was handled incorrectly in coreutils-8.22 +# Note standard permissions are updated for existing directories +# in the destination, so SELinux contexts should be updated too. +chmod o+rw restore/existing_dir +mkdir -p backup/existing_dir/ || framework_failure_ +ls -Zd backup/existing_dir | grep $ctx && framework_failure_ +touch backup/existing_dir/file || framework_failure_ +chcon $ctx backup/existing_dir/file || framework_failure_ +# Set the dir context to ensure it is reset +mkdir -p --context="$ctx" restore/existing_dir || framework_failure_ +# Copy and ensure existing directories updated +cp -a backup/. restore/ +ls -Zd restore/existing_dir | grep $ctx && + { ls -lZd restore/existing_dir; fail=1; } + +# Check restorecon (-Z) functionality for file and directory +get_selinux_type() { ls -Zd "$1" | sed -n 's/.*:\(.*_t\):.*/\1/p'; } +# Also make a dir with our known context +mkdir c_d || framework_failure_ +chcon $ctx c_d || framework_failure_ +# Get the type of this known context for file and dir +old_type_f=$(get_selinux_type c) +old_type_d=$(get_selinux_type c_d) +# Setup copies for manipulation with restorecon +# and get the adjusted type for comparison +cp -a c Z1 || fail=1 +cp -a c_d Z1_d || fail=1 +if restorecon Z1 Z1_d 2>/dev/null; then + new_type_f=$(get_selinux_type Z1) + new_type_d=$(get_selinux_type Z1_d) + + # Ensure -Z sets the type like restorecon does + cp -Z c Z2 || fail=1 + cpZ_type_f=$(get_selinux_type Z2) + test "$cpZ_type_f" = "$new_type_f" || fail=1 + + # Ensuze -Z overrides -a and that dirs are handled too + cp -aZ c Z3 || fail=1 + cp -aZ c_d Z3_d || fail=1 + cpaZ_type_f=$(get_selinux_type Z3) + cpaZ_type_d=$(get_selinux_type Z3_d) + test "$cpaZ_type_f" = "$new_type_f" || fail=1 + test "$cpaZ_type_d" = "$new_type_d" || fail=1 + + # Ensure -Z sets the type for existing files + mkdir -p existing/c_d || framework_failure_ + touch existing/c || framework_failure_ + cp -aZ c c_d existing || fail=1 + cpaZ_type_f=$(get_selinux_type existing/c) + cpaZ_type_d=$(get_selinux_type existing/c_d) + test "$cpaZ_type_f" = "$new_type_f" || fail=1 + test "$cpaZ_type_d" = "$new_type_d" || fail=1 +fi skip=0 # Create a file system, then mount it with the context=... option. @@ -54,27 +111,30 @@ test $skip = 1 \ cd mnt || framework_failure_ -echo > f || framework_failure_ - +# Create files with hopefully different contexts +echo > ../f || framework_failure_ echo > g || framework_failure_ +test "$(stat -c%C ../f)" = "$(stat -c%C g)" && + skip_ "files on separate file systems have the same security context" + # /bin/cp from coreutils-6.7-3.fc7 would fail this test by letting cp # succeed (giving no diagnostics), yet leaving the destination file empty. -cp -a f g 2>err || fail=1 +cp -a ../f g 2>err || fail=1 test -s g || fail=1 # The destination file must not be empty. -test -s err && fail=1 # There must be no stderr output. +compare /dev/null err || fail=1 # ===================================================== # Here, we expect cp to succeed and not warn with "Operation not supported" rm -f g echo > g -cp --preserve=all f g 2>err || fail=1 +cp --preserve=all ../f g 2>err || fail=1 test -s g || fail=1 grep "Operation not supported" err && fail=1 # ===================================================== # The same as above except destination does not exist rm -f g -cp --preserve=all f g 2>err || fail=1 +cp --preserve=all ../f g 2>err || fail=1 test -s g || fail=1 grep "Operation not supported" err && fail=1 @@ -94,21 +154,52 @@ echo > g # ===================================================== # Here, we expect cp to fail, because it cannot set the SELinux # security context through NFS or a mount with fixed context. -cp --preserve=context f g 2> out && fail=1 +cp --preserve=context ../f g 2> out && fail=1 # Here, we *do* expect the destination to be empty. -test -s g && fail=1 -sed "s/ .g' to .*//" out > k +compare /dev/null g || fail=1 +sed "s/ .g'.*//" out > k mv k out compare exp out || fail=1 rm -f g echo > g # Check if -a option doesn't silence --preserve=context option diagnostics -cp -a --preserve=context f g 2> out2 && fail=1 +cp -a --preserve=context ../f g 2> out2 && fail=1 # Here, we *do* expect the destination to be empty. -test -s g && fail=1 -sed "s/ .g' to .*//" out2 > k +compare /dev/null g || fail=1 +sed "s/ .g'.*//" out2 > k mv k out2 compare exp out2 || fail=1 +for no_g_cmd in '' 'rm -f g'; do + # restorecon equivalent. Note even though the context + # returned from matchpathcon() will not match $ctx + # the resulting ENOTSUP warning will be suppressed. + # With absolute path + $no_g_cmd + cp -Z ../f $(realpath g) || fail=1 + # With relative path + $no_g_cmd + cp -Z ../f g || fail=1 + # -Z overrides -a + $no_g_cmd + cp -Z -a ../f g || fail=1 + # -Z doesn't take an arg + $no_g_cmd + cp -Z "$ctx" ../f g && fail=1 + + # Explicit context + $no_g_cmd + # Explicitly defaulting to the global $ctx should work + cp --context="$ctx" ../f g || fail=1 + # --context overrides -a + $no_g_cmd + cp -a --context="$ctx" ../f g || fail=1 +done + +# Mutually exlusive options +cp -Z --preserve=context ../f g && fail=1 +cp --preserve=context -Z ../f g && fail=1 +cp --preserve=context --context="$ctx" ../f g && fail=1 + Exit $fail |