From 8d6cb98afe5818523933a4b708d5cc99be074cc9 Mon Sep 17 00:00:00 2001 From: Vit Mojzis Date: Mon, 26 Jan 2026 16:24:19 +0100 Subject: [PATCH] libselinux-3.9-4 - restorecon: Add option to count relabeled files Resolves: RHEL-144056 --- ...-Add-option-to-count-relabeled-files.patch | 199 ++++++++++++++++++ changelog | 3 + libselinux.spec | 3 +- 3 files changed, 204 insertions(+), 1 deletion(-) create mode 100644 0003-restorecon-Add-option-to-count-relabeled-files.patch diff --git a/0003-restorecon-Add-option-to-count-relabeled-files.patch b/0003-restorecon-Add-option-to-count-relabeled-files.patch new file mode 100644 index 0000000..1dbeac5 --- /dev/null +++ b/0003-restorecon-Add-option-to-count-relabeled-files.patch @@ -0,0 +1,199 @@ +From 54cbd31a219790932364d8b79f9a459ea3276bcf Mon Sep 17 00:00:00 2001 +From: Vit Mojzis +Date: Fri, 7 Nov 2025 18:41:36 +0100 +Subject: [PATCH] restorecon: Add option to count relabeled files + +This is useful in case we want to check that a remediation using +restorecon was successful (otherwise 0 is always returned, even if no +files were relabeled). + +Signed-off-by: Vit Mojzis +--- + libselinux/include/selinux/restorecon.h | 15 +++++++++++ + libselinux/src/libselinux.map | 5 ++++ + libselinux/src/selinux_restorecon.c | 34 ++++++++++++++++++++++--- + 3 files changed, 50 insertions(+), 4 deletions(-) + +diff --git a/libselinux/include/selinux/restorecon.h b/libselinux/include/selinux/restorecon.h +index 8dcc831b..aca218dc 100644 +--- a/libselinux/include/selinux/restorecon.h ++++ b/libselinux/include/selinux/restorecon.h +@@ -134,6 +134,11 @@ extern int selinux_restorecon_parallel(const char *pathname, + */ + #define SELINUX_RESTORECON_SET_USER_ROLE 0x40000 + ++/* ++ * Count the number of relabeled files (or would be relabeled if "nochange" was not set). ++ */ ++#define SELINUX_RESTORECON_COUNT_RELABELED 0x80000 ++ + /** + * selinux_restorecon_set_sehandle - Set the global fc handle. + * @hndl: specifies handle to set as the global fc handle. +@@ -228,6 +233,16 @@ extern int selinux_restorecon_xattr(const char *pathname, + */ + extern long unsigned selinux_restorecon_get_skipped_errors(void); + ++/* selinux_restorecon_get_relabeled_files - Get the number of relabeled files ++ * ++ * If SELINUX_RESTORECON_COUNT_RELABELED was passed to selinux_restorecon(3) or ++ * selinux_restorecon_parallel(3), this function returns the number of files ++ * that were successfully relabeled. ++ * If the SELINUX_RESTORECON_NOCHANGE flag was set, this function returns ++ * the number of files that would be relabeled. ++ */ ++extern long unsigned selinux_restorecon_get_relabeled_files(void); ++ + #ifdef __cplusplus + } + #endif +diff --git a/libselinux/src/libselinux.map b/libselinux/src/libselinux.map +index ab002f01..95cd53b0 100644 +--- a/libselinux/src/libselinux.map ++++ b/libselinux/src/libselinux.map +@@ -262,3 +262,8 @@ LIBSELINUX_3.9 { + global: + context_to_str; + } LIBSELINUX_3.8; ++ ++LIBSELINUX_3.10 { ++ global: ++ selinux_restorecon_get_relabeled_files; ++} LIBSELINUX_3.9; +diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c +index 23546cb0..28749ee2 100644 +--- a/libselinux/src/selinux_restorecon.c ++++ b/libselinux/src/selinux_restorecon.c +@@ -69,6 +69,9 @@ static struct dir_xattr *dir_xattr_last; + /* Number of errors ignored during the file tree walk. */ + static long unsigned skipped_errors; + ++/* Number of successfully relabeled files or files that would be relabeled */ ++static long unsigned relabeled_files; ++ + /* restorecon_flags for passing to restorecon_sb() */ + struct rest_flags { + bool nochange; +@@ -88,6 +91,7 @@ struct rest_flags { + bool warnonnomatch; + bool conflicterror; + bool count_errors; ++ bool count_relabeled; + }; + + static void restorecon_init(void) +@@ -650,11 +654,12 @@ out: + } + + static int restorecon_sb(const char *pathname, const struct stat *sb, +- const struct rest_flags *flags, bool first) ++ const struct rest_flags *flags, bool first, bool *updated_out) + { + char *newcon = NULL; + char *curcon = NULL; + int rc; ++ bool updated = false; + const char *lookup_path = pathname; + + if (rootpath) { +@@ -736,7 +741,6 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, + } + + if (curcon == NULL || strcmp(curcon, newcon) != 0) { +- bool updated = false; + + if (!flags->set_specctx && curcon && + (is_context_customizable(curcon) > 0)) { +@@ -796,9 +800,14 @@ static int restorecon_sb(const char *pathname, const struct stat *sb, + syslog(LOG_INFO, "labeling %s to %s\n", + pathname, newcon); + } ++ ++ /* Note: relabel counting handled by caller */ ++ + } + + out: ++ if (updated_out) ++ *updated_out = updated; + rc = 0; + out1: + freecon(curcon); +@@ -887,6 +896,7 @@ struct rest_state { + bool abort; + int error; + long unsigned skipped_errors; ++ long unsigned relabeled_files; + int saved_errno; + pthread_mutex_t mutex; + }; +@@ -1010,8 +1020,9 @@ loop_body: + if (state->parallel) + pthread_mutex_unlock(&state->mutex); + ++ bool updated = false; + error = restorecon_sb(ent_path, &ent_st, &state->flags, +- first); ++ first, &updated); + + if (state->parallel) { + pthread_mutex_lock(&state->mutex); +@@ -1030,6 +1041,8 @@ loop_body: + state->skipped_errors++; + else + state->error = error; ++ } else if (updated && state->flags.count_relabeled) { ++ state->relabeled_files++; + } + break; + } +@@ -1087,6 +1100,8 @@ static int selinux_restorecon_common(const char *pathname_orig, + SELINUX_RESTORECON_IGNORE_DIGEST) ? true : false; + state.flags.count_errors = (restorecon_flags & + SELINUX_RESTORECON_COUNT_ERRORS) ? true : false; ++ state.flags.count_relabeled = (restorecon_flags & ++ SELINUX_RESTORECON_COUNT_RELABELED) ? true : false; + state.setrestorecondigest = true; + + state.head = NULL; +@@ -1094,6 +1109,7 @@ static int selinux_restorecon_common(const char *pathname_orig, + state.abort = false; + state.error = 0; + state.skipped_errors = 0; ++ state.relabeled_files = 0; + state.saved_errno = 0; + + struct stat sb; +@@ -1215,7 +1231,11 @@ static int selinux_restorecon_common(const char *pathname_orig, + goto cleanup; + } + +- error = restorecon_sb(pathname, &sb, &state.flags, true); ++ bool updated = false; ++ error = restorecon_sb(pathname, &sb, &state.flags, true, &updated); ++ if (updated && state.flags.count_relabeled) { ++ state.relabeled_files++; ++ } + goto cleanup; + } + +@@ -1341,6 +1361,7 @@ out: + (void) fts_close(state.fts); + errno = state.saved_errno; + cleanup: ++ relabeled_files = state.relabeled_files; + if (state.flags.add_assoc) { + if (state.flags.verbose) + filespec_eval(); +@@ -1618,3 +1639,8 @@ long unsigned selinux_restorecon_get_skipped_errors(void) + { + return skipped_errors; + } ++ ++long unsigned selinux_restorecon_get_relabeled_files(void) ++{ ++ return relabeled_files; ++} +-- +2.52.0 + diff --git a/changelog b/changelog index ab84cbc..8160103 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,6 @@ +* Mon Jan 26 2026 Vit Mojzis - 3.9-4 +- restorecon: Add option to count relabeled files (RHEL-144056) + * Mon Dec 15 2025 Veronika Syncakova - 3.9-3 - Rebuild to accomodate changes in swig (RHEL-118812) diff --git a/libselinux.spec b/libselinux.spec index c203c20..3a1a656 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -4,7 +4,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 3.9 -Release: 3%{?dist} +Release: 4%{?dist} License: LicenseRef-Fedora-Public-Domain # https://github.com/SELinuxProject/selinux/wiki/Releases Source0: https://github.com/SELinuxProject/selinux/releases/download/%{version}/libselinux-%{version}.tar.gz @@ -21,6 +21,7 @@ Url: https://github.com/SELinuxProject/selinux/wiki # Patch list start Patch0001: 0001-Use-SHA-2-instead-of-SHA-1.patch Patch0002: 0002-libselinux-Ignore-files-removed-during-relabeling.patch +Patch0003: 0003-restorecon-Add-option-to-count-relabeled-files.patch # Patch list end BuildRequires: gcc make BuildRequires: ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre2-devel