Bug 1045122 - cp -a messes up destination selinux contexts for existing directories
Summary: cp -a messes up destination selinux contexts for existing directories
Keywords:
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Enterprise Linux 7
Classification: Red Hat
Component: coreutils
Version: 7.0
Hardware: All
OS: Linux
urgent
urgent
Target Milestone: rc
: 7.0
Assignee: Ondrej Vasik
QA Contact: Tomas Dolezal
URL:
Whiteboard:
Depends On:
Blocks: 798670
TreeView+ depends on / blocked
 
Reported: 2013-12-19 16:30 UTC by Michal Trunecka
Modified: 2014-06-18 04:53 UTC (History)
11 users (show)

Fixed In Version: coreutils-8.22-5.el7
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2014-06-13 11:16:49 UTC
Target Upstream Version:


Attachments (Terms of Use)
Strace output of the reproducing cp command (15.73 KB, text/plain)
2014-01-02 09:04 UTC, Michal Trunecka
no flags Details
proposed fix (2.03 KB, patch)
2014-01-02 17:02 UTC, Pádraig Brady
no flags Details | Diff

Description Michal Trunecka 2013-12-19 16:30:01 UTC
Description of problem:

This is a regression in coreutils version 8.22-1

In our tests, we have backups like this, with given (correctly backed up) contexts:

/var/tmp/beakerlib-meTuGkC/backup-krb5/var/kerberos/krb5kdc/kdc.conf
                  root_t---^           ^      ^        ^        ^
                             var_t-----^      ^        ^        ^
                             var_t------------^        ^        ^
                                       krb5kdc_conf_t--^--------^

But after restoring the backup, which is done by 

cp -fa /var/tmp/beakerlib-meTuGkC/backup-krb5/var  /

it assigns the krb5kdc_conf_t context to the whole destination path! It means that /var has this context and the whole system is broken by this.



Version-Release number of selected component (if applicable):
coreutils-8.22-1.el7.ppc64

How reproducible:
always


Expected results:

cp -fa should preserve the original contexts

Comment 1 Ondrej Vasik 2013-12-19 19:06:38 UTC
Thanks Michal for looking at this - adding Dan Walsh to CC - as he is the author of most of the upstream changes...
There is one divergency in SELinux copy mechanism in downstream SELinux coreutils-8.22 patch - so pasting it here to be sure. I'll try to analyze it while on Christmas break.
diff -urNp coreutils-8.21-orig/src/copy.c coreutils-8.21/src/copy.c
--- coreutils-8.21-orig/src/copy.c	2013-02-07 10:37:05.000000000 +0100
+++ coreutils-8.21/src/copy.c	2013-02-15 14:31:58.941467872 +0100
@@ -2315,6 +2315,8 @@ copy_internal (char const *src_name, cha
         {
           /* Here, we are crossing a file system boundary and cp's -x option
              is in effect: so don't copy the contents of this directory. */
+        if (x->preserve_security_context)
+           restore_default_fscreatecon_or_die ();
         }
       else
         {

Comment 3 Daniel Walsh 2013-12-20 16:13:06 UTC
Are you saying we added or removed

+        if (x->preserve_security_context)
+           restore_default_fscreatecon_or_die ();

Comment 4 Ondrej Vasik 2013-12-20 16:28:52 UTC
No, this is part of our downstream patch which is in Fedora/RHEL for ages. As most of the things are already accepted upstream, this one is the only remaining chunk in copy.c - probably it is not connected to the issue.

Comment 5 Ondrej Vasik 2013-12-20 17:58:04 UTC
Is this specific for ppc64? It seems to work properly on my machine (ok, compiled coreutils-8.22 on F20, I haven't tried the rhel7 machine yet). Can you please provide strace of the failure? TIA.

Comment 6 Daniel Walsh 2013-12-20 20:33:27 UTC
Then the problem looks like it is calling setfscreatecon(krb5kdc_conf_t) before to create the target file but not for the intermediate directories.  



/var/tmp/beakerlib-meTuGkC/backup-krb5/var/kerberos/krb5kdc/kdc.conf
                  root_t---^           ^      ^        ^        ^
                             var_t-----^      ^        ^        ^
                             var_t------------^        ^        ^
                                       krb5kdc_conf_t--^--------^
IE is should be calling

setfsreatecon(root_t); mkdir backup-krb5
 setfsreatecon(var_t); mkdir var
 setfsreatecon(var_t); mkdir kerberos
 setfsreatecon(krb5kdc_conf_t); mkdir krb5kdc
 setfsreatecon(krb5kdc_conf_t); create kdc.conf

Comment 7 Michal Trunecka 2014-01-02 09:04:15 UTC
Created attachment 844440 [details]
Strace output of the reproducing cp command

Yes, it is reproducible on x86_64 too, attached strace of the command.

# rpm -q coreutils
coreutils-8.22-1.el7.x86_64

Comment 8 Ondrej Vasik 2014-01-02 09:28:22 UTC
Hmmms, from strace it clearly calls setxattr "unconfined_u:object_r:krb5kdc_conf_t:s0" on /var ... strange - it really works just fine on my F20 x86_64 machine with the same coreutils build. I'm going to compare the straces. One suspicious thing - warnings about missing /var/run/setrans/.setrans-unix socket file - is mcstrans service running?

Comment 9 Michal Trunecka 2014-01-02 09:41:35 UTC
No, mcstrans was not even installed. But the bug is still reproducible after installing and running mcstrans daemon.

Comment 10 Ondrej Vasik 2014-01-02 09:55:25 UTC
Ok, now I see - my reproducer on F20 was "slightly modified" - copying the output to non-existing directory - that worked (-f was not in action). I'm able to reproduce it now - it seems to correctly copy the context if the file/directory doesn't exist before the command, it screws up the context if the directory existed before the command. Further investigating.

Comment 11 Ondrej Vasik 2014-01-02 10:19:04 UTC
I believe this is caused by this chunk from the http://git.savannah.gnu.org/cgit/coreutils.git/commit/src/copy.c?id=7958a4a4fe234f9787daf178a60bc83449605dac ... as -a turns on the x->preserve_security_context ... 

@@ -2521,6 +2596,19 @@ copy_internal (char const *src_name, char const *dst_name,
goto un_backup;
}
+ /* 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
+ && (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;
+ }
+ }
+
if (command_line_arg && x->dest_info)
{
/* Now that the destination file is very likely to exist,

Adding upstream maintainer to CC to let him notified about this regression.
I believe "|| x->require_preserve_context" should be used there. Anyway - this chunk is probably wrong in general, as it sets the context of all recursive subdirs to the context of destination file.

Comment 12 Pádraig Brady 2014-01-02 14:22:47 UTC
Ugh. What created the backup BTW? I'm not sure that any version of `cp -a` copies intermediate directory contexts. Anyway looking at this now...

Comment 13 Michal Trunecka 2014-01-02 14:26:37 UTC
The backup was not created by single cp command, but by Beaker rlFileBackup function, which creates the path using mkdir and assigns the contexts using chcon.

Comment 14 Pádraig Brady 2014-01-02 17:02:38 UTC
Created attachment 844620 [details]
proposed fix

I need to add a test for this before pushing upstream, but it should fix this issue.

I also noticed the related issue that the context is not set for new
dirs when using --parents

Comment 15 Ondrej Vasik 2014-01-02 17:53:32 UTC
Thanks Pádraig...

Comment 18 Michal Trunecka 2014-01-03 12:15:56 UTC
I can confirm that the scenario in the Bug Description works as expected now with coreutils-8.22-5.el7.x86_64.

Comment 25 Pádraig Brady 2014-01-07 18:09:39 UTC
The proposed upstream commit also includes a test
http://lists.gnu.org/archive/html/coreutils/2014-01/msg00012.html

Comment 27 Ludek Smid 2014-06-13 11:16:49 UTC
This request was resolved in Red Hat Enterprise Linux 7.0.

Contact your manager or support representative in case you have further questions about the request.


Note You need to log in before you can comment on or make changes to this bug.