From 28113cf3f6a471d190ff0de5c5a4c8b5d17b3e7c Mon Sep 17 00:00:00 2001 From: Yi-Yo Chiang Date: Thu, 23 Nov 2023 14:47:58 +0800 Subject: [PATCH] second-stage-init: Don't move submounts when mounting overlayfs Right now there is a bug in second-stage-init that screws up the overlayfs overrides. This happens because: 1. second-stage-init mount_all might be executed in the "bootstrap" mount namespace. 2. In order to move (MS_MOVE) submounts in fs_mgr_overlayfs_mount_all(), we change the mount propagation type of overridden filesystems to MS_PRIVATE. 3. This means that the "default" mount namespace would not receive the mount events of the overlayfs overrides. 4. After /data is mounted, init would switch to the "default" namespace. This means any new processes spawned after this period would not be able to see the overlayfs overrides. We fix this by changing the mount order of second-stage-init mount_all to mount the overlayfs override of a partition immediately after the partition is mounted. This way we don't need to move any submounts as there can't be any, thus we don't need to set any mountpoint to MS_PRIVATE so the mount event of the overlayfs would be propagated to the "default" mount namespace, too. Bug: 309407859 Bug: 306124139 Test: adb-remount-test Test: verify that overlayfs tookover successfully from second-stage-init Change-Id: If2ff4852516292ccbc7abdeebe0e9a7c1c7ba606 --- fs_mgr/fs_mgr.cpp | 9 ++-- fs_mgr/fs_mgr_overlayfs_mount.cpp | 74 +++++++++++++++++++++++-------- fs_mgr/include/fs_mgr_overlayfs.h | 3 ++ 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index faea5eb7a..35c8c6396 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -1388,6 +1388,8 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { return {FS_MGR_MNTALL_FAIL, userdata_mounted}; } + bool scratch_can_be_mounted = true; + // Keep i int to prevent unsigned integer overflow from (i = top_idx - 1), // where top_idx is 0. It will give SIGABRT for (int i = 0; i < static_cast(fstab->size()); i++) { @@ -1520,6 +1522,9 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { if (current_entry.mount_point == "/data") { userdata_mounted = true; } + + MountOverlayfs(attempted_entry, &scratch_can_be_mounted); + // Success! Go get the next one. continue; } @@ -1604,10 +1609,6 @@ MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) { set_type_property(encryptable); -#if ALLOW_ADBD_DISABLE_VERITY == 1 // "userdebug" build - fs_mgr_overlayfs_mount_all(fstab); -#endif - if (error_count) { return {FS_MGR_MNTALL_FAIL, userdata_mounted}; } else { diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp index cdbac00c6..e0b6721ad 100644 --- a/fs_mgr/fs_mgr_overlayfs_mount.cpp +++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp @@ -302,6 +302,25 @@ static bool fs_mgr_overlayfs_move_mount(const std::string& source, const std::st return true; } +static bool fs_mgr_overlayfs_mount(const std::string& mount_point, const std::string& options) { + auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay"; + for (const auto& opt : android::base::Split(options, ",")) { + if (android::base::StartsWith(opt, kUpperdirOption)) { + report = report + "," + opt; + break; + } + } + report = report + ")="; + auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME, + options.c_str()); + if (ret) { + PERROR << report << ret; + } else { + LINFO << report << ret; + } + return !ret; +} + struct mount_info { std::string mount_point; bool shared_flag; @@ -488,25 +507,7 @@ static bool fs_mgr_overlayfs_mount_one(const FstabEntry& fstab_entry) { moved_mounts.push_back(std::move(new_entry)); } - // hijack __mount() report format to help triage - auto report = "__mount(source=overlay,target="s + mount_point + ",type=overlay"; - const auto opt_list = android::base::Split(options, ","); - for (const auto& opt : opt_list) { - if (android::base::StartsWith(opt, kUpperdirOption)) { - report = report + "," + opt; - break; - } - } - report = report + ")="; - - auto ret = mount("overlay", mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME, - options.c_str()); - if (ret) { - retval = false; - PERROR << report << ret; - } else { - LINFO << report << ret; - } + retval &= fs_mgr_overlayfs_mount(mount_point, options); // Move submounts back. for (const auto& entry : moved_mounts) { @@ -814,3 +815,38 @@ bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overl } return false; } + +namespace android { +namespace fs_mgr { + +void MountOverlayfs(const FstabEntry& fstab_entry, bool* scratch_can_be_mounted) { + if (!OverlayfsSetupAllowed()) { + return; + } + const auto candidates = fs_mgr_overlayfs_candidate_list({fstab_entry}); + if (candidates.empty()) { + return; + } + const auto& entry = candidates.front(); + if (fs_mgr_is_verity_enabled(entry)) { + return; + } + const auto mount_point = fs_mgr_mount_point(entry.mount_point); + if (fs_mgr_overlayfs_already_mounted(mount_point)) { + return; + } + if (*scratch_can_be_mounted) { + *scratch_can_be_mounted = false; + if (!fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) { + TryMountScratch(); + } + } + const auto options = fs_mgr_get_overlayfs_options(entry); + if (options.empty()) { + return; + } + fs_mgr_overlayfs_mount(mount_point, options); +} + +} // namespace fs_mgr +} // namespace android diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index bdaabbf07..bf68b2c81 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -30,6 +30,9 @@ bool fs_mgr_overlayfs_is_setup(); namespace android { namespace fs_mgr { +// Mount the overlayfs override for |fstab_entry|. +void MountOverlayfs(const FstabEntry& fstab_entry, bool* scratch_can_be_mounted); + void MapScratchPartitionIfNeeded(Fstab* fstab, const std::function&)>& init);