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

Commit 18a6cc2b authored by Yi-Yo Chiang's avatar Yi-Yo Chiang
Browse files

Make fs_mgr_overlayfs_mount_fstab_entry() available for user builds

Rename fs_mgr_overlayfs_mount_fstab_entry() to
fs_mgr_mount_overlayfs_fstab_entry() and move it out of
fs_mgr_overlayfs.cpp to make it available for user builds.

Add checks to unsure overlayfs mount point doesn't contain symbolic
link or /../.

Check the mount point with an allowlist if user build. The mount point
should either be /vendor, /product ... or their submounts, or strict
submounts of /mnt/vendor and /mnt/product.

Bug: 188862155
Test: Boot test with overlayfs mount entries on user build
Change-Id: I3b60dfa4b63cf2ae0754f53d1d08365aa7be1ee0
Merged-In: I3b60dfa4b63cf2ae0754f53d1d08365aa7be1ee0
(cherry picked from commit 23816e84)
parent 85703980
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -2265,3 +2265,72 @@ std::string fs_mgr_get_super_partition_name(int slot) {
    }
    return LP_METADATA_DEFAULT_PARTITION_NAME;
}

bool fs_mgr_mount_overlayfs_fstab_entry(const FstabEntry& entry) {
    auto overlayfs_valid_result = fs_mgr_overlayfs_valid();
    if (overlayfs_valid_result == OverlayfsValidResult::kNotSupported) {
        LERROR << __FUNCTION__ << "(): kernel does not support overlayfs";
        return false;
    }

#if ALLOW_ADBD_DISABLE_VERITY == 0
    // Allowlist the mount point if user build.
    static const std::vector<const std::string> kAllowedPaths = {
            "/odm", "/odm_dlkm", "/oem", "/product", "/system_ext", "/vendor", "/vendor_dlkm",
    };
    static const std::vector<const std::string> kAllowedPrefixes = {
            "/mnt/product/",
            "/mnt/vendor/",
    };
    if (std::none_of(kAllowedPaths.begin(), kAllowedPaths.end(),
                     [&entry](const auto& path) -> bool {
                         return entry.mount_point == path ||
                                StartsWith(entry.mount_point, path + "/");
                     }) &&
        std::none_of(kAllowedPrefixes.begin(), kAllowedPrefixes.end(),
                     [&entry](const auto& prefix) -> bool {
                         return entry.mount_point != prefix &&
                                StartsWith(entry.mount_point, prefix);
                     })) {
        LERROR << __FUNCTION__
               << "(): mount point is forbidden on user build: " << entry.mount_point;
        return false;
    }
#endif  // ALLOW_ADBD_DISABLE_VERITY == 0

    // Create the mount point in case it doesn't exist.
    mkdir(entry.mount_point.c_str(), 0755);

    // Ensure that mount point exists and doesn't contain symbolic link or /../.
    std::string mount_point;
    if (!Realpath(entry.mount_point, &mount_point)) {
        PERROR << __FUNCTION__ << "(): failed to realpath " << entry.mount_point;
        return false;
    }
    if (entry.mount_point != mount_point) {
        LERROR << __FUNCTION__ << "(): mount point must be a canonicalized path: realpath "
               << entry.mount_point << " = " << mount_point;
        return false;
    }

    auto options = "lowerdir=" + entry.lowerdir;
    if (overlayfs_valid_result == OverlayfsValidResult::kOverrideCredsRequired) {
        options += ",override_creds=off";
    }

    // Use "overlay-" + entry.blk_device as the mount() source, so that adb-remout-test don't
    // confuse this with adb remount overlay, whose device name is "overlay".
    // Overlayfs is a pseudo filesystem, so the source device is a symbolic value and isn't used to
    // back the filesystem. However the device name would be shown in /proc/mounts.
    auto source = "overlay-" + entry.blk_device;
    auto report = "__mount(source=" + source + ",target=" + entry.mount_point + ",type=overlay," +
                  options + ")=";
    auto ret = mount(source.c_str(), entry.mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
                     options.c_str());
    if (ret) {
        PERROR << report << ret;
        return false;
    }
    LINFO << report << ret;
    return true;
}
+0 −32
Original line number Diff line number Diff line
@@ -92,10 +92,6 @@ bool fs_mgr_overlayfs_mount_all(Fstab*) {
    return false;
}

bool fs_mgr_overlayfs_mount_fstab_entry(const android::fs_mgr::FstabEntry&) {
    return false;
}

std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab*) {
    return {};
}
@@ -1299,34 +1295,6 @@ static void TryMountScratch() {
    }
}

bool fs_mgr_overlayfs_mount_fstab_entry(const android::fs_mgr::FstabEntry& entry) {
    if (fs_mgr_overlayfs_invalid()) return false;

    // Create the mount point in case it doesn't exist.
    mkdir(entry.mount_point.c_str(), 0755);

    auto options = kLowerdirOption + entry.lowerdir;
    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
        options += ",override_creds=off";
    }

    // Use "overlay-" + entry.blk_device as the mount() source, so that adb-remout-test don't
    // confuse this with adb remount overlay, whose device name is "overlay".
    // Overlayfs is a pseudo filesystem, so the source device is a symbolic value and isn't used to
    // back the filesystem. However the device name would be shown in /proc/mounts.
    auto source = "overlay-" + entry.blk_device;
    auto report = "__mount(source=" + source + ",target=" + entry.mount_point + ",type=overlay," +
                  options + ")=";
    auto ret = mount(source.c_str(), entry.mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
                     options.c_str());
    if (ret) {
        PERROR << report << ret;
        return false;
    }
    LINFO << report << ret;
    return true;
}

bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
    auto ret = false;
    if (fs_mgr_overlayfs_invalid()) return ret;
+5 −0
Original line number Diff line number Diff line
@@ -131,3 +131,8 @@ int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab);
// Finds the dm_bow device on which this block device is stacked, or returns
// empty string
std::string fs_mgr_find_bow_device(const std::string& block_device);

// Like fs_mgr_do_mount_one() but for overlayfs fstab entries.
// Unlike fs_mgr_overlayfs, mount overlayfs without upperdir and workdir, so the
// filesystem cannot be remount read-write.
bool fs_mgr_mount_overlayfs_fstab_entry(const android::fs_mgr::FstabEntry& entry);
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);

bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
bool fs_mgr_overlayfs_mount_fstab_entry(const android::fs_mgr::FstabEntry& entry);
std::vector<std::string> fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
                            bool* change = nullptr, bool force = true);
+1 −1
Original line number Diff line number Diff line
@@ -574,7 +574,7 @@ bool FirstStageMount::MountPartitions() {

    for (const auto& entry : fstab_) {
        if (entry.fs_type == "overlay") {
            fs_mgr_overlayfs_mount_fstab_entry(entry);
            fs_mgr_mount_overlayfs_fstab_entry(entry);
        }
    }