[PATCH v4 2/2] man: Document directory cycle handling of selinux_restorecon

Johannes Segitz <[email protected]> Tue, 28 Jul 2026 08:59:17 +0200
Newsgroups org.kernel.vger.selinux
Message-ID <[email protected]>
Skipping directory cycles instead of aborting the file tree walk is a
user visible behavior change: restorecon -R over a tree containing e.g.
a bind mount of an ancestor directory now logs a warning, skips the
cycle and completes successfully, instead of failing with ELOOP.

Document the new behavior for the flag SELINUX_RESTORECON_RECURSE,
including that a cycle is not an error and therefore is neither
affected by SELINUX_RESTORECON_ABORT_ON_ERROR nor counted by
SELINUX_RESTORECON_COUNT_ERRORS, and note the previous behavior in the
selinux_restorecon(3), restorecon(8) and setfiles(8) man pages.

Signed-off-by: Johannes Segitz <[email protected]>
---
 libselinux/man/man3/selinux_restorecon.3 | 28 ++++++++++++++++++++++++
 policycoreutils/setfiles/restorecon.8    | 20 +++++++++++++++++
 policycoreutils/setfiles/setfiles.8      | 14 ++++++++++++
 3 files changed, 62 insertions(+)

diff --git a/libselinux/man/man3/selinux_restorecon.3 b/libselinux/man/man3/selinux_restorecon.3
index 9bcd3d42..bafa86a2 100644
--- a/libselinux/man/man3/selinux_restorecon.3
+++ b/libselinux/man/man3/selinux_restorecon.3
@@ -99,6 +99,21 @@ and if successful write an SHA1 digest of the specfile entries to an
 extended attribute as described in the
 .B NOTES
 section.
+.RS
+Note that directory cycles encountered while descending, for example a bind
+mount of an ancestor directory or nested BTRFS subvolumes, are not followed.
+A warning is logged, the offending directory is not descended into and the
+file tree walk continues with the remaining entries. Such cycles are not
+treated as errors, therefore they neither abort the file tree walk when
+.B SELINUX_RESTORECON_ABORT_ON_ERROR
+is set, nor are they included in the count returned by
+.BR selinux_restorecon_get_skipped_errors (3)
+when
+.B SELINUX_RESTORECON_COUNT_ERRORS
+is set. See the
+.B NOTES
+section for details of the previous behavior.
+.RE
 .sp
 .B SELINUX_RESTORECON_VERBOSE
 log file label changes.
@@ -302,6 +317,19 @@ with the
 .B SELINUX_CB_LOG
 .I type
 option.
+.IP "6." 4
+Up to and including libselinux 3.11 a directory cycle was fatal:
+.BR selinux_restorecon ()
+logged an error, stopped the file tree walk and returned \-1 with
+.I errno
+set to
+.BR ELOOP ,
+regardless of the
+.B SELINUX_RESTORECON_ABORT_ON_ERROR
+and
+.B SELINUX_RESTORECON_COUNT_ERRORS
+flags. Since then the cycle is skipped as described above, so a file tree
+walk over a directory tree containing a cycle can complete successfully.
 .
 .SH "SEE ALSO"
 .BR selabel_get_digests_all_partial_matches (3),
diff --git a/policycoreutils/setfiles/restorecon.8 b/policycoreutils/setfiles/restorecon.8
index 982701c2..443f29ab 100644
--- a/policycoreutils/setfiles/restorecon.8
+++ b/policycoreutils/setfiles/restorecon.8
@@ -145,6 +145,9 @@ options are mutually exclusive.
 .TP
 .B \-R, \-r
 change files and directories file labels recursively (descend directories).
+Directory cycles are skipped, see the
+.B NOTES
+section for details.
 .br
 .TP
 .B \-v
@@ -240,6 +243,23 @@ and provided the
 .B \-n
 option is NOT set and recursive mode is set, files will be relabeled as
 required with the digests then being updated provided there are no errors.
+.IP "4." 4
+When descending directories (i.e. the
+.B \-R
+or
+.B \-r
+option is set)
+.B restorecon
+detects directory cycles, for example a bind mount of an ancestor directory or
+nested BTRFS subvolumes. A cycle is reported as a warning and the offending
+directory is not descended into, the remaining entries are still relabeled.
+A directory cycle is not counted as a relabeling error, so it does not affect
+the exit status and does not stop the file tree walk. Up to and including
+version 3.11 a directory cycle was instead treated as a fatal
+.B ELOOP
+error, terminating
+.B restorecon
+with a non-zero exit status.
 
 .SH EXAMPLE
 .nf
diff --git a/policycoreutils/setfiles/setfiles.8 b/policycoreutils/setfiles/setfiles.8
index d55b42db..17cabe37 100644
--- a/policycoreutils/setfiles/setfiles.8
+++ b/policycoreutils/setfiles/setfiles.8
@@ -307,6 +307,20 @@ and provided the
 .B \-n
 option is NOT set, files will be relabeled as required with the digests then
 being updated provided there are no errors.
+.IP "4." 4
+.B setfiles
+detects directory cycles while descending directories, for example a bind
+mount of an ancestor directory or nested BTRFS subvolumes. A cycle is reported
+as a warning and the offending directory is not descended into, the remaining
+entries are still relabeled. A directory cycle is not counted as a relabeling
+error, so it does not affect the exit status and does not stop the file tree
+walk. Up to and including version 3.11 a directory cycle was instead treated
+as a fatal
+.B ELOOP
+error, terminating
+.B setfiles
+with exit status
+.BR 255 .
 
 .SH EXAMPLE
 .nf
-- 
2.55.0