cp: -a now preserves SELinux context, with reduced diagnostics

* 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.
This commit is contained in:
Ondřej Vašík 2009-02-17 15:53:39 +01:00 committed by Jim Meyering
parent 86cef85b36
commit 8c243ff965
8 changed files with 65 additions and 21 deletions

5
NEWS
View File

@ -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

View 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

View 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;
}

View 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;

View File

@ -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;

View 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;

View File

@ -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;

View File

@ -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