summaryrefslogtreecommitdiff
path: root/src/copy.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2007-01-20 16:10:43 +0100
committerJim Meyering <jim@meyering.net>2007-03-29 21:37:06 +0200
commit85ddc626be5fd202f04aa8ced398b5119174b556 (patch)
treefdece904533e6747c797254cff27512a3e82cb3d /src/copy.c
parent5a7fe9c0f8a3154d52d44265c73675b91441b209 (diff)
downloadcoreutils-85ddc626be5fd202f04aa8ced398b5119174b556.tar.xz
cp, mv, install: add SELinux support, but unlike with the Red Hat
patch, mv and cp do not provide the "-Z context" option. * src/copy.c: Include <selinux/selinux.h>. (restore_default_fscreatecon): New function. (copy_reg): Make cp --preserve=context work for existing destination. (copy_internal): Likewise for new destinations. * src/copy.h (cp_options) [preserve_security_context]: New member. * src/cp.c: Include <selinux/selinux.h>. (selinux_enabled): New global. (usage): Mention new --preserve=context option. (PRESERVE_CONTEXT): Define/use. (decode_preserve_arg): Handle PRESERVE_CONTEXT. (main): Remove an obsolete comment. If --preserve=context is specified on a system without SELinux enabled, give a diagnostic and fail. * src/mv.c: Include <selinux/selinux.h>. Set x->preserve_security_context if SELinux is enabled. * src/install.c: Accept new "-Z, --context=C" option. Accept --preserve-context option (but not -P option). Accept alternate spelling: --preserve_context, for now. Include <selinux/selinux.h> and "quotearg.h". (selinux_enabled, use_default_selinux_context): New globals. (PRESERVE_CONTEXT_OPTION): Define. (cp_option_init): Default: do not preserve security context. (setdefaultfilecon): New function. (main): Honor new options. * src/Makefile.am (mv_LDADD, cp_LDADD, ginstall_LDADD): Add $(LIB_SELINUX).
Diffstat (limited to 'src/copy.c')
-rw-r--r--src/copy.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/src/copy.c b/src/copy.c
index 786de2f9e..f60fa55bd 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <assert.h>
#include <sys/types.h>
+#include <selinux/selinux.h>
#if HAVE_HURD_H
# include <hurd.h>
@@ -298,6 +299,36 @@ copy_reg (char const *src_name, char const *dst_name,
{
dest_desc = open (dst_name, O_WRONLY | O_TRUNC | O_BINARY);
+ /* When using cp --preserve=context to copy to an existing destination,
+ use the default context rather than that of the source. Why?
+ 1) the src context may prohibit writing, and
+ 2) because it's more consistent to use the same context
+ that is used when the destination file doesn't already exist. */
+ if (x->preserve_security_context && 0 <= dest_desc)
+ {
+ security_context_t con;
+ if (getfscreatecon (&con) < 0)
+ {
+ error (0, errno, _("failed to get file system create context"));
+ return_val = false;
+ goto close_src_desc;
+ }
+
+ if (con)
+ {
+ 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));
+ return_val = false;
+ freecon (con);
+ goto close_src_desc;
+ }
+ freecon(con);
+ }
+ }
+
if (dest_desc < 0 && x->unlink_dest_after_failed_open)
{
if (unlink (dst_name) != 0)
@@ -1001,6 +1032,15 @@ emit_verbose (char const *src, char const *dst, char const *backup_dst_name)
putchar ('\n');
}
+/* A wrapper around "setfscreatecon (NULL)" that exits upon failure. */
+static void
+restore_default_fscreatecon_or_die (void)
+{
+ if (setfscreatecon (NULL) != 0)
+ error (EXIT_FAILURE, errno,
+ _("failed to restore the default file creation context"));
+}
+
/* Copy the file SRC_NAME to the file DST_NAME. The files may be of
any type. NEW_DST should be true if the file DST_NAME cannot
exist because its parent directory was just created; NEW_DST should
@@ -1349,7 +1389,7 @@ copy_internal (char const *src_name, char const *dst_name,
if (x->move_mode && src_sb.st_nlink == 1)
{
- earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
+ earlier_file = src_to_dest_lookup (src_sb.st_ino, src_sb.st_dev);
}
else if ((x->preserve_links
&& (1 < src_sb.st_nlink
@@ -1539,6 +1579,37 @@ copy_internal (char const *src_name, char const *dst_name,
delayed_ok = true;
+ if (x->preserve_security_context)
+ {
+ security_context_t con;
+
+ if (0 <= lgetfilecon (src_name, &con))
+ {
+ if (setfscreatecon (con) < 0)
+ {
+ error (0, errno,
+ _("failed to set default file creation context to %s"),
+ quote (con));
+ if (x->require_preserve)
+ {
+ freecon (con);
+ return false;
+ }
+ }
+ freecon (con);
+ }
+ else
+ {
+ if (errno != ENOTSUP && errno != ENODATA)
+ {
+ error (0, errno,
+ _("failed to get security context of %s"),
+ quote (src_name));
+ return false;
+ }
+ }
+ }
+
/* In certain modes (cp's --symbolic-link), and for certain file types
(symlinks and hard links) it doesn't make sense to preserve metadata,
or it's possible to preserve only some of it.
@@ -1768,6 +1839,9 @@ copy_internal (char const *src_name, char const *dst_name,
}
}
+ if (x->preserve_security_context)
+ restore_default_fscreatecon_or_die ();
+
/* There's no need to preserve timestamps or permissions. */
preserve_metadata = false;
@@ -1901,6 +1975,9 @@ copy_internal (char const *src_name, char const *dst_name,
un_backup:
+ if (x->preserve_security_context)
+ restore_default_fscreatecon_or_die ();
+
/* We have failed to create the destination file.
If we've just added a dev/ino entry via the remember_copied
call above (i.e., unless we've just failed to create a hard link),