]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount-setup: port from nftw() to recurse_dir()
authorLennart Poettering <lennart@poettering.net>
Fri, 1 Oct 2021 13:56:27 +0000 (15:56 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 7 Oct 2021 09:59:23 +0000 (11:59 +0200)
src/shared/mount-setup.c

index ae148541d7d3a54b2938899d293c83348640eecc..7057a8763edcda3d9cc309bf43d61d154eff226e 100644 (file)
@@ -1,7 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <errno.h>
-#include <ftw.h>
 #include <stdlib.h>
 #include <sys/mount.h>
 #include <sys/statvfs.h>
@@ -9,9 +8,9 @@
 
 #include "alloc-util.h"
 #include "bus-util.h"
+#include "cgroup-setup.h"
 #include "cgroup-util.h"
 #include "conf-files.h"
-#include "cgroup-setup.h"
 #include "dev-setup.h"
 #include "dirent-util.h"
 #include "efi-loader.h"
@@ -27,6 +26,7 @@
 #include "mountpoint-util.h"
 #include "nulstr-util.h"
 #include "path-util.h"
+#include "recurse-dir.h"
 #include "set.h"
 #include "smack-util.h"
 #include "strv.h"
@@ -365,27 +365,46 @@ int mount_cgroup_controllers(void) {
 }
 
 #if HAVE_SELINUX || ENABLE_SMACK
-static int nftw_cb(
-                const char *fpath,
-                const struct stat *sb,
-                int tflag,
-                struct FTW *ftwbuf) {
-
-        /* No need to label /dev twice in a row... */
-        if (_unlikely_(ftwbuf->level == 0))
-                return FTW_CONTINUE;
-
-        (void) label_fix(fpath, 0);
-
-        /* /run/initramfs is static data and big, no need to
-         * dynamically relabel its contents at boot... */
-        if (_unlikely_(ftwbuf->level == 1 &&
-                      tflag == FTW_D &&
-                      streq(fpath, "/run/initramfs")))
-                return FTW_SKIP_SUBTREE;
-
-        return FTW_CONTINUE;
-};
+static int relabel_cb(
+                RecurseDirEvent event,
+                const char *path,
+                int dir_fd,
+                int inode_fd,
+                const struct dirent *de,
+                const struct statx *sx,
+                void *userdata) {
+
+        switch (event) {
+
+        case RECURSE_DIR_LEAVE:
+        case RECURSE_DIR_SKIP_MOUNT:
+                /* If we already saw this dirent when entering it or this is a dirent that on a different
+                 * mount, don't relabel it. */
+                return RECURSE_DIR_CONTINUE;
+
+        case RECURSE_DIR_ENTER:
+                /* /run/initramfs is static data and big, no need to dynamically relabel its contents at boot... */
+                if (path_equal(path, "/run/initramfs"))
+                        return RECURSE_DIR_SKIP_ENTRY;
+
+                _fallthrough_;
+
+        default:
+                /* Otherwise, label it, even if we had trouble stat()ing it and similar. SELinux can figure this out */
+                (void) label_fix(path, 0);
+                return RECURSE_DIR_CONTINUE;
+        }
+}
+
+static int relabel_tree(const char *path) {
+        int r;
+
+        r = recurse_dir_at(AT_FDCWD, path, 0, UINT_MAX, RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_SAME_MOUNT, relabel_cb, NULL);
+        if (r < 0)
+                log_debug_errno(r, "Failed to recursively relabel '%s': %m", path);
+
+        return r;
+}
 
 static int relabel_cgroup_filesystems(void) {
         int r;
@@ -404,7 +423,7 @@ static int relabel_cgroup_filesystems(void) {
                         (void) mount_nofollow(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL);
 
                 (void) label_fix("/sys/fs/cgroup", 0);
-                (void) nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+                (void) relabel_tree("/sys/fs/cgroup");
 
                 if (st.f_flags & ST_RDONLY)
                         (void) mount_nofollow(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL);
@@ -468,7 +487,7 @@ static int relabel_extra(void) {
 
                         log_debug("Relabelling additional file/directory '%s'.", line);
                         (void) label_fix(line, 0);
-                        (void) nftw(line, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+                        (void) relabel_tree(line);
                         c++;
                 }
 
@@ -505,7 +524,7 @@ int mount_setup(bool loaded_policy, bool leave_propagation) {
                 before_relabel = now(CLOCK_MONOTONIC);
 
                 FOREACH_STRING(i, "/dev", "/dev/shm", "/run")
-                        (void) nftw(i, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
+                        (void) relabel_tree(i);
 
                 (void) relabel_cgroup_filesystems();