{
/* With -Z, adjust the default context for the process
to have the type component adjusted as per the destination path. */
- if (new_dst && defaultcon (dst_name, mode) < 0)
+ if (new_dst && defaultcon (dst_name, mode) < 0
+ && ! ignorable_ctx_err (errno))
{
- if (!errno_unsupported (errno))
- error (0, errno,
- _("failed to set default file creation context for %s"),
- quote (dst_name));
+ error (0, errno,
+ _("failed to set default file creation context for %s"),
+ quote (dst_name));
}
}
x.one_file_system = true;
break;
-
case 'Z':
/* politely decline if we're not on a selinux-enabled kernel. */
if (selinux_enabled)
if (scontext)
restorecon (dst_path, 0, true);
*/
- if (scontext && setfscreatecon (optarg) < 0)
+ if (scontext && setfscreatecon (scontext) < 0)
error (EXIT_FAILURE, errno,
_("failed to set default file creation context to %s"),
- quote (optarg));
+ quote (scontext));
#if !USE_XATTR
if (x.require_preserve_xattr)
{
struct mkdir_options const *o = options;
- if (o->set_security_context && defaultcon (dir, S_IFDIR) < 0)
+ if (o->set_security_context && defaultcon (dir, S_IFDIR) < 0
+ && ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quote (dir));
set_defaultcon = true;
free (pdir);
}
- if (set_defaultcon && defaultcon (dir, S_IFDIR) < 0)
+ if (set_defaultcon && defaultcon (dir, S_IFDIR) < 0
+ && ! ignorable_ctx_err (errno))
error (0, errno, _("failed to set default creation context for %s"),
quote (dir));
}
and here we set the context for the final component. */
if (ret == EXIT_SUCCESS && o->set_security_context && ! set_defaultcon)
{
- if (restorecon (last_component (dir), false, false) < 0)
- error (0, errno, _("failed to set restore context for %s"),
+ if (! restorecon (last_component (dir), false, false)
+ && ! ignorable_ctx_err (errno))
+ error (0, errno, _("failed to restore context for %s"),
quote (dir));
}
backup_suffix_string = optarg;
break;
case 'Z':
- /* politely decline if we're not on a selinux-enabled kernel. */
+ /* As a performance enhancement, don't even bother trying
+ to "restorecon" when not on an selinux-enabled kernel. */
if (selinux_enabled)
{
x.preserve_security_context = false;
#ifndef COREUTILS_SELINUX_H
# define COREUTILS_SELINUX_H
+/* Return true if ERR corresponds to an unsupported request,
+ or if there is no context or it's inaccessible. */
+static inline bool
+ignorable_ctx_err (int err)
+{
+ return err == ENOTSUP || err == ENODATA;
+}
+
# if HAVE_SELINUX_SELINUX_H
extern bool restorecon (char const *path, bool recurse, bool preserve);
# ensure that ls -l output includes the ".".
c=$(ls -l f|cut -c11); test "$c" = . || fail=1
+# Copy with an invalid context and ensure it fails
+# Note this may succeed when root and selinux is in permissive mode
+if test "$(getenforce)" = Enforcing; then
+ cp --context='invalid-selinux-context' f f.cp && fail=1
+fi
+
# Copy each to a new directory and ensure that context is preserved.
cp -r --preserve=all d f p s1 || fail=1
for i in d f p; do