diff options
author | Jim Meyering <jim@meyering.net> | 2007-01-20 16:10:43 +0100 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2007-03-29 21:37:06 +0200 |
commit | 85ddc626be5fd202f04aa8ced398b5119174b556 (patch) | |
tree | fdece904533e6747c797254cff27512a3e82cb3d /src/copy.c | |
parent | 5a7fe9c0f8a3154d52d44265c73675b91441b209 (diff) | |
download | coreutils-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.c | 79 |
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), |