aed857
From 1707b9959e67e5e73987e1ff8a72189d24656fa0 Mon Sep 17 00:00:00 2001
aed857
From: Krzysztof Nowicki <krzysztof.a.nowicki+github@gmail.com>
aed857
Date: Wed, 28 Mar 2018 13:36:33 +0200
aed857
Subject: [PATCH] core: dont't remount /sys/fs/cgroup for relabel if not needed
aed857
 (#8595)
aed857
aed857
The initial fix for relabelling the cgroup filesystem for
aed857
SELinux delivered in commit 8739f23e3 was based on the assumption that
aed857
the cgroup filesystem is already populated once mount_setup() is
aed857
executed, which was true for my system. What I wasn't aware is that this
aed857
is the case only when another instance of systemd was running before
aed857
this one, which can happen if systemd is used in the initrd (for ex. by
aed857
dracut).
aed857
aed857
In case of a clean systemd start-up the cgroup filesystem is actually
aed857
being populated after mount_setup() and does not need relabelling as at
aed857
that moment the SELinux policy is already loaded. Since however the root
aed857
cgroup filesystem was remounted read-only in the meantime this operation
aed857
will now fail.
aed857
aed857
To fix this check for the filesystem mount flags before relabelling and
aed857
only remount ro->rw->ro if necessary and leave the filesystem read-write
aed857
otherwise.
aed857
aed857
Fixes #7901.
aed857
aed857
(cherry picked from commit 6f7729c1767998110c4460c85c94435c5782a613)
aed857
---
aed857
 src/core/mount-setup.c | 35 ++++++++++++++++++++++++++++++-----
aed857
 1 file changed, 30 insertions(+), 5 deletions(-)
aed857
aed857
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
aed857
index 7a2cae4a3..ed493cbe3 100644
aed857
--- a/src/core/mount-setup.c
aed857
+++ b/src/core/mount-setup.c
aed857
@@ -25,6 +25,8 @@
aed857
 #include <stdlib.h>
aed857
 #include <string.h>
aed857
 #include <assert.h>
aed857
+#include <sys/statfs.h>
aed857
+#include <sys/statvfs.h>
aed857
 #include <unistd.h>
aed857
 #include <ftw.h>
aed857
 
aed857
@@ -337,6 +339,31 @@ static int nftw_cb(
aed857
 
aed857
         return FTW_CONTINUE;
aed857
 };
aed857
+
aed857
+static int relabel_cgroup_filesystems(void) {
aed857
+        int r;
aed857
+        struct statfs st;
aed857
+
aed857
+        /* Temporarily remount the root cgroup filesystem to give it a proper label. Do this
aed857
+           only when the filesystem has been already populated by a previous instance of systemd
aed857
+           running from initrd. Otherwise don't remount anything and leave the filesystem read-write
aed857
+           for the cgroup filesystems to be mounted inside. */
aed857
+        r = statfs("/sys/fs/cgroup", &st);
aed857
+        if (r < 0) {
aed857
+                return log_error_errno(errno, "Failed to determine mount flags for /sys/fs/cgroup: %m");
aed857
+        }
aed857
+
aed857
+        if (st.f_flags & ST_RDONLY)
aed857
+                (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL);
aed857
+
aed857
+        (void) label_fix("/sys/fs/cgroup", false, false);
aed857
+        nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
aed857
+
aed857
+        if (st.f_flags & ST_RDONLY)
aed857
+                (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL);
aed857
+
aed857
+        return 0;
aed857
+}
aed857
 #endif
aed857
 
aed857
 int mount_setup(bool loaded_policy) {
aed857
@@ -369,11 +396,9 @@ int mount_setup(bool loaded_policy) {
aed857
                 nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
aed857
                 nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
aed857
 
aed857
-                /* Temporarily remount the root cgroup filesystem to give it a proper label. */
aed857
-                (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL);
aed857
-                label_fix("/sys/fs/cgroup", false, false);
aed857
-                nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
aed857
-                (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL);
aed857
+                r = relabel_cgroup_filesystems();
aed857
+                if (r < 0)
aed857
+                        return r;
aed857
 
aed857
                 after_relabel = now(CLOCK_MONOTONIC);
aed857