]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
selinux: fix --context=CTX for cp and diagnose defaultcon() errors
authorPádraig Brady <P@draigBrady.com>
Wed, 4 Dec 2013 19:10:37 +0000 (19:10 +0000)
committerPádraig Brady <P@draigBrady.com>
Thu, 5 Dec 2013 00:18:36 +0000 (00:18 +0000)
* src/selinux.h (ignorable_ctx_err): A new function used
to determine if a warning should be given after a call
to defaultcon() or restorecon().
* src/cp.c (main): Fix the setfscreatecon() call to use
the argument passed by the user.
* src/mkdir.c (make_ancestor): Show all but "ignoreable" errors
from defaultcon() and restorecon().
* tests/misc/selinux.sh: Add a test run as root in selinux enforcing
mode, to ensure cp --context=invalid is honored and fails immediately.

src/copy.c
src/cp.c
src/mkdir.c
src/mv.c
src/selinux.h
tests/misc/selinux.sh

index dab8fdd779b735dff353b840cda4d2e37c0aef27..0f044d021d01b219db9324e61b66d7ea701b72a1 100644 (file)
@@ -805,12 +805,12 @@ set_process_security_ctx (char const *src_name, char const *dst_name,
     {
       /* 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));
         }
     }
 
index 59d659d03bd712be09dce87ecad0ffe6813efa5d..9038d4e7d4ffbbeb0626f34d967fa4a672773829 100644 (file)
--- a/src/cp.c
+++ b/src/cp.c
@@ -1099,7 +1099,6 @@ main (int argc, char **argv)
           x.one_file_system = true;
           break;
 
-
         case 'Z':
           /* politely decline if we're not on a selinux-enabled kernel.  */
           if (selinux_enabled)
@@ -1195,10 +1194,10 @@ main (int argc, char **argv)
        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)
index 25b1da5e77f24dde1e6f009a1186d1866bc05fbf..adc29301904df5ef432710a49b0e9ce9e0d5a585 100644 (file)
@@ -118,7 +118,8 @@ make_ancestor (char const *dir, char const *component, void *options)
 {
   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));
 
@@ -162,7 +163,8 @@ process_dir (char *dir, struct savewd *wd, void *options)
             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));
     }
@@ -180,8 +182,9 @@ process_dir (char *dir, struct savewd *wd, void *options)
      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));
     }
 
index cb6b70e25845c05ce23123f84ec3d7a627c1d980..b69b355049337721a4dcfdc3cd50760d08e18e9e 100644 (file)
--- a/src/mv.c
+++ b/src/mv.c
@@ -424,7 +424,8 @@ main (int argc, char **argv)
           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;
index 31771632ecdfa4a4eb80489cccc23bb36396d4e9..e4ded84666b01cf90d0b77f5940897dc49ae5185 100644 (file)
 #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);
index b30bcbcf762b3db5529dfad0c93c83b8559b69c0..3c53b9fce9f1d86f8a9f7c5a4d87c111d51e1a15 100755 (executable)
@@ -44,6 +44,12 @@ done
 # 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