Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3609bf70 authored by Yi-Yo Chiang's avatar Yi-Yo Chiang Committed by Gerrit Code Review
Browse files

Merge changes I6debf849,I6cdbe8c5 into main

* changes:
  fs_mgr_overlayfs: Remove temp dir under /dev when aborting
  fs_mgr_overlayfs: Support remounting submounts
parents b28db2a9 05d3adb7
Loading
Loading
Loading
Loading
+65 −41
Original line number Original line Diff line number Diff line
@@ -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);
        }
        }
@@ -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
@@ -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);
        }
        }
@@ -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;
}
}
+0 −19
Original line number Original line Diff line number Diff line
@@ -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) {}
@@ -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;
}
}


@@ -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.