The attached patch reinstates the "prefix" optimization from matchpathcon_init_prefix(), with the SELABEL_OPT_SUBSET equivalent. The original code was added in: https://git.sv.gnu.org/gitweb/?p=coreutils.git;a=commitdiff;h=v6.9.89-7-g56e3106e9 and suggests an 8x perf improvement.
However I'm not seeing any perf difference, and a very quick scan of the selinux source suggests the option is moot in the presence of compiled contexts. I'd rather not add back this code if possible. Could Red Hat folks indicate how useful it is currently, and if non compiled policies are a practical consideration for install(1). thanks, Pádraig
>From e54ac99841ea855c75f83628fca75e871f9e2afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com> Date: Mon, 23 Nov 2020 21:58:10 +0000 Subject: [PATCH] install: reinstate prefix length hint to selinux * src/install.c (get_labeling_handle): Reinstate the equivalent matchpathcon_init_prefix() code from v6.9.89-7-g56e3106e9, which suggests significant performance benefit. --- src/install.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/install.c b/src/install.c index dce29dbe1..e0d51f821 100644 --- a/src/install.c +++ b/src/install.c @@ -302,17 +302,49 @@ cp_option_init (struct cp_options *x) } static struct selabel_handle * -get_labeling_handle (void) +get_labeling_handle (char const *file) { static bool initialized; static struct selabel_handle *hnd; - if (!initialized) + + if (! initialized) { initialized = true; - hnd = selabel_open (SELABEL_CTX_FILE, NULL, 0); + char *prefix = NULL; + + if (file && IS_ABSOLUTE_FILE_NAME (file)) + { + /* Calling selabel_open with a prefix is an optimization to + minimize the expense of the following selabel_lookup calls. */ + char const *p0; + char const *p = file + 1; + while (ISSLASH (*p)) + ++p; + + /* Record final leading slash, when FILE starts with two or more. */ + p0 = p - 1; + + if (*p) + { + do + { + ++p; + } + while (*p && !ISSLASH (*p)); + + prefix = malloc (p - p0 + 2); + if (prefix) + stpcpy (stpncpy (prefix, p0, p - p0), "/"); + } + } + + struct selinux_opt option = {SELABEL_OPT_SUBSET, prefix}; + hnd = selabel_open (SELABEL_CTX_FILE, &option, 1); if (!hnd) error (0, errno, _("warning: security labeling handle failed")); + free (prefix); } + return hnd; } @@ -334,7 +366,7 @@ setdefaultfilecon (char const *file) if (lstat (file, &st) != 0) return; - struct selabel_handle *hnd = get_labeling_handle (); + struct selabel_handle *hnd = get_labeling_handle (file); if (!hnd) return; if (selabel_lookup (hnd, &scontext, file, st.st_mode) != 0) @@ -875,7 +907,7 @@ main (int argc, char **argv) if (optarg) scontext = optarg; else - x.set_security_context = get_labeling_handle (); + x.set_security_context = get_labeling_handle (NULL); } else if (optarg) { -- 2.26.2