fs_mgr_overlayfs: Fix "/" mount propagation type after remount

If remounting "/system" caused "/" to be set to MS_PRIVATE, restore it
to MS_SHARED after remount.

Bug: 306124139
Test: adb-remount-test
Test: remount /system and verify /proc/self/mountinfo
Change-Id: I12bc2ccdaf7d2b2de330064b61a8533b96defe00
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index 4cadeec..cdbac00 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -288,10 +288,6 @@
     if (ret) {
         PERROR << "__mount(target=" << mount_point
                << ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
-        // If "/system" doesn't look like a mountpoint, retry with "/".
-        if (errno == EINVAL && mount_point == "/system") {
-            return fs_mgr_overlayfs_set_shared_mount("/", shared_flag);
-        }
         return false;
     }
     return true;
@@ -393,6 +389,8 @@
     bool retval = true;
     bool move_dir_shared = true;
     bool parent_shared = true;
+    bool root_shared = true;
+    bool root_made_private = false;
 
     // There could be multiple mount entries with the same mountpoint.
     // Group these entries together with stable_sort, and keep only the last entry of a group.
@@ -419,6 +417,9 @@
             (mount_point == "/system" && entry.mount_point == "/")) {
             parent_shared = entry.shared_flag;
         }
+        if (entry.mount_point == "/") {
+            root_shared = entry.shared_flag;
+        }
     }
 
     // Precondition is that kMoveMountTempDir is MS_PRIVATE, otherwise don't try to move any
@@ -429,7 +430,13 @@
 
     // Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE.
     // This could happen if its parent mount is remounted later.
-    fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+    if (!fs_mgr_overlayfs_set_shared_mount(mount_point, false)) {
+        // If failed to set "/system" mount type, it might be due to "/system" not being a valid
+        // mountpoint after switch root. Retry with "/" in this case.
+        if (errno == EINVAL && mount_point == "/system") {
+            root_made_private = fs_mgr_overlayfs_set_shared_mount("/", false);
+        }
+    }
 
     for (const auto& entry : mountinfo) {
         // Find all immediate submounts.
@@ -515,6 +522,9 @@
     if (parent_shared) {
         fs_mgr_overlayfs_set_shared_mount(mount_point, true);
     }
+    if (root_shared && root_made_private) {
+        fs_mgr_overlayfs_set_shared_mount("/", true);
+    }
 
     return retval;
 }