diff --git a/fs_mgr/fs_mgr_overlayfs_control.cpp b/fs_mgr/fs_mgr_overlayfs_control.cpp index 2cc0d2d5e..50d8280e9 100644 --- a/fs_mgr/fs_mgr_overlayfs_control.cpp +++ b/fs_mgr/fs_mgr_overlayfs_control.cpp @@ -144,7 +144,8 @@ bool fs_mgr_overlayfs_setup_one(const std::string& overlay, const std::string& m if (fs_mgr_overlayfs_already_mounted(mount_point)) { return true; } - auto fsrec_mount_point = overlay + "/" + android::base::Basename(mount_point) + "/"; + const auto base = GetEncodedBaseDirForMountPoint(mount_point); + auto fsrec_mount_point = overlay + "/" + base + "/"; AutoSetFsCreateCon createcon(kOverlayfsFileContext); if (!createcon.Ok()) { @@ -286,10 +287,10 @@ bool fs_mgr_overlayfs_teardown_one(const std::string& overlay, const std::string } auto cleanup_all = mount_point.empty(); - const auto partition_name = android::base::Basename(mount_point); - const auto oldpath = top + (cleanup_all ? "" : ("/" + partition_name)); + const auto base = GetEncodedBaseDirForMountPoint(mount_point); + const auto oldpath = top + (cleanup_all ? "" : ("/" + base)); const auto newpath = cleanup_all ? overlay + "/." + kOverlayTopDir + ".teardown" - : top + "/." + partition_name + ".teardown"; + : top + "/." + base + ".teardown"; auto ret = fs_mgr_rm_all(newpath); if (!rename(oldpath.c_str(), newpath.c_str())) { if (change) *change = true; diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp index 9f17c06f7..0dadbffc6 100644 --- a/fs_mgr/fs_mgr_overlayfs_mount.cpp +++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp @@ -60,6 +60,7 @@ constexpr char kPhysicalDevice[] = "/dev/block/by-name/"; constexpr char kLowerdirOption[] = "lowerdir="; constexpr char kUpperdirOption[] = "upperdir="; +constexpr char kWorkdirOption[] = "workdir="; bool fs_mgr_is_dsu_running() { // Since android::gsi::CanBootIntoGsi() or android::gsi::MarkSystemAsGsi() is @@ -89,6 +90,14 @@ std::vector OverlayMountPoints() { return {kScratchMountPoint, kCacheMountPoint}; } +std::string GetEncodedBaseDirForMountPoint(const std::string& mount_point) { + std::string normalized_path; + if (mount_point.empty() || !android::base::Realpath(mount_point, &normalized_path)) { + return ""; + } + return android::base::StringReplace(normalized_path, "/", "@", true); +} + static bool fs_mgr_is_dir(const std::string& path) { struct stat st; return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode); @@ -202,21 +211,6 @@ static bool fs_mgr_overlayfs_enabled(FstabEntry* entry) { return has_shared_blocks; } -static std::string fs_mgr_get_overlayfs_candidate(const std::string& mount_point) { - if (!fs_mgr_is_dir(mount_point)) return ""; - const auto base = android::base::Basename(mount_point) + "/"; - for (const auto& overlay_mount_point : OverlayMountPoints()) { - auto dir = overlay_mount_point + "/" + kOverlayTopDir + "/" + base; - auto upper = dir + kUpperName; - if (!fs_mgr_is_dir(upper)) continue; - auto work = dir + kWorkName; - if (!fs_mgr_is_dir(work)) continue; - if (access(work.c_str(), R_OK | W_OK)) continue; - return dir; - } - return ""; -} - const std::string fs_mgr_mount_point(const std::string& mount_point) { if ("/"s != mount_point) return mount_point; return "/system"; @@ -225,16 +219,30 @@ const std::string fs_mgr_mount_point(const std::string& mount_point) { // default options for mount_point, returns empty string for none available. static std::string fs_mgr_get_overlayfs_options(const FstabEntry& entry) { const auto mount_point = fs_mgr_mount_point(entry.mount_point); - auto candidate = fs_mgr_get_overlayfs_candidate(mount_point); - if (candidate.empty()) return ""; - auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName + - ",workdir=" + candidate + kWorkName + android::fs_mgr::CheckOverlayfs().mount_flags; - for (const auto& flag : android::base::Split(entry.fs_options, ",")) { - if (android::base::StartsWith(flag, "context=")) { - ret += "," + flag; - } + if (!fs_mgr_is_dir(mount_point)) { + return ""; } - return ret; + const auto base = GetEncodedBaseDirForMountPoint(mount_point); + if (base.empty()) { + return ""; + } + for (const auto& overlay_mount_point : OverlayMountPoints()) { + const auto dir = overlay_mount_point + "/" + kOverlayTopDir + "/" + base + "/"; + const auto upper = dir + kUpperName; + const auto work = dir + kWorkName; + if (!fs_mgr_is_dir(upper) || !fs_mgr_is_dir(work) || access(work.c_str(), R_OK | W_OK)) { + continue; + } + auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + upper + "," + + kWorkdirOption + work + android::fs_mgr::CheckOverlayfs().mount_flags; + for (const auto& flag : android::base::Split(entry.fs_options, ",")) { + if (android::base::StartsWith(flag, "context=")) { + ret += "," + flag; + } + } + return ret; + } + return ""; } bool AutoSetFsCreateCon::Set(const std::string& context) { diff --git a/fs_mgr/fs_mgr_overlayfs_mount.h b/fs_mgr/fs_mgr_overlayfs_mount.h index f0afac1ed..98b9007b5 100644 --- a/fs_mgr/fs_mgr_overlayfs_mount.h +++ b/fs_mgr/fs_mgr_overlayfs_mount.h @@ -58,3 +58,4 @@ std::vector OverlayMountPoints(); bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true); bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry); android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab); +std::string GetEncodedBaseDirForMountPoint(const std::string& mount_point);