]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp: -a now preserves SELinux context, with reduced diagnostics
authorOndřej Vašík <ovasik@redhat.com>
Tue, 17 Feb 2009 14:53:39 +0000 (15:53 +0100)
committerJim Meyering <meyering@redhat.com>
Wed, 18 Feb 2009 14:27:10 +0000 (15:27 +0100)
* copy.c (copy_reg): Reduce SELinux context diagnostics for 'cp -a'.
(copy_internal): Likewise
* copy.h (cp_options): Add boolean reduce_diagnostics.
* cp.c (usage): Say that --archive (-a) behaves like -dR --preserve=all.
(cp_option_init): Initialize added reduce_diagnostics.
(main): Add reduce_diagnostics for the -a option, and preserve SELinux
context, if possible.
* mv.c (cp_options_init): Initialize new cp_options booleans.
* install.c (cp_option_init): Likewise.
* NEWS: Mention those behaviour changes.
* doc/coreutils.texi: Document --preserve=context, document that
diagnostics are not shown for failures of non-mandatory attributes
(just SELinux at the moment).
* tests/cp/cp-a-selinux: Check not only failures, but succesful use
of preserving SELinux context in cp.

NEWS
doc/coreutils.texi
src/copy.c
src/copy.h
src/cp.c
src/install.c
src/mv.c
tests/cp/cp-a-selinux

diff --git a/NEWS b/NEWS
index 90bd44299fea8b3077d918928dd9ce925ebb1c2d..e541829a81f8f7834375d6733e39efaf680bbdd8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,7 +6,7 @@ GNU coreutils NEWS                                    -*- outline -*-
 
   Add extended attribute support available on certain filesystems like ext2
   and XFS.
-    cp: Tries to copy xattrs when --preserve=xattr specified
+    cp: Tries to copy xattrs when --preserve=xattr or --preserve=all specified
     mv: Always tries to copy xattrs
     install: Never copies xattrs
 
@@ -32,6 +32,9 @@ GNU coreutils NEWS                                    -*- outline -*-
 
   cp uses much less memory in some situations
 
+  cp -a now correctly tries to preserve SELinux context (announced in 6.9.90),
+  doesn't inform about failure, unlike with --preserve=all
+
   du --files0-from=FILE no longer reads all of FILE into RAM before
   processing the first file name
 
index ba1e74e3095b7e3dd1d1cd85f75febce6ef684cf..42234d36a8c48d570053120c3bee951febdb03a1 100644 (file)
@@ -7262,7 +7262,10 @@ Preserve as much as possible of the structure and attributes of the
 original files in the copy (but do not attempt to preserve internal
 directory structure; i.e., @samp{ls -U} may list the entries in a copied
 directory in a different order).
-Equivalent to @option{-dpR}.
+Try to preserve SELinux security context, but ignore any failure to do that
+and print no corresponding diagnostic.
+This option does not preserve extended attributes(xattr) at the moment.
+Equivalent to @option{-dR --preserve=all} with a few exceptions.
 
 @item -b
 @itemx @w{@kbd{--backup}[=@var{method}]}
@@ -7404,6 +7407,9 @@ Preserve in the destination files
 any links between corresponding source files.
 @c Give examples illustrating how hard links are preserved.
 @c Also, show how soft links map to hard links with -L and -H.
+@itemx context
+Preserve SELinux security context of the file. @command{cp} will fail
+if the preserving of SELinux security context is not succesful.
 @itemx xattr
 Preserve extended attributes if @command{cp} is built with xattr support,
 and xattrs are supported and enabled on your file system.
@@ -7411,7 +7417,10 @@ If SELinux context and/or ACLs are implemented using xattrs,
 they are preserved by this option as well.
 @itemx all
 Preserve all file attributes.
-Equivalent to specifying all of the above.
+Equivalent to specifying all of the above, but with the difference
+that failure to preserve SELinux security context or extended attributes
+does not change @command{cp}'s exit status.
+@command{cp} does diagnose such failures.
 @end table
 
 Using @option{--preserve} with no @var{attribute_list} is equivalent
index a6ca9dda49e39f27533ba05e08c5b70fe2a2e78c..7a7fae4497e7838f7bfecced0cd5e874d1f09f3a 100644 (file)
@@ -450,7 +450,8 @@ copy_reg (char const *src_name, char const *dst_name,
          security_context_t con = NULL;
          if (getfscreatecon (&con) < 0)
            {
-             error (0, errno, _("failed to get file system create context"));
+             if (!x->reduce_diagnostics)
+               error (0, errno, _("failed to get file system create context"));
              if (x->require_preserve_context)
                {
                  return_val = false;
@@ -462,9 +463,10 @@ copy_reg (char const *src_name, char const *dst_name,
            {
              if (fsetfilecon (dest_desc, con) < 0)
                {
-                 error (0, errno,
-                        _("failed to set the security context of %s to %s"),
-                        quote_n (0, dst_name), quote_n (1, con));
+                 if (!x->reduce_diagnostics)
+                   error (0, errno,
+                          _("failed to set the security context of %s to %s"),
+                          quote_n (0, dst_name), quote_n (1, con));
                  if (x->require_preserve_context)
                    {
                      return_val = false;
@@ -472,7 +474,7 @@ copy_reg (char const *src_name, char const *dst_name,
                      goto close_src_and_dst_desc;
                    }
                }
-             freecon(con);
+             freecon (con);
            }
        }
 
@@ -495,7 +497,7 @@ copy_reg (char const *src_name, char const *dst_name,
   if (*new_dst)
     {
       int open_flags = O_WRONLY | O_CREAT | O_BINARY;
-      dest_desc = open (dst_name, open_flags | O_EXCL ,
+      dest_desc = open (dst_name, open_flags | O_EXCL,
                        dst_mode & ~omitted_permissions);
       dest_errno = errno;
 
@@ -1721,9 +1723,10 @@ copy_internal (char const *src_name, char const *dst_name,
        {
          if (setfscreatecon (con) < 0)
            {
-             error (0, errno,
-                    _("failed to set default file creation context to %s"),
-                    quote (con));
+             if (!x->reduce_diagnostics)
+               error (0, errno,
+                      _("failed to set default file creation context to %s"),
+                      quote (con));
              if (x->require_preserve_context)
                {
                  freecon (con);
@@ -1736,9 +1739,10 @@ copy_internal (char const *src_name, char const *dst_name,
        {
          if (errno != ENOTSUP && errno != ENODATA)
            {
-             error (0, errno,
-                    _("failed to get security context of %s"),
-                    quote (src_name));
+             if (!x->reduce_diagnostics)
+               error (0, errno,
+                      _("failed to get security context of %s"),
+                      quote (src_name));
              if (x->require_preserve_context)
                return false;
            }
index 0cdf16be154ffdf3d4b7fa0721bc609aa904ff9e..8e0b4080e341141f57bad900cdf765bc2d5047f8 100644 (file)
@@ -186,6 +186,12 @@ struct cp_options
      this flag is "true", while with "cp --preserve=all", it is false. */
   bool require_preserve_xattr;
 
+  /* Used as difference boolean between cp -a and cp -dR --preserve=all.
+     If true, non-mandatory failure diagnostics are not displayed. This
+     should prevent poluting cp -a output.
+   */
+  bool reduce_diagnostics;
+
   /* If true, copy directories recursively and copy special files
      as themselves rather than copying their contents. */
   bool recursive;
index 9171fa652eab5664e4d0e04d08792d156574b500..57907cc79adca21316c65526475207ed11bd353b 100644 (file)
--- a/src/cp.c
+++ b/src/cp.c
@@ -160,7 +160,7 @@ Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
 Mandatory arguments to long options are mandatory for short options too.\n\
 "), stdout);
       fputs (_("\
-  -a, --archive                same as -dpR\n\
+  -a, --archive                same as -dR --preserve=all\n\
       --backup[=CONTROL]       make a backup of each existing destination file\n\
   -b                           like --backup but does not accept an argument\n\
       --copy-contents          copy contents of special files when recursive\n\
@@ -766,6 +766,7 @@ cp_option_init (struct cp_options *x)
   x->preserve_security_context = false;
   x->require_preserve_context = false;
   x->preserve_xattr = false;
+  x->reduce_diagnostics = false;
   x->require_preserve_xattr = false;
 
   x->require_preserve = false;
@@ -921,13 +922,16 @@ main (int argc, char **argv)
                                     sparse_type_string, sparse_type);
          break;
 
-       case 'a':               /* Like -dpR. */
+       case 'a':               /* Like -dR --preserve=all with reduced failure diagnostics. */
          x.dereference = DEREF_NEVER;
          x.preserve_links = true;
          x.preserve_ownership = true;
          x.preserve_mode = true;
          x.preserve_timestamps = true;
          x.require_preserve = true;
+         if (selinux_enabled)
+            x.preserve_security_context = true;
+         x.reduce_diagnostics = true;
          x.recursive = true;
          break;
 
index 2aa27d0af5b4cf6947fc09d6cdd2b9c229de3c9f..b09c405c43244c75ca38f53fea118a60d60f5078 100644 (file)
@@ -289,8 +289,10 @@ cp_option_init (struct cp_options *x)
   x->preserve_links = false;
   x->preserve_mode = false;
   x->preserve_timestamps = false;
+  x->reduce_diagnostics=false;
   x->require_preserve = false;
   x->require_preserve_context = false;
+  x->require_preserve_xattr = false;
   x->recursive = false;
   x->sparse_mode = SPARSE_AUTO;
   x->symbolic_link = false;
index db9207bd536772db96066d1bad3dafa89b5e7beb..77ad2fbe9407f3c7ca45a9dca78ae6e7cf48926b 100644 (file)
--- a/src/mv.c
+++ b/src/mv.c
@@ -122,9 +122,11 @@ cp_option_init (struct cp_options *x)
   x->preserve_mode = true;
   x->preserve_timestamps = true;
   x->preserve_security_context = selinux_enabled;
+  x->reduce_diagnostics = false;
   x->require_preserve = false;  /* FIXME: maybe make this an option */
   x->require_preserve_context = false;
   x->preserve_xattr = true;
+  x->require_preserve_xattr = false;
   x->recursive = true;
   x->sparse_mode = SPARSE_AUTO;  /* FIXME: maybe make this an option */
   x->symbolic_link = false;
index 2f4af35938b77b97aea235701ae3d2de35ef8913..8b7cc4d30550f73d9c1576158fd9b13c39abde62 100755 (executable)
@@ -1,8 +1,10 @@
 #!/bin/sh
 # Ensure that cp -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-2008 Free Software Foundation, Inc.
+# Copyright (C) 2007-2009 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
@@ -29,6 +31,21 @@ require_selinux_
 cwd=`pwd`
 cleanup_() { cd /; umount "$cwd/mnt"; }
 
+# This context is special: it works even when mcstransd isn't running.
+ctx=root:object_r:tmp_t:s0
+
+# Check basic functionality - before check on fixed context mount
+touch c || framework_failure
+chcon $ctx c || framework_failure
+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
+ls -Z e | grep $ctx || fail=1
+ls -Z f | grep $ctx || fail=1
+
+
 # Create a file system, then mount it with the context=... option.
 dd if=/dev/zero of=blob bs=8192 count=200 > /dev/null 2>&1 \
                                              || framework_failure
@@ -36,9 +53,6 @@ mkdir mnt                                    || framework_failure
 mkfs -t ext2 -F blob ||
   skip_test_ "failed to create an ext2 file system"
 
-# This context is special: it works even when mcstransd isn't running.
-ctx=root:object_r:tmp_t:s0
-
 mount -oloop,context=$ctx blob mnt           || framework_failure
 cd mnt                                       || framework_failure