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

Commit 2cad3b0f authored by David Anderson's avatar David Anderson
Browse files

remount: Refactor verity disabling into a helper function.

Bug: 241179247
Test: remount
Change-Id: I1428eed91b8b4ff42b39c3a152a61f38779ab0e6
parent 0b0b2b6b
Loading
Loading
Loading
Loading
+25 −20
Original line number Diff line number Diff line
@@ -85,6 +85,10 @@ bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {

#if ALLOW_ADBD_DISABLE_VERITY == 0  // If we are a user build, provide stubs

bool fs_mgr_wants_overlayfs(FstabEntry*) {
    return false;
}

Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
    return {};
}
@@ -388,26 +392,6 @@ bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overl
    return false;
}

bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
    // Don't check entries that are managed by vold.
    if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;

    // *_other doesn't want overlayfs.
    if (entry->fs_mgr_flags.slot_select_other) return false;

    // Only concerned with readonly partitions.
    if (!(entry->flags & MS_RDONLY)) return false;

    // If unbindable, do not allow overlayfs as this could expose us to
    // security issues.  On Android, this could also be used to turn off
    // the ability to overlay an otherwise acceptable filesystem since
    // /system and /vendor are never bound(sic) to.
    if (entry->flags & MS_UNBINDABLE) return false;

    if (!fs_mgr_overlayfs_enabled(entry)) return false;

    return true;
}
constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";

bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
@@ -1284,6 +1268,27 @@ bool fs_mgr_overlayfs_invalid() {

}  // namespace

bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
    // Don't check entries that are managed by vold.
    if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;

    // *_other doesn't want overlayfs.
    if (entry->fs_mgr_flags.slot_select_other) return false;

    // Only concerned with readonly partitions.
    if (!(entry->flags & MS_RDONLY)) return false;

    // If unbindable, do not allow overlayfs as this could expose us to
    // security issues.  On Android, this could also be used to turn off
    // the ability to overlay an otherwise acceptable filesystem since
    // /system and /vendor are never bound(sic) to.
    if (entry->flags & MS_UNBINDABLE) return false;

    if (!fs_mgr_overlayfs_enabled(entry)) return false;

    return true;
}

Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
    Fstab candidates;
    for (const auto& entry : fstab) {
+77 −57
Original line number Diff line number Diff line
@@ -261,6 +261,74 @@ static RemountStatus GetRemountList(const Fstab& fstab, const std::vector<std::s
    return REMOUNT_SUCCESS;
}

struct RemountCheckResult {
    bool reboot_later = false;
    bool setup_overlayfs = false;
    bool disabled_verity = false;
    bool verity_error = false;
};

static RemountStatus CheckVerity(const FstabEntry& entry, RemountCheckResult* result) {
    if (!fs_mgr_is_verity_enabled(entry)) {
        return REMOUNT_SUCCESS;
    }
    if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
        return VERITY_PARTITION;
    }

    bool ok = false;

    std::unique_ptr<AvbOps, decltype(&::avb_ops_user_free)> ops(avb_ops_user_new(),
                                                                &::avb_ops_user_free);
    if (ops) {
        auto suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
        ok = avb_user_verity_set(ops.get(), suffix.c_str(), false);
    }
    if (!ok && fs_mgr_set_blk_ro(entry.blk_device, false)) {
        fec::io fh(entry.blk_device.c_str(), O_RDWR);
        ok = fh && fh.set_verity_status(false);
    }
    if (!ok) {
        return VERITY_PARTITION;
    }
    result->disabled_verity = true;
    result->reboot_later = true;
    return REMOUNT_SUCCESS;
}

static RemountStatus CheckVerityAndOverlayfs(Fstab* partitions, RemountCheckResult* result) {
    RemountStatus status = REMOUNT_SUCCESS;
    for (auto it = partitions->begin(); it != partitions->end();) {
        auto& entry = *it;
        const auto& mount_point = entry.mount_point;

        if (auto rv = CheckVerity(entry, result); rv != REMOUNT_SUCCESS) {
            LOG(ERROR) << "Skipping verified partition " << mount_point << " for remount";
            status = rv;
            it = partitions->erase(it);
            continue;
        }

        if (fs_mgr_wants_overlayfs(&entry)) {
            bool change = false;
            bool force = result->disabled_verity;
            if (!fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, force)) {
                LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
                status = BAD_OVERLAY;
                it = partitions->erase(it);
                continue;
            }
            if (change) {
                LOG(INFO) << "Using overlayfs for " << mount_point;
                result->reboot_later = true;
                result->setup_overlayfs = true;
            }
        }
        it++;
    }
    return status;
}

static int do_remount(int argc, char* argv[]) {
    RemountStatus retval = REMOUNT_SUCCESS;

@@ -342,64 +410,16 @@ static int do_remount(int argc, char* argv[]) {
    }

    // Check verity and optionally setup overlayfs backing.
    auto reboot_later = false;
    auto user_please_reboot_later = false;
    auto setup_overlayfs = false;
    auto just_disabled_verity = false;
    for (auto it = partitions.begin(); it != partitions.end();) {
        auto& entry = *it;
        auto& mount_point = entry.mount_point;
        if (fs_mgr_is_verity_enabled(entry)) {
            retval = VERITY_PARTITION;
            auto ret = false;
            if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") != "locked") {
                if (AvbOps* ops = avb_ops_user_new()) {
                    ret = avb_user_verity_set(
                            ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
                            false);
                    avb_ops_user_free(ops);
                }
                if (!ret && fs_mgr_set_blk_ro(entry.blk_device, false)) {
                    fec::io fh(entry.blk_device.c_str(), O_RDWR);
                    ret = fh && fh.set_verity_status(false);
                }
                if (ret) {
                    LOG(WARNING) << "Disabling verity for " << mount_point;
                    just_disabled_verity = true;
                    reboot_later = can_reboot;
                    user_please_reboot_later = true;
                }
            }
            if (!ret) {
                LOG(ERROR) << "Skipping " << mount_point << " for remount";
                it = partitions.erase(it);
                continue;
            }
        }
    RemountCheckResult check_result;
    retval = CheckVerityAndOverlayfs(&partitions, &check_result);

        auto change = false;
        errno = 0;
        if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, just_disabled_verity)) {
            if (change) {
                LOG(INFO) << "Using overlayfs for " << mount_point;
                reboot_later = can_reboot;
                user_please_reboot_later = true;
                setup_overlayfs = true;
            }
        } else if (errno) {
            PLOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
            retval = BAD_OVERLAY;
            it = partitions.erase(it);
            continue;
        }
        ++it;
    }
    bool auto_reboot = check_result.reboot_later && can_reboot;

    // If (1) remount requires a reboot to take effect, (2) system is currently
    // running a DSU guest and (3) DSU is disabled, then enable DSU so that the
    // next reboot would not take us back to the host system but stay within
    // the guest system.
    if (reboot_later) {
    if (auto_reboot) {
        if (auto gsid = android::gsi::GetGsiService()) {
            auto dsu_running = false;
            if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
@@ -430,9 +450,9 @@ static int do_remount(int argc, char* argv[]) {
        }
    }

    if (partitions.empty() || just_disabled_verity) {
        if (reboot_later) reboot(setup_overlayfs);
        if (user_please_reboot_later) {
    if (partitions.empty() || check_result.disabled_verity) {
        if (auto_reboot) reboot(check_result.setup_overlayfs);
        if (check_result.reboot_later) {
            return MUST_REBOOT;
        }
        LOG(WARNING) << "No partitions to remount";
@@ -518,8 +538,8 @@ static int do_remount(int argc, char* argv[]) {
        retval = REMOUNT_FAILED;
    }

    if (reboot_later) reboot(setup_overlayfs);
    if (user_please_reboot_later) {
    if (auto_reboot) reboot(check_result.setup_overlayfs);
    if (check_result.reboot_later) {
        LOG(INFO) << "Now reboot your device for settings to take effect";
        return 0;
    }
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@

android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);

bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
bool fs_mgr_overlayfs_mount_all(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);