copy: fix SELinux context preservation for existing directories

* src/copy.c (copy_internal): Use the global process context
to set the context of existing directories before they're populated.
This is more consistent with the new directory case, and fixes
a bug for existing directories where we erroneously set the
context to the last copied descendent, rather than to that of
the source directory itself.
* tests/cp/cp-a-selinux.sh: Add a test for this case.
* NEWS: Mention the fix.
* THANKS.in: Add reporter Michal Trunecka.
This commit is contained in:
Pádraig Brady 2014-01-02 16:40:58 +00:00
parent 5d7591d0ed
commit 243128dbf0
4 changed files with 36 additions and 1 deletions

7
NEWS
View File

@ -2,6 +2,13 @@ GNU coreutils NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
** Bug fixes
cp -a, mv, and install --preserve-context, once again set the correct SELinux
context for existing directories in the destination. Previously they set
the context of an existing directory to that of its last copied descendent.
[bug introduced in coreutils-8.22]
* Noteworthy changes in release 8.22 (2013-12-13) [stable]

View File

@ -441,6 +441,7 @@ Michael Veksler mveksler@techunix.technion.ac.il
Michail Litvak mci@owl.openwall.com
Michal Politowski mpol@charybda.icm.edu.pl
Michal Svec msvec@suse.cz
Michal Trunecka mtruneck@redhat.com
Michel Robitaille robitail@IRO.UMontreal.CA
Michiel Bacchiani bacchian@raven.bu.edu
Mike Castle dalgoda@ix.netcom.com

View File

@ -2408,6 +2408,17 @@ copy_internal (char const *src_name, char const *dst_name,
else
{
omitted_permissions = 0;
/* For directories, the process global context could be reset for
descendents, so use it to set the context for existing dirs here.
This will also give earlier indication of failure to set ctx. */
if (x->set_security_context || x->preserve_security_context)
if (! set_file_security_ctx (dst_name, x->preserve_security_context,
false, x))
{
if (x->require_preserve_context)
goto un_backup;
}
}
/* Decide whether to copy the contents of the directory. */
@ -2598,7 +2609,7 @@ copy_internal (char const *src_name, char const *dst_name,
/* With -Z or --preserve=context, set the context for existing files.
Note this is done already for copy_reg() for reasons described therein. */
if (!new_dst && !x->copy_as_regular
if (!new_dst && !x->copy_as_regular && !S_ISDIR (src_mode)
&& (x->set_security_context || x->preserve_security_context))
{
if (! set_file_security_ctx (dst_name, x->preserve_security_context,

View File

@ -41,6 +41,22 @@ test -s err && fail=1 #there must be no stderr output for -a
ls -Z e | grep $ctx || fail=1
ls -Z f | grep $ctx || fail=1
# 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