Loading fs_mgr/fs_mgr_overlayfs_mount.cpp +65 −41 Original line number Original line Diff line number Diff line Loading @@ -381,54 +381,86 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { auto retval = true; auto retval = true; struct move_entry { struct MoveEntry { std::string mount_point; std::string mount_point; std::string dir; std::string dir; bool shared_flag; bool shared_flag; }; }; std::vector<move_entry> move; std::vector<MoveEntry> moved_mounts; auto parent_private = false; auto parent_private = false; auto parent_made_private = false; auto parent_made_private = false; auto dev_private = false; auto dev_private = false; auto dev_made_private = false; auto dev_made_private = false; for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) { // 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. // Only move mount the last entry in an over mount group, because the other entries are // overshadowed and only the filesystem mounted with the last entry participates in file // pathname resolution. auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo"); std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point < rhs.mount_point; }); std::reverse(mountinfo.begin(), mountinfo.end()); auto erase_from = std::unique( mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; }); mountinfo.erase(erase_from, mountinfo.end()); std::reverse(mountinfo.begin(), mountinfo.end()); // mountinfo is reversed twice, so still is in lexical sorted order. for (const auto& entry : mountinfo) { if ((entry.mount_point == mount_point) && !entry.shared_flag) { if ((entry.mount_point == mount_point) && !entry.shared_flag) { parent_private = true; parent_private = true; } } if ((entry.mount_point == "/dev") && !entry.shared_flag) { if ((entry.mount_point == "/dev") && !entry.shared_flag) { dev_private = true; dev_private = true; } } } // 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. if (!parent_private) { parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); } for (const auto& entry : mountinfo) { // Find all immediate submounts. if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) { if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) { continue; continue; } } if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) { // Exclude duplicated or more specific entries. return android::base::StartsWith(entry.mount_point, it.mount_point + "/"); if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) { }) != move.end()) { return it.mount_point == entry.mount_point || android::base::StartsWith(entry.mount_point, it.mount_point + "/"); }) != moved_mounts.end()) { continue; continue; } } // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of // entries of |moved_mounts|. // use as the bound directory in /dev. // use as the bound directory in /dev. MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; { AutoSetFsCreateCon createcon; AutoSetFsCreateCon createcon; auto new_context = fs_mgr_get_context(entry.mount_point); auto new_context = fs_mgr_get_context(entry.mount_point); if (new_context.empty() || !createcon.Set(new_context)) { if (new_context.empty() || !createcon.Set(new_context)) { continue; continue; } } move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; const auto target = mkdtemp(new_entry.dir.data()); const auto target = mkdtemp(new_entry.dir.data()); if (!createcon.Restore()) { return false; } if (!target) { if (!target) { retval = false; retval = false; PERROR << "temporary directory for MS_BIND"; PERROR << "temporary directory for MS_MOVE"; continue; continue; } } if (!createcon.Restore()) { if (!parent_private && !parent_made_private) { retval = false; parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); rmdir(new_entry.dir.c_str()); continue; } } } if (new_entry.shared_flag) { if (new_entry.shared_flag) { new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false); new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false); } } Loading @@ -437,9 +469,10 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { if (new_entry.shared_flag) { if (new_entry.shared_flag) { fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true); fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true); } } rmdir(new_entry.dir.c_str()); continue; continue; } } move.emplace_back(std::move(new_entry)); moved_mounts.push_back(std::move(new_entry)); } } // hijack __mount() report format to help triage // hijack __mount() report format to help triage Loading @@ -463,7 +496,7 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { } } // Move submounts back. // Move submounts back. for (const auto& entry : move) { for (const auto& entry : moved_mounts) { if (!dev_private && !dev_made_private) { if (!dev_private && !dev_made_private) { dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false); dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false); } } Loading Loading @@ -658,22 +691,13 @@ Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { !fs_mgr_wants_overlayfs(&new_entry)) { !fs_mgr_wants_overlayfs(&new_entry)) { continue; continue; } } auto new_mount_point = fs_mgr_mount_point(entry.mount_point); const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point); auto duplicate_or_more_specific = false; if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) { for (auto it = candidates.begin(); it != candidates.end();) { return fs_mgr_mount_point(it.mount_point) == new_mount_point; auto it_mount_point = fs_mgr_mount_point(it->mount_point); }) != candidates.end()) { if ((it_mount_point == new_mount_point) || continue; (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) { duplicate_or_more_specific = true; break; } if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) { it = candidates.erase(it); } else { ++it; } } } if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry)); candidates.push_back(std::move(new_entry)); } } return candidates; return candidates; } } Loading fs_mgr/fs_mgr_remount.cpp +0 −19 Original line number Original line Diff line number Diff line Loading @@ -88,17 +88,6 @@ const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) { return entry.mount_point; return entry.mount_point; } } const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) { auto mount_point = system_mount_point(entry); auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(), [&mount_point](const auto& entry) { return android::base::StartsWith(mount_point, system_mount_point(entry) + "/"); }); if (it == overlayfs_candidates.end()) return nullptr; return &(*it); } class MyLogger { class MyLogger { public: public: explicit MyLogger(bool verbose) : verbose_(verbose) {} explicit MyLogger(bool verbose) : verbose_(verbose) {} Loading Loading @@ -196,9 +185,6 @@ static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) { if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) { if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) { return candidate_entry->fs_type == entry.fs_type; return candidate_entry->fs_type == entry.fs_type; } } if (GetWrappedEntry(candidates, entry)) { return false; } return true; return true; } } Loading Loading @@ -252,11 +238,6 @@ bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fs } } const FstabEntry* entry = &*it; const FstabEntry* entry = &*it; if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) { LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point << ", switching"; entry = wrap; } // If it's already remounted, include it so it gets gracefully skipped // If it's already remounted, include it so it gets gracefully skipped // later on. // later on. Loading Loading
fs_mgr/fs_mgr_overlayfs_mount.cpp +65 −41 Original line number Original line Diff line number Diff line Loading @@ -381,54 +381,86 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { auto retval = true; auto retval = true; struct move_entry { struct MoveEntry { std::string mount_point; std::string mount_point; std::string dir; std::string dir; bool shared_flag; bool shared_flag; }; }; std::vector<move_entry> move; std::vector<MoveEntry> moved_mounts; auto parent_private = false; auto parent_private = false; auto parent_made_private = false; auto parent_made_private = false; auto dev_private = false; auto dev_private = false; auto dev_made_private = false; auto dev_made_private = false; for (auto& entry : ReadMountinfoFromFile("/proc/self/mountinfo")) { // 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. // Only move mount the last entry in an over mount group, because the other entries are // overshadowed and only the filesystem mounted with the last entry participates in file // pathname resolution. auto mountinfo = ReadMountinfoFromFile("/proc/self/mountinfo"); std::stable_sort(mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point < rhs.mount_point; }); std::reverse(mountinfo.begin(), mountinfo.end()); auto erase_from = std::unique( mountinfo.begin(), mountinfo.end(), [](const auto& lhs, const auto& rhs) { return lhs.mount_point == rhs.mount_point; }); mountinfo.erase(erase_from, mountinfo.end()); std::reverse(mountinfo.begin(), mountinfo.end()); // mountinfo is reversed twice, so still is in lexical sorted order. for (const auto& entry : mountinfo) { if ((entry.mount_point == mount_point) && !entry.shared_flag) { if ((entry.mount_point == mount_point) && !entry.shared_flag) { parent_private = true; parent_private = true; } } if ((entry.mount_point == "/dev") && !entry.shared_flag) { if ((entry.mount_point == "/dev") && !entry.shared_flag) { dev_private = true; dev_private = true; } } } // 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. if (!parent_private) { parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); } for (const auto& entry : mountinfo) { // Find all immediate submounts. if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) { if (!android::base::StartsWith(entry.mount_point, mount_point + "/")) { continue; continue; } } if (std::find_if(move.begin(), move.end(), [&entry](const auto& it) { // Exclude duplicated or more specific entries. return android::base::StartsWith(entry.mount_point, it.mount_point + "/"); if (std::find_if(moved_mounts.begin(), moved_mounts.end(), [&entry](const auto& it) { }) != move.end()) { return it.mount_point == entry.mount_point || android::base::StartsWith(entry.mount_point, it.mount_point + "/"); }) != moved_mounts.end()) { continue; continue; } } // mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of // entries of |moved_mounts|. // use as the bound directory in /dev. // use as the bound directory in /dev. MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; { AutoSetFsCreateCon createcon; AutoSetFsCreateCon createcon; auto new_context = fs_mgr_get_context(entry.mount_point); auto new_context = fs_mgr_get_context(entry.mount_point); if (new_context.empty() || !createcon.Set(new_context)) { if (new_context.empty() || !createcon.Set(new_context)) { continue; continue; } } move_entry new_entry = {std::move(entry.mount_point), "/dev/TemporaryDir-XXXXXX", entry.shared_flag}; const auto target = mkdtemp(new_entry.dir.data()); const auto target = mkdtemp(new_entry.dir.data()); if (!createcon.Restore()) { return false; } if (!target) { if (!target) { retval = false; retval = false; PERROR << "temporary directory for MS_BIND"; PERROR << "temporary directory for MS_MOVE"; continue; continue; } } if (!createcon.Restore()) { if (!parent_private && !parent_made_private) { retval = false; parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false); rmdir(new_entry.dir.c_str()); continue; } } } if (new_entry.shared_flag) { if (new_entry.shared_flag) { new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false); new_entry.shared_flag = fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, false); } } Loading @@ -437,9 +469,10 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { if (new_entry.shared_flag) { if (new_entry.shared_flag) { fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true); fs_mgr_overlayfs_set_shared_mount(new_entry.mount_point, true); } } rmdir(new_entry.dir.c_str()); continue; continue; } } move.emplace_back(std::move(new_entry)); moved_mounts.push_back(std::move(new_entry)); } } // hijack __mount() report format to help triage // hijack __mount() report format to help triage Loading @@ -463,7 +496,7 @@ static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) { } } // Move submounts back. // Move submounts back. for (const auto& entry : move) { for (const auto& entry : moved_mounts) { if (!dev_private && !dev_made_private) { if (!dev_private && !dev_made_private) { dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false); dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false); } } Loading Loading @@ -658,22 +691,13 @@ Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { !fs_mgr_wants_overlayfs(&new_entry)) { !fs_mgr_wants_overlayfs(&new_entry)) { continue; continue; } } auto new_mount_point = fs_mgr_mount_point(entry.mount_point); const auto new_mount_point = fs_mgr_mount_point(new_entry.mount_point); auto duplicate_or_more_specific = false; if (std::find_if(candidates.begin(), candidates.end(), [&](const auto& it) { for (auto it = candidates.begin(); it != candidates.end();) { return fs_mgr_mount_point(it.mount_point) == new_mount_point; auto it_mount_point = fs_mgr_mount_point(it->mount_point); }) != candidates.end()) { if ((it_mount_point == new_mount_point) || continue; (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) { duplicate_or_more_specific = true; break; } if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) { it = candidates.erase(it); } else { ++it; } } } if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry)); candidates.push_back(std::move(new_entry)); } } return candidates; return candidates; } } Loading
fs_mgr/fs_mgr_remount.cpp +0 −19 Original line number Original line Diff line number Diff line Loading @@ -88,17 +88,6 @@ const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) { return entry.mount_point; return entry.mount_point; } } const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const FstabEntry& entry) { auto mount_point = system_mount_point(entry); auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(), [&mount_point](const auto& entry) { return android::base::StartsWith(mount_point, system_mount_point(entry) + "/"); }); if (it == overlayfs_candidates.end()) return nullptr; return &(*it); } class MyLogger { class MyLogger { public: public: explicit MyLogger(bool verbose) : verbose_(verbose) {} explicit MyLogger(bool verbose) : verbose_(verbose) {} Loading Loading @@ -196,9 +185,6 @@ static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) { if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) { if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) { return candidate_entry->fs_type == entry.fs_type; return candidate_entry->fs_type == entry.fs_type; } } if (GetWrappedEntry(candidates, entry)) { return false; } return true; return true; } } Loading Loading @@ -252,11 +238,6 @@ bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fs } } const FstabEntry* entry = &*it; const FstabEntry* entry = &*it; if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) { LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point << ", switching"; entry = wrap; } // If it's already remounted, include it so it gets gracefully skipped // If it's already remounted, include it so it gets gracefully skipped // later on. // later on. Loading