Re: [PATCH] selinux_restorecon: Do not exit on directory cycles

Stephen Smalley <[email protected]> Thu, 23 Jul 2026 10:55:48 -0400
Newsgroups org.kernel.vger.selinux
Message-ID <CAEjxPJ5KfidbsqrUe07F8sdssdqEtEUsBUDgGqn4dm4RZUcyOw@mail.gmail.com>
On Thu, Jul 23, 2026 at 4:56 AM Johannes Segitz <[email protected]> wrote:
>
> All other failures are handled gracefully. Directory cycles can e.g.
> happen on BTRFS filesystems with subvolumes. Skip them and continue
> instead of exiting

This is a user-visible behavior change so we should note it; restorecon -R
on a tree with a bind mount of an ancestor will now complete with rc 0 and
only a WARNING rather than aborting with ELOOP.

Missing Signed-off-by line and the patch still doesn't apply for me
(did you send it using git send-email and against current selinux/main?)
but also see comment below on the code.

> ---
>  libselinux/src/selinux_restorecon.c | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c
> index 30f1b836..fdefc92c 100644
> --- a/libselinux/src/selinux_restorecon.c
> +++ b/libselinux/src/selinux_restorecon.c
> @@ -1393,15 +1393,14 @@ static void *selinux_restorecon_thread(void *arg)
>                 if (is_dir) {
>                         if (descend && walk_is_cycle(state, ent_sb.st_dev,
>                                                      ent_sb.st_ino)) {
> -                               selinux_log(SELINUX_ERROR,
> +                               selinux_log(SELINUX_WARNING,
>                                             "Directory cycle on %s.\n",
>                                             ent_path);
>                                 close(ent_fd);
> -                               close(rd_fd);
> -                               errno = ELOOP;
> -                               state->error = -1;
> -                               state->abort = true;
> -                               goto finish;
> +                               if (rd_fd >= 0)
> +                                       close(rd_fd);

You don't need the if (rd_fd >= 0) guard here because this branch is only
executed if descend == true so that's always true.

> +                               prune_pathbuf(state);
> +                               continue;
>                         }
>
>                         if (state->sfsb.f_type == SYSFS_MAGIC &&
> --
> 2.55.0