]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
copy,install: avoid unnecessary security context translations
authorChristian Göttsche <cgzones@googlemail.com>
Tue, 19 Dec 2023 14:55:28 +0000 (15:55 +0100)
committerPádraig Brady <P@draigBrady.com>
Tue, 19 Dec 2023 17:34:33 +0000 (17:34 +0000)
Do not perform SELinux context translation for operations not involving
user input or output.  Context translation converts MCS/MLS labels into
human readable form, which is useful for user facing applications like
ls(1) or the --context=CTX argument of cp(1).

* src/copy.c (set_process_security_ctx): Use raw selinux variants.
* src/install.c (need_copy): Likewise.
(setdefaultfilecon): Likewise.
* src/selinux.c (computecon): Likewise.
(defaultcon): Likewise.
* tests/cp/no-ctx.sh: Add raw variants to preload lib.
* NEWS: Mention the improvement.

NEWS
src/copy.c
src/install.c
src/selinux.c
tests/cp/no-ctx.sh

diff --git a/NEWS b/NEWS
index a4fd77073bdd205870ba503be7a39bb0393e20c9..26da9993ef11ffde4e1823a65ecaca58161682b9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -52,6 +52,9 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Improvements
 
+  SELinux operations in file copy operations are now more efficient,
+  avoiding unneeded MCS/MLS label translation.
+
   wc is now much faster in single-byte locales and somewhat faster in
   multi-byte locales.
 
index f54253e5bfec9fbfdb469d404fbb0bd4eae6b365..b74e27f63a4f7cc6f7bb7386bcd4fdc5075f273f 100644 (file)
@@ -1020,23 +1020,23 @@ set_process_security_ctx (char const *src_name, char const *dst_name,
       /* Set the default context for the process to match the source.  */
       bool all_errors = !x->data_copy_required || x->require_preserve_context;
       bool some_errors = !all_errors && !x->reduce_diagnostics;
-      char *con;
+      char *con_raw;
 
-      if (0 <= lgetfilecon (src_name, &con))
+      if (0 <= lgetfilecon_raw (src_name, &con_raw))
         {
-          if (setfscreatecon (con) < 0)
+          if (setfscreatecon_raw (con_raw) < 0)
             {
               if (all_errors || (some_errors && !errno_unsupported (errno)))
                 error (0, errno,
                        _("failed to set default file creation context to %s"),
-                       quote (con));
+                       quote (con_raw));
               if (x->require_preserve_context)
                 {
-                  freecon (con);
+                  freecon (con_raw);
                   return false;
                 }
             }
-          freecon (con);
+          freecon (con_raw);
         }
       else
         {
index 31a48f114d334287a6aa2232cbb1e10520400312..855c30cd51349c0cb7db66ad02d611af44369289 100644 (file)
@@ -214,23 +214,23 @@ need_copy (char const *src_name, char const *dest_name,
   /* compare SELinux context if preserving */
   if (selinux_enabled && x->preserve_security_context)
     {
-      char *file_scontext = nullptr;
-      char *to_scontext = nullptr;
+      char *file_scontext_raw = nullptr;
+      char *to_scontext_raw = nullptr;
       bool scontext_match;
 
-      if (getfilecon (src_name, &file_scontext) == -1)
+      if (getfilecon_raw (src_name, &file_scontext_raw) == -1)
         return true;
 
-      if (getfilecon (dest_name, &to_scontext) == -1)
+      if (getfilecon_raw (dest_name, &to_scontext_raw) == -1)
         {
-          freecon (file_scontext);
+          freecon (file_scontext_raw);
           return true;
         }
 
-      scontext_match = STREQ (file_scontext, to_scontext);
+      scontext_match = STREQ (file_scontext_raw, to_scontext_raw);
 
-      freecon (file_scontext);
-      freecon (to_scontext);
+      freecon (file_scontext_raw);
+      freecon (to_scontext_raw);
       if (!scontext_match)
         return true;
     }
@@ -323,7 +323,7 @@ static void
 setdefaultfilecon (char const *file)
 {
   struct stat st;
-  char *scontext = nullptr;
+  char *scontext_raw = nullptr;
 
   if (selinux_enabled != 1)
     {
@@ -336,7 +336,7 @@ setdefaultfilecon (char const *file)
   struct selabel_handle *hnd = get_labeling_handle ();
   if (!hnd)
     return;
-  if (selabel_lookup (hnd, &scontext, file, st.st_mode) != 0)
+  if (selabel_lookup_raw (hnd, &scontext_raw, file, st.st_mode) != 0)
     {
       if (errno != ENOENT && ! ignorable_ctx_err (errno))
         error (0, errno, _("warning: %s: context lookup failed"),
@@ -344,12 +344,12 @@ setdefaultfilecon (char const *file)
       return;
     }
 
-  if (lsetfilecon (file, scontext) < 0 && errno != ENOTSUP)
+  if (lsetfilecon_raw (file, scontext_raw) < 0 && errno != ENOTSUP)
     error (0, errno,
            _("warning: %s: failed to change context to %s"),
-           quotef_n (0, file), quote_n (1, scontext));
+           quotef_n (0, file), quote_n (1, scontext_raw));
 
-  freecon (scontext);
+  freecon (scontext_raw);
 }
 
 /* Report that directory DIR was made, if OPTIONS requests this.  */
index 0fdd0c81fa4f4c86fe350239068ab3c8aa3fd785..7fcaab78426b4e939c0c3d65bf4958a050cbc35b 100644 (file)
@@ -69,37 +69,37 @@ mode_to_security_class (mode_t m)
 */
 
 static int
-computecon (char const *path, mode_t mode, char **con)
+computecon_raw (char const *path, mode_t mode, char **con)
 {
-  char *scon = nullptr;
-  char *tcon = nullptr;
+  char *scon_raw = nullptr;
+  char *tcon_raw = nullptr;
   security_class_t tclass;
   int rc = -1;
 
   char *dir = dir_name (path);
   if (!dir)
     goto quit;
-  if (getcon (&scon) < 0)
+  if (getcon_raw (&scon_raw) < 0)
     goto quit;
-  if (getfilecon (dir, &tcon) < 0)
+  if (getfilecon_raw (dir, &tcon_raw) < 0)
     goto quit;
   tclass = mode_to_security_class (mode);
   if (!tclass)
     goto quit;
-  rc = security_compute_create (scon, tcon, tclass, con);
+  rc = security_compute_create_raw (scon_raw, tcon_raw, tclass, con);
 
  quit:;
   int err = errno;
   free (dir);
-  freecon (scon);
-  freecon (tcon);
+  freecon (scon_raw);
+  freecon (tcon_raw);
   errno = err;
   return rc;
 }
 
 /*
-  This function takes a handle, path and mode, it calls computecon to get the
-  label of the path object if the current process created it, then it calls
+  This function takes a handle, path and mode, it calls computecon_raw to get
+  the label of the path object if the current process created it, then it calls
   selabel_lookup to get the default type for the object.  It substitutes the
   default type into label.  It tells the SELinux Kernel to label all new file
   system objects created by the current process with this label.
@@ -111,8 +111,8 @@ defaultcon (struct selabel_handle *selabel_handle,
             char const *path, mode_t mode)
 {
   int rc = -1;
-  char *scon = nullptr;
-  char *tcon = nullptr;
+  char *scon_raw = nullptr;
+  char *tcon_raw = nullptr;
   context_t scontext = 0, tcontext = 0;
   char const *contype;
   char const *constr;
@@ -127,7 +127,7 @@ defaultcon (struct selabel_handle *selabel_handle,
       path = newpath;
     }
 
-  if (selabel_lookup (selabel_handle, &scon, path, mode) < 0)
+  if (selabel_lookup_raw (selabel_handle, &scon_raw, path, mode) < 0)
     {
       /* "No such file or directory" is a confusing error,
          when processing files, when in fact it was the
@@ -138,11 +138,11 @@ defaultcon (struct selabel_handle *selabel_handle,
         errno = ENODATA;
       goto quit;
     }
-  if (computecon (path, mode, &tcon) < 0)
+  if (computecon_raw (path, mode, &tcon_raw) < 0)
     goto quit;
-  if (!(scontext = context_new (scon)))
+  if (!(scontext = context_new (scon_raw)))
     goto quit;
-  if (!(tcontext = context_new (tcon)))
+  if (!(tcontext = context_new (tcon_raw)))
     goto quit;
 
   if (!(contype = context_type_get (scontext)))
@@ -152,14 +152,14 @@ defaultcon (struct selabel_handle *selabel_handle,
   if (!(constr = context_str (tcontext)))
     goto quit;
 
-  rc = setfscreatecon (constr);
+  rc = setfscreatecon_raw (constr);
 
  quit:;
   int err = errno;
   context_free (scontext);
   context_free (tcontext);
-  freecon (scon);
-  freecon (tcon);
+  freecon (scon_raw);
+  freecon (tcon_raw);
   free (newpath);
   errno = err;
   return rc;
@@ -179,8 +179,8 @@ restorecon_private (struct selabel_handle *selabel_handle, char const *path)
 {
   int rc = -1;
   struct stat sb;
-  char *scon = nullptr;
-  char *tcon = nullptr;
+  char *scon_raw = nullptr;
+  char *tcon_raw = nullptr;
   context_t scontext = 0, tcontext = 0;
   char const *contype;
   char const *constr;
@@ -188,16 +188,16 @@ restorecon_private (struct selabel_handle *selabel_handle, char const *path)
 
   if (!selabel_handle)
     {
-      if (getfscreatecon (&tcon) < 0)
+      if (getfscreatecon_raw (&tcon_raw) < 0)
         return rc;
-      if (!tcon)
+      if (!tcon_raw)
         {
           errno = ENODATA;
           return rc;
         }
-      rc = lsetfilecon (path, tcon);
+      rc = lsetfilecon_raw (path, tcon_raw);
       int err = errno;
-      freecon (tcon);
+      freecon (tcon_raw);
       errno = err;
       return rc;
     }
@@ -217,7 +217,7 @@ restorecon_private (struct selabel_handle *selabel_handle, char const *path)
         goto quit;
     }
 
-  if (selabel_lookup (selabel_handle, &scon, path, sb.st_mode) < 0)
+  if (selabel_lookup_raw (selabel_handle, &scon_raw, path, sb.st_mode) < 0)
     {
       /* "No such file or directory" is a confusing error,
          when processing files, when in fact it was the
@@ -228,21 +228,21 @@ restorecon_private (struct selabel_handle *selabel_handle, char const *path)
         errno = ENODATA;
       goto quit;
     }
-  if (!(scontext = context_new (scon)))
+  if (!(scontext = context_new (scon_raw)))
     goto quit;
 
   if (fd != -1)
     {
-      if (fgetfilecon (fd, &tcon) < 0)
+      if (fgetfilecon_raw (fd, &tcon_raw) < 0)
         goto quit;
     }
   else
     {
-      if (lgetfilecon (path, &tcon) < 0)
+      if (lgetfilecon_raw (path, &tcon_raw) < 0)
         goto quit;
     }
 
-  if (!(tcontext = context_new (tcon)))
+  if (!(tcontext = context_new (tcon_raw)))
     goto quit;
 
   if (!(contype = context_type_get (scontext)))
@@ -253,9 +253,9 @@ restorecon_private (struct selabel_handle *selabel_handle, char const *path)
     goto quit;
 
   if (fd != -1)
-    rc = fsetfilecon (fd, constr);
+    rc = fsetfilecon_raw (fd, constr);
   else
-    rc = lsetfilecon (path, constr);
+    rc = lsetfilecon_raw (path, constr);
 
  quit:;
   int err = errno;
@@ -263,8 +263,8 @@ restorecon_private (struct selabel_handle *selabel_handle, char const *path)
     close (fd);
   context_free (scontext);
   context_free (tcontext);
-  freecon (scon);
-  freecon (tcon);
+  freecon (scon_raw);
+  freecon (tcon_raw);
   errno = err;
   return rc;
 }
index 8c69bf38d37455a17d37b42a9f82956e11c94990..6296f6aa3a3adb30ef295a32fcc59cab145e044b 100755 (executable)
@@ -39,8 +39,14 @@ int getfilecon (const char *path, char **con)
   return -1;
 }
 
+int getfilecon_raw (const char *path, char **con)
+{ return getfilecon (path, con); }
+
 int lgetfilecon (const char *path, char **con)
 { return getfilecon (path, con); }
+
+int lgetfilecon_raw (const char *path, char **con)
+{ return getfilecon (path, con); }
 EOF
 
 # Then compile/link it: