From: Christian Göttsche Date: Tue, 19 Dec 2023 14:55:28 +0000 (+0100) Subject: copy,install: avoid unnecessary security context translations X-Git-Tag: v9.5~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98d463ef5d44b9dfe6757942251164b56795b06f;p=thirdparty%2Fcoreutils.git copy,install: avoid unnecessary security context translations 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. --- diff --git a/NEWS b/NEWS index a4fd77073b..26da9993ef 100644 --- 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. diff --git a/src/copy.c b/src/copy.c index f54253e5bf..b74e27f63a 100644 --- a/src/copy.c +++ b/src/copy.c @@ -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 { diff --git a/src/install.c b/src/install.c index 31a48f114d..855c30cd51 100644 --- a/src/install.c +++ b/src/install.c @@ -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. */ diff --git a/src/selinux.c b/src/selinux.c index 0fdd0c81fa..7fcaab7842 100644 --- a/src/selinux.c +++ b/src/selinux.c @@ -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; } diff --git a/tests/cp/no-ctx.sh b/tests/cp/no-ctx.sh index 8c69bf38d3..6296f6aa3a 100755 --- a/tests/cp/no-ctx.sh +++ b/tests/cp/no-ctx.sh @@ -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: