public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/libsemanage] rawhide: Optionally sort file_contexts.local by specificity
@ 2026-09-08 15:07 Petr Lautrbach
0 siblings, 0 replies; only message in thread
From: Petr Lautrbach @ 2026-09-08 15:07 UTC (permalink / raw)
To: git-commits
A new commit has been pushed.
Repo : rpms/libsemanage
Branch : rawhide
Commit : aecb61672ec87c4a3ffb2ca1b2bd39d9fe519ff6
Author : Petr Lautrbach <lautrbach@redhat.com>
Date : 2026-09-08T10:01:52+02:00
Stats : +316/-7 in 4 file(s)
URL : https://src.fedoraproject.org/rpms/libsemanage/c/aecb61672ec87c4a3ffb2ca1b2bd39d9fe519ff6?branch=rawhide
Log:
Optionally sort file_contexts.local by specificity
---
diff --git a/0001-libsemanage-optionally-sort-file_contexts.local-by-s.patch b/0001-libsemanage-optionally-sort-file_contexts.local-by-s.patch
new file mode 100644
index 0000000..44c66d6
--- /dev/null
+++ b/0001-libsemanage-optionally-sort-file_contexts.local-by-s.patch
@@ -0,0 +1,258 @@
+From 8941a47c788d974f284ad3ad03b16b0b53f6f37f Mon Sep 17 00:00:00 2001
+From: Stephen Smalley <stephen.smalley.work@gmail.com>
+Date: Thu, 3 Sep 2026 07:59:28 -0400
+Subject: [PATCH] libsemanage: optionally sort file_contexts.local by
+ specificity
+Content-type: text/plain
+
+The policy-supplied file_contexts is emitted by the CIL compiler in
+least-to-most-specific order (cil_post_filecon_compare()) so that the
+libselinux label_file backend, which returns last matching spec, picks
+the most specific match. file_contexts.local is written by libsemanage
+in the order the entriers were added with semanage fcontext -a, so a
+broad entry added after a narrow one overrides it, and callers cannot
+rely on "most specific wins" for local customizations.
+
+Add a semanage.conf sort-local-fcontexts boolean. When set to true,
+the copy of file_contexts.local installed to the policy directory is
+run through semanage_fc_sort(), which uses the same heuristics as
+cil_post_filecon_compare(), with equally-specific entries retaining
+their insertion order. The module store copy is left in insertion
+order, so semanage fcontext -l -C still shows entries as they were
+added.
+
+Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=678577
+Fixes: https://github.com/SELinuxProject/selinux/issues/40
+Signed-off-by: Stephen Smalley <stephen.smalley.work@gmail.com>
+---
+ libsemanage/man/man5/semanage.conf.5 | 13 ++++++
+ libsemanage/src/conf-parse.y | 15 +++++-
+ libsemanage/src/conf-scan.l | 1 +
+ libsemanage/src/direct_api.c | 19 ++++++--
+ libsemanage/src/semanage_conf.h | 1 +
+ libsemanage/src/semanage_store.c | 70 ++++++++++++++++++++++++++++
+ libsemanage/src/semanage_store.h | 2 +
+ 7 files changed, 116 insertions(+), 5 deletions(-)
+
+diff --git a/libsemanage/man/man5/semanage.conf.5 b/libsemanage/man/man5/semanage.conf.5
+index 74f0d34fe17c..336e02d09692 100644
+--- a/libsemanage/man/man5/semanage.conf.5
++++ b/libsemanage/man/man5/semanage.conf.5
+@@ -131,6 +131,19 @@ It can be set to either "true" or "false" and by default it is set to "true".
+ When set to "true", duplicate type, type attribute, and role declarations will be allowed.
+ It can be set to either "true" or "false" and by default it is set to "true".
+
++.TP
++.B sort-local-fcontexts
++When set to "true", the installed
++.I file_contexts.local
++file is sorted from least to most specific using the same heuristic as the policy-supplied
++.IR file_contexts ,
++so the most specific local entry wins regardless of the order the entries were added with
++.BR "semanage fcontext \-a" .
++The module store copy (and thus
++.BR "semanage fcontext \-l \-C" )
++is unaffected.
++It can be set to either "true" or "false" and by default it is set to "false", preserving insertion-order matching.
++
+ .RE
+ .PP
+ For certain tasks the SELinux Management library resorts to running
+diff --git a/libsemanage/src/conf-parse.y b/libsemanage/src/conf-parse.y
+index dee17b2fbbbc..ba75a1ecfc8d 100644
+--- a/libsemanage/src/conf-parse.y
++++ b/libsemanage/src/conf-parse.y
+@@ -62,7 +62,7 @@ static int parse_errors;
+ char *s;
+ }
+
+-%token MODULE_STORE VERSION EXPAND_CHECK FILE_MODE SAVE_PREVIOUS SAVE_LINKED TARGET_PLATFORM COMPILER_DIR IGNORE_MODULE_CACHE STORE_ROOT OPTIMIZE_POLICY MULTIPLE_DECLS
++%token MODULE_STORE VERSION EXPAND_CHECK FILE_MODE SAVE_PREVIOUS SAVE_LINKED TARGET_PLATFORM COMPILER_DIR IGNORE_MODULE_CACHE STORE_ROOT OPTIMIZE_POLICY MULTIPLE_DECLS SORT_LOCAL_FCONTEXTS
+ %token LOAD_POLICY_START SETFILES_START SEFCONTEXT_COMPILE_START DISABLE_GENHOMEDIRCON HANDLE_UNKNOWN USEPASSWD IGNOREDIRS
+ %token BZIP_BLOCKSIZE BZIP_SMALL RELABEL_STORE REMOVE_HLL
+ %token VERIFY_MOD_START VERIFY_LINKED_START VERIFY_KERNEL_START BLOCK_END
+@@ -101,6 +101,7 @@ single_opt: module_store
+ | relabel_store
+ | optimize_policy
+ | multiple_decls
++ | sort_local_fcontexts
+ ;
+
+ module_store: MODULE_STORE '=' ARG {
+@@ -329,6 +330,17 @@ multiple_decls: MULTIPLE_DECLS '=' ARG {
+ free($3);
+ }
+
++sort_local_fcontexts: SORT_LOCAL_FCONTEXTS '=' ARG {
++ if (strcasecmp($3, "false") == 0) {
++ current_conf->sort_local_fcontexts = false;
++ } else if (strcasecmp($3, "true") == 0) {
++ current_conf->sort_local_fcontexts = true;
++ } else {
++ yyerror("sort-local-fcontexts can only be 'true' or 'false'");
++ }
++ free($3);
++}
++
+ command_block:
+ command_start external_opts BLOCK_END {
+ if (new_external->path == NULL) {
+@@ -425,6 +437,7 @@ static int semanage_conf_init(semanage_conf_t * conf)
+ conf->relabel_store = true;
+ conf->optimize_policy = true;
+ conf->multiple_decls = true;
++ conf->sort_local_fcontexts = false;
+
+ conf->save_previous = false;
+ conf->save_linked = false;
+diff --git a/libsemanage/src/conf-scan.l b/libsemanage/src/conf-scan.l
+index c592fb6387a1..8d1d56ac33f3 100644
+--- a/libsemanage/src/conf-scan.l
++++ b/libsemanage/src/conf-scan.l
+@@ -57,6 +57,7 @@ remove-hll return REMOVE_HLL;
+ relabel_store return RELABEL_STORE;
+ optimize-policy return OPTIMIZE_POLICY;
+ multiple-decls return MULTIPLE_DECLS;
++sort-local-fcontexts return SORT_LOCAL_FCONTEXTS;
+ "[load_policy]" return LOAD_POLICY_START;
+ "[setfiles]" return SETFILES_START;
+ "[sefcontext_compile]" return SEFCONTEXT_COMPILE_START;
+diff --git a/libsemanage/src/direct_api.c b/libsemanage/src/direct_api.c
+index 9572dbf05982..37ea1cd23c98 100644
+--- a/libsemanage/src/direct_api.c
++++ b/libsemanage/src/direct_api.c
+@@ -1607,10 +1607,21 @@ static int semanage_direct_commit(semanage_handle_t *sh)
+ goto cleanup;
+ }
+
+- retval = copy_file_if_exists(
+- sh, semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
+- semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL),
+- sh->conf->file_mode);
++ if (sh->conf->sort_local_fcontexts) {
++ retval = semanage_sort_fc_file(
++ sh,
++ semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
++ semanage_final_path(SEMANAGE_FINAL_TMP,
++ SEMANAGE_FC_LOCAL),
++ sh->conf->file_mode);
++ } else {
++ retval = copy_file_if_exists(
++ sh,
++ semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
++ semanage_final_path(SEMANAGE_FINAL_TMP,
++ SEMANAGE_FC_LOCAL),
++ sh->conf->file_mode);
++ }
+ if (retval < 0) {
+ goto cleanup;
+ }
+diff --git a/libsemanage/src/semanage_conf.h b/libsemanage/src/semanage_conf.h
+index 5a24ea87026d..d8544dc908f5 100644
+--- a/libsemanage/src/semanage_conf.h
++++ b/libsemanage/src/semanage_conf.h
+@@ -51,6 +51,7 @@ typedef struct semanage_conf {
+ bool optimize_policy;
+ bool multiple_decls;
+ bool relabel_store;
++ bool sort_local_fcontexts;
+ char *ignoredirs; /* ";" separated of list for genhomedircon to ignore */
+ struct external_prog *load_policy;
+ struct external_prog *setfiles;
+diff --git a/libsemanage/src/semanage_store.c b/libsemanage/src/semanage_store.c
+index f14ebe97ecf6..d6f56a82795d 100644
+--- a/libsemanage/src/semanage_store.c
++++ b/libsemanage/src/semanage_store.c
+@@ -1604,6 +1604,76 @@ cleanup:
+ return retval;
+ }
+
++/*
++ * Read file-context specifications from @src, sort them from least
++ * to most specific using the same heuristic as the policy-supplied
++ * file_contexts (see semanage_fc_compare()), and write the result to
++ * @dst. Comments in @src are dropped; the auto-generated header is
++ * re-emitted. A missing @src is not an error.
++ */
++int semanage_sort_fc_file(semanage_handle_t *sh, const char *src,
++ const char *dst, mode_t mode)
++{
++ const char *header = "# This file is auto-generated by libsemanage\n"
++ "# Do not edit directly.\n\n";
++ struct file_contents contents = {};
++ char *sorted = NULL;
++ size_t sorted_len = 0;
++ int out = -1, retval = -1;
++ mode_t mask;
++
++ if (access(src, F_OK) != 0)
++ return (errno == ENOENT) ? 0 : -1;
++
++ if (map_compressed_file(sh, src, &contents) < 0) {
++ ERR(sh, "Could not read %s.", src);
++ return -1;
++ }
++
++ if (contents.len > 0 &&
++ semanage_fc_sort(sh, contents.data, contents.len, &sorted,
++ &sorted_len) < 0) {
++ ERR(sh, "Could not sort file contexts from %s.", src);
++ goto cleanup;
++ }
++
++ if (!mode)
++ mode = S_IRUSR | S_IWUSR;
++ mask = umask(0);
++ out = open(dst, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
++ umask(mask);
++ if (out < 0) {
++ ERR(sh, "Could not open %s for writing.", dst);
++ goto cleanup;
++ }
++ if (write_full(out, header, strlen(header)) < 0) {
++ ERR(sh, "Write to %s failed.", dst);
++ goto cleanup;
++ }
++
++ if (sorted && sorted_len > 1 &&
++ write_full(out, sorted, sorted_len - 1) < 0) {
++ ERR(sh, "Write to %s failed.", dst);
++ goto cleanup;
++ }
++
++ if (close(out) < 0 && errno != EINTR) {
++ out = -1;
++ goto cleanup;
++ }
++ out = -1;
++
++ semanage_setfiles(sh, dst);
++ retval = 0;
++
++cleanup:
++ if (out >= 0)
++ close(out);
++ free(sorted);
++ unmap_compressed_file(&contents);
++ return retval;
++}
++
+ static int sefcontext_compile(semanage_handle_t *sh, const char *path)
+ {
+ int r;
+diff --git a/libsemanage/src/semanage_store.h b/libsemanage/src/semanage_store.h
+index 86ae093652f2..3480595127a9 100644
+--- a/libsemanage/src/semanage_store.h
++++ b/libsemanage/src/semanage_store.h
+@@ -156,6 +156,8 @@ int semanage_split_fc(semanage_handle_t *sh);
+ /* sort file context routines */
+ int semanage_fc_sort(semanage_handle_t *sh, const char *buf, size_t buf_len,
+ char **sorted_buf, size_t *sorted_buf_len);
++int semanage_sort_fc_file(semanage_handle_t *sh, const char *src,
++ const char *dst, mode_t mode);
+
+ /* sort netfilter context routines */
+ int semanage_nc_sort(semanage_handle_t *sh, const char *buf, size_t buf_len,
+--
+2.55.0
+
diff --git a/0002-libsemanage-genhomedircon-reject-users-with-a-relati.patch b/0002-libsemanage-genhomedircon-reject-users-with-a-relati.patch
new file mode 100644
index 0000000..87fa790
--- /dev/null
+++ b/0002-libsemanage-genhomedircon-reject-users-with-a-relati.patch
@@ -0,0 +1,46 @@
+From ed3001e29f66ce63ccdbd21420c1447522fe2f83 Mon Sep 17 00:00:00 2001
+From: Vit Mojzis <vmojzis@redhat.com>
+Date: Wed, 2 Sep 2026 13:38:29 +0200
+Subject: [PATCH] libsemanage/genhomedircon: reject users with a relative home
+ directory
+Content-type: text/plain
+
+If a user's home directory in the password database is empty or
+otherwise does not start with "/" (e.g. because of a broken NSS lookup
+or a malformed passwd entry), the HOME_DIR template ends up being turned
+into a regular expression such as "/.+", which matches any path on the
+filesystem. This causes genhomedircon to generate a file context that
+relabels far more of the filesystem than intended. Skip such users
+instead of using their home directory to build the regex.
+
+Signed-off-by: Vit Mojzis <vmojzis@redhat.com>
+Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
+---
+ libsemanage/src/genhomedircon.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c
+index ce7ea16722d8..e3f55f68b358 100644
+--- a/libsemanage/src/genhomedircon.c
++++ b/libsemanage/src/genhomedircon.c
+@@ -1110,6 +1110,17 @@ retry:
+ pwent->pw_dir[len] = '\0';
+ }
+
++ if (pwent->pw_dir[0] != '/') {
++ /* an empty (or otherwise relative) home directory would
++ * turn the HOME_DIR template into a regex that matches
++ * everything, e.g. "/.+", so refuse to use it */
++ WARN(s->h_semanage,
++ "user %s has an invalid home directory \"%s\", ignoring",
++ name, pwent->pw_dir);
++ retval = STATUS_SUCCESS;
++ goto cleanup;
++ }
++
+ if (strcmp(pwent->pw_dir, "/") == 0) {
+ /* don't relabel / genhomdircon checked to see if root
+ * was the user and if so, set his home directory to
+--
+2.55.0
+
diff --git a/changelog b/changelog
index 01dd7b8..4a6735e 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,12 @@
+* Tue Sep 08 2026 Petr Lautrbach <lautrbach@redhat.com> - 3.11-4
+- Optionally sort file_contexts.local by specificity
+
+* Wed Jul 22 2026 Python Maint <python-maint@redhat.com> - 3.11-3
+- Rebuilt for Python 3.15.0b4 ABI change
+
+* Thu Jul 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 3.11-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
+
* Wed Jul 01 2026 Petr Lautrbach <lautrbach@redhat.com> - 3.11-1
- SELinux userspace 3.11 release
diff --git a/libsemanage.spec b/libsemanage.spec
index d08b381..ed7dfd4 100644
--- a/libsemanage.spec
+++ b/libsemanage.spec
@@ -4,7 +4,7 @@
Summary: SELinux binary policy manipulation library
Name: libsemanage
Version: 3.11
-Release: 3%{?dist}
+Release: 4%{?dist}
License: LGPL-2.1-or-later
Source0: https://github.com/SELinuxProject/selinux/releases/download/%{version}/libsemanage-%{version}.tar.gz
Source1: https://github.com/SELinuxProject/selinux/releases/download/%{version}/libsemanage-%{version}.tar.gz.asc
@@ -12,6 +12,8 @@ Source2: https://github.com/bachradsusi.gpg
# git format-patch -N 3.11 -- libsemanage
# i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done
# Patch list start
+Patch0001: 0001-libsemanage-optionally-sort-file_contexts.local-by-s.patch
+Patch0002: 0002-libsemanage-genhomedircon-reject-users-with-a-relati.patch
# Patch list end
URL: https://github.com/SELinuxProject/selinux/wiki
VCS: git:https://github.com/SELinuxProject/selinux.git
@@ -158,10 +160,4 @@ cp %{SOURCE3} ${RPM_BUILD_ROOT}%{_sysconfdir}/selinux/semanage.conf
%{_libexecdir}/selinux/semanage_migrate_store
%changelog
-* Wed Jul 22 2026 Python Maint <python-maint@redhat.com> - 3.11-3
-- Rebuilt for Python 3.15.0b4 ABI change
-
-* Thu Jul 16 2026 Fedora Release Engineering <releng@fedoraproject.org> - 3.11-2
-- Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
-
%autochangelog
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-08 15:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-08 15:07 [rpms/libsemanage] rawhide: Optionally sort file_contexts.local by specificity Petr Lautrbach
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox