From 8a86223d45be7597b229a95381aebab3512bf6d7 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Wed, 31 Jan 2007 23:01:50 +0100 Subject: * tests/cp/cp-a-selinux: New file. Test for the bug reported in * tests/cp/Makefile.am (TESTS): Add cp-a-selinux. * tests/selinux: New file. * tests/Makefile.am (EXTRA_DIST): Add selinux. * tests/misc/selinux: Source the new script, rather than open coding it. Change how "cp -a" and "cp --preserve=context" work with SELinux. Now, cp -a attempts to preserve context, but failure to do so does not change cp's exit status. However "cp --preserve=context" is similar, but failure *does* cause cp to exit with nonzero status. * src/copy.h (struct cp_options) [require_preserve_context]: New member. * src/copy.c (copy_reg, copy_internal): Implement the above. * src/mv.c (cp_option_init): Initialize the new member. * src/install.c (cp_option_init): Likewise. * src/cp.c (cp_option_init): Likewise. (decode_preserve_arg): Set it or reset it. FIXME: add an on-writable-NFS-only test --- src/copy.c | 21 ++++++++++++++------- src/copy.h | 22 +++++++++++++++++----- src/cp.c | 2 ++ src/install.c | 1 + src/mv.c | 1 + 5 files changed, 35 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/copy.c b/src/copy.c index f60fa55bd..d2088ae46 100644 --- a/src/copy.c +++ b/src/copy.c @@ -310,8 +310,11 @@ copy_reg (char const *src_name, char const *dst_name, if (getfscreatecon (&con) < 0) { error (0, errno, _("failed to get file system create context")); - return_val = false; - goto close_src_desc; + if (x->require_preserve_context) + { + return_val = false; + goto close_src_desc; + } } if (con) @@ -321,9 +324,12 @@ copy_reg (char const *src_name, char const *dst_name, error (0, errno, _("failed to set the security context of %s to %s"), quote_n (0, dst_name), quote_n (1, con)); - return_val = false; - freecon (con); - goto close_src_desc; + if (x->require_preserve_context) + { + return_val = false; + freecon (con); + goto close_src_desc; + } } freecon(con); } @@ -1590,7 +1596,7 @@ copy_internal (char const *src_name, char const *dst_name, error (0, errno, _("failed to set default file creation context to %s"), quote (con)); - if (x->require_preserve) + if (x->require_preserve_context) { freecon (con); return false; @@ -1605,7 +1611,8 @@ copy_internal (char const *src_name, char const *dst_name, error (0, errno, _("failed to get security context of %s"), quote (src_name)); - return false; + if (x->require_preserve_context) + return false; } } } diff --git a/src/copy.h b/src/copy.h index eab6c8678..0d6233f95 100644 --- a/src/copy.h +++ b/src/copy.h @@ -127,9 +127,6 @@ struct cp_options bool preserve_ownership; bool preserve_mode; bool preserve_timestamps; - /* If true, attempt to preserve the SELinux security context, too. - Set this only if the kernel is SELinux enabled. */ - bool preserve_security_context; /* Enabled for mv, and for cp by the --preserve=links option. If true, attempt to preserve in the destination files any @@ -145,10 +142,25 @@ struct cp_options /* If true and any of the above (for preserve) file attributes cannot be applied to a destination file, treat it as a failure and return - nonzero immediately. E.g. cp -p requires this be nonzero, mv requires - it be zero. */ + nonzero immediately. E.g. for cp -p this must be true, for mv it + must be false. */ bool require_preserve; + /* If true, attempt to preserve the SELinux security context, too. + Set this only if the kernel is SELinux enabled. */ + bool preserve_security_context; + + /* Useful only when preserve_security_context is true. + If true, a failed attempt to preserve a file's security context + propagates failure "out" to the caller. If false, a failure to + preserve a file's security context does not change the invoking + application's exit status. Give diagnostics for failed syscalls + regardless of this setting. For example, with "cp --preserve=context" + this flag is "true", while with "cp -a", it is false. That means + "cp -a" attempts to preserve any security context, but does not + fail if it is unable to do so. */ + bool require_preserve_context; + /* If true, copy directories recursively and copy special files as themselves rather than copying their contents. */ bool recursive; diff --git a/src/cp.c b/src/cp.c index c63e047d9..35c487b9f 100644 --- a/src/cp.c +++ b/src/cp.c @@ -754,6 +754,7 @@ cp_option_init (struct cp_options *x) x->preserve_mode = false; x->preserve_timestamps = false; x->preserve_security_context = false; + x->require_preserve_context = false; x->require_preserve = false; x->recursive = false; @@ -832,6 +833,7 @@ decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off) case PRESERVE_CONTEXT: x->preserve_security_context = on_off; + x->require_preserve_context = on_off; break; case PRESERVE_ALL: diff --git a/src/install.c b/src/install.c index f6152f355..dc7ff0141 100644 --- a/src/install.c +++ b/src/install.c @@ -174,6 +174,7 @@ cp_option_init (struct cp_options *x) x->preserve_mode = false; x->preserve_timestamps = false; x->require_preserve = false; + x->require_preserve_context = false; x->recursive = false; x->sparse_mode = SPARSE_AUTO; x->symbolic_link = false; diff --git a/src/mv.c b/src/mv.c index 90387f79b..5ffe2ae23 100644 --- a/src/mv.c +++ b/src/mv.c @@ -131,6 +131,7 @@ cp_option_init (struct cp_options *x) x->preserve_timestamps = true; x->preserve_security_context = selinux_enabled; x->require_preserve = false; /* FIXME: maybe make this an option */ + x->require_preserve_context = false; x->recursive = true; x->sparse_mode = SPARSE_AUTO; /* FIXME: maybe make this an option */ x->symbolic_link = false; -- cgit v1.2.3-54-g00ecf