/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>

#include <iostream>
#include <string>
#include <thread>
#include <utility>
#include <vector>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android/os/IVold.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <fs_mgr_overlayfs.h>
#include <fs_mgr_priv.h>
#include <fstab/fstab.h>
#include <libavb_user/libavb_user.h>
#include <libgsi/libgsid.h>

#include "fs_mgr_overlayfs_control.h"
#include "fs_mgr_overlayfs_mount.h"

using namespace std::literals;
using android::fs_mgr::Fstab;
using android::fs_mgr::FstabEntry;

namespace {

void usage() {
    const std::string progname = getprogname();
    if (progname == "disable-verity" || progname == "enable-verity" ||
        progname == "set-verity-state") {
        std::cout << "Usage: disable-verity\n"
                  << "       enable-verity\n"
                  << "       set-verity-state [0|1]\n"
                  << R"(
Options:
    -h --help       this help
    -R --reboot     automatic reboot if needed for new settings to take effect
    -v --verbose    be noisy)"
                  << std::endl;
    } else {
        std::cout << "Usage: " << progname << " [-h] [-R] [-T fstab_file] [partition]...\n"
                  << R"(
Options:
    -h --help       this help
    -R --reboot     disable verity & reboot to facilitate remount
    -v --verbose    be noisy
    -T --fstab      custom fstab file location
    partition       specific partition(s) (empty does all)

Remount specified partition(s) read-write, by name or mount point.
-R notwithstanding, verity must be disabled on partition(s).
-R within a DSU guest system reboots into the DSU instead of the host system,
this command would enable DSU (one-shot) if not already enabled.)"
                  << std::endl;
    }
}

const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
    if (entry.mount_point == "/") return "/system";
    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 {
  public:
    explicit MyLogger(bool verbose) : verbose_(verbose) {}

    void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
                    const char* file, unsigned int line, const char* message) {
        // By default, print ERROR logs and logs of this program (does not start with '[')
        // Print [libfs_mgr] INFO logs only if -v is given.
        if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
            fprintf(stderr, "%s\n", message);
        }
        logd_(id, severity, tag, file, line, message);
    }

  private:
    android::base::LogdLogger logd_;
    bool verbose_;
};

[[noreturn]] void reboot(const std::string& name) {
    LOG(INFO) << "Rebooting device for new settings to take effect";
    ::sync();
    android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
    ::sleep(60);
    LOG(ERROR) << "Failed to reboot";
    ::exit(1);
}

static android::sp<android::os::IVold> GetVold() {
    auto sm = android::defaultServiceManager();
    while (true) {
        if (auto binder = sm->checkService(android::String16("vold"))) {
            if (auto vold = android::interface_cast<android::os::IVold>(binder)) {
                return vold;
            }
        }
        std::this_thread::sleep_for(2s);
    }
}

static bool ReadFstab(const char* fstab_file, android::fs_mgr::Fstab* fstab) {
    if (fstab_file) {
        return android::fs_mgr::ReadFstabFromFile(fstab_file, fstab);
    }
    if (!android::fs_mgr::ReadDefaultFstab(fstab)) {
        return false;
    }

    // Manufacture a / entry from /proc/mounts if missing.
    if (!GetEntryForMountPoint(fstab, "/system") && !GetEntryForMountPoint(fstab, "/")) {
        android::fs_mgr::Fstab mounts;
        if (android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
            if (auto entry = GetEntryForMountPoint(&mounts, "/")) {
                if (entry->fs_type != "rootfs") fstab->emplace_back(*entry);
            }
        }
    }
    return true;
}

bool VerifyCheckpointing() {
    if (!android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
        !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
        return true;
    }

    // Virtual A/B devices can use /data as backing storage; make sure we're
    // not checkpointing.
    auto vold = GetVold();
    bool checkpointing = false;
    if (!vold->isCheckpointing(&checkpointing).isOk()) {
        LOG(ERROR) << "Could not determine checkpointing status.";
        return false;
    }
    if (checkpointing) {
        LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
        LOG(ERROR) << "To force end checkpointing, call 'vdc checkpoint commitChanges'";
        LOG(ERROR) << "Warning: this can lead to data corruption if rolled back.";
        return false;
    }
    return true;
}

static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
    if (entry.fs_mgr_flags.vold_managed || entry.fs_mgr_flags.recovery_only ||
        entry.fs_mgr_flags.slot_select_other) {
        return false;
    }
    if (!(entry.flags & MS_RDONLY)) {
        return false;
    }
    if (entry.fs_type == "vfat") {
        return false;
    }
    if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) {
        return candidate_entry->fs_type == entry.fs_type;
    }
    if (GetWrappedEntry(candidates, entry)) {
        return false;
    }
    return true;
}

static Fstab::const_iterator FindPartition(const Fstab& fstab, const std::string& partition) {
    Fstab mounts;
    if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
        LOG(ERROR) << "Failed to read /proc/mounts";
        return fstab.end();
    }

    for (auto iter = fstab.begin(); iter != fstab.end(); iter++) {
        const auto mount_point = system_mount_point(*iter);
        if (partition == mount_point || partition == android::base::Basename(mount_point)) {
            // In case fstab has multiple entries, pick the one that matches the
            // actual mounted filesystem type.
            auto proc_mount_point = (iter->mount_point == "/system") ? "/" : iter->mount_point;
            auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
            if (mounted && mounted->fs_type == iter->fs_type) {
                return iter;
            }
        }
    }
    return fstab.end();
}

static Fstab GetAllRemountablePartitions(Fstab& fstab) {
    auto candidates = fs_mgr_overlayfs_candidate_list(fstab);

    Fstab partitions;
    for (const auto& entry : fstab) {
        if (IsRemountable(candidates, entry)) {
            partitions.emplace_back(entry);
        }
    }
    return partitions;
}

bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fstab* partitions) {
    auto candidates = fs_mgr_overlayfs_candidate_list(fstab);

    for (const auto& arg : argv) {
        std::string partition = arg;
        if (partition == "/") {
            partition = "/system";
        }

        auto it = FindPartition(fstab, partition);
        if (it == fstab.end()) {
            LOG(ERROR) << "Unknown partition " << arg;
            return false;
        }

        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
        // later on.
        if (!fs_mgr_overlayfs_already_mounted(entry->mount_point) &&
            !IsRemountable(candidates, *entry)) {
            LOG(ERROR) << "Invalid partition " << arg;
            return false;
        }
        if (GetEntryForMountPoint(partitions, entry->mount_point) != nullptr) {
            continue;
        }
        partitions->emplace_back(*entry);
    }

    return true;
}

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

bool CheckOverlayfs(Fstab* partitions, RemountCheckResult* result) {
    bool ok = true;
    for (auto it = partitions->begin(); it != partitions->end();) {
        auto& entry = *it;
        const auto& mount_point = entry.mount_point;

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

bool EnableDsuIfNeeded() {
    auto gsid = android::gsi::GetGsiService();
    if (!gsid) {
        return true;
    }

    auto dsu_running = false;
    if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
        LOG(ERROR) << "Failed to get DSU running state: " << status;
        return false;
    }
    auto dsu_enabled = false;
    if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
        LOG(ERROR) << "Failed to get DSU enabled state: " << status;
        return false;
    }
    if (dsu_running && !dsu_enabled) {
        std::string dsu_slot;
        if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
            LOG(ERROR) << "Failed to get active DSU slot: " << status;
            return false;
        }
        LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
                     "DSU guest system after reboot";
        int error = 0;
        if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error); !status.isOk()) {
            LOG(ERROR) << "Failed to enable DSU: " << status;
            return false;
        }
        if (error != android::gsi::IGsiService::INSTALL_OK) {
            LOG(ERROR) << "Failed to enable DSU, error code: " << error;
            return false;
        }
        LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
    }
    return true;
}

bool RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
    // unlock the r/o key for the mount point device
    if (entry.fs_mgr_flags.logical) {
        fs_mgr_update_logical_partition(&entry);
    }
    auto blk_device = entry.blk_device;
    auto mount_point = entry.mount_point;

    auto found = false;
    for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
        auto& rentry = *it;
        if (mount_point == rentry.mount_point) {
            blk_device = rentry.blk_device;
            found = true;
            break;
        }
        // Find overlayfs mount point?
        if ((mount_point == "/" && rentry.mount_point == "/system") ||
            (mount_point == "/system" && rentry.mount_point == "/")) {
            blk_device = rentry.blk_device;
            mount_point = "/system";
            found = true;
            break;
        }
    }
    if (!found) {
        PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
        return true;
    }
    if (blk_device == "/dev/root") {
        auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
        if (from_fstab) blk_device = from_fstab->blk_device;
    }
    fs_mgr_set_blk_ro(blk_device, false);

    // Find system-as-root mount point?
    if ((mount_point == "/system") && !GetEntryForMountPoint(&mounts, mount_point) &&
        GetEntryForMountPoint(&mounts, "/")) {
        mount_point = "/";
    }

    // Now remount!
    for (const auto& mnt_point : {mount_point, entry.mount_point}) {
        if (::mount(blk_device.c_str(), mnt_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
                    nullptr) == 0) {
            LOG(INFO) << "Remounted " << mnt_point << " as RW";
            return true;
        }
        if (errno != EINVAL || mount_point == entry.mount_point) {
            break;
        }
    }

    PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
    return false;
}

struct SetVerityStateResult {
    bool success = false;
    bool want_reboot = false;
};

SetVerityStateResult SetVerityState(bool enable_verity) {
    const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
    std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
                                                              &avb_ops_user_free);
    if (!ops) {
        LOG(ERROR) << "Error getting AVB ops";
        return {};
    }
    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
        LOG(ERROR) << "Error setting verity state";
        return {};
    }
    bool verification_enabled = false;
    if (!avb_user_verification_get(ops.get(), ab_suffix.c_str(), &verification_enabled)) {
        LOG(ERROR) << "Error getting verification state";
        return {};
    }
    if (!verification_enabled) {
        LOG(WARNING) << "AVB verification is disabled, "
                     << (enable_verity ? "enabling" : "disabling")
                     << " verity state may have no effect";
        return {.success = true, .want_reboot = false};
    }
    const auto verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
    const bool was_enabled = (verity_mode != "disabled");
    if ((was_enabled && enable_verity) || (!was_enabled && !enable_verity)) {
        LOG(INFO) << "Verity is already " << (enable_verity ? "enabled" : "disabled");
        return {.success = true, .want_reboot = false};
    }
    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
    return {.success = true, .want_reboot = true};
}

bool SetupOrTeardownOverlayfs(bool enable) {
    bool want_reboot = false;
    if (enable) {
        Fstab fstab;
        if (!ReadDefaultFstab(&fstab)) {
            LOG(ERROR) << "Could not read fstab.";
            return want_reboot;
        }
        if (!fs_mgr_overlayfs_setup(fstab, nullptr, &want_reboot)) {
            LOG(ERROR) << "Overlayfs setup failed.";
            return want_reboot;
        }
        if (want_reboot) {
            printf("enabling overlayfs\n");
        }
    } else {
        auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
        if (rv == OverlayfsTeardownResult::Error) {
            LOG(ERROR) << "Overlayfs teardown failed.";
            return want_reboot;
        }
        if (rv == OverlayfsTeardownResult::Busy) {
            LOG(ERROR) << "Overlayfs is still active until reboot.";
            return true;
        }
        if (want_reboot) {
            printf("disabling overlayfs\n");
        }
    }
    return want_reboot;
}

bool do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
                RemountCheckResult* check_result) {
    Fstab partitions;
    if (partition_args.empty()) {
        partitions = GetAllRemountablePartitions(fstab);
    } else {
        if (!GetRemountList(fstab, partition_args, &partitions)) {
            return false;
        }
    }

    // Disable verity.
    auto verity_result = SetVerityState(false /* enable_verity */);

    // Treat error as fatal and suggest reboot only if verity is enabled.
    // TODO(b/260041315): We check the device mapper for any "<partition>-verity" device present
    // instead of checking ro.boot.veritymode because emulator has incorrect property value.
    bool must_disable_verity = false;
    for (const auto& partition : partitions) {
        if (fs_mgr_is_verity_enabled(partition)) {
            must_disable_verity = true;
            break;
        }
    }
    if (must_disable_verity) {
        if (!verity_result.success) {
            return false;
        }
        if (verity_result.want_reboot) {
            check_result->reboot_later = true;
            check_result->disabled_verity = true;
        }
    }

    // Optionally setup overlayfs backing.
    bool ok = CheckOverlayfs(&partitions, check_result);

    if (partitions.empty() || check_result->disabled_verity) {
        if (partitions.empty()) {
            LOG(WARNING) << "No remountable partitions were found.";
        }
        return ok;
    }

    // Mount overlayfs.
    if (!fs_mgr_overlayfs_mount_all(&partitions)) {
        LOG(WARNING) << "Cannot mount overlayfs for some partitions";
        // Continue regardless to handle raw remount case.
    }

    // Get actual mounts _after_ overlayfs has been added.
    android::fs_mgr::Fstab mounts;
    if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
        PLOG(ERROR) << "Failed to read /proc/mounts";
        return false;
    }

    // Remount selected partitions.
    for (auto& entry : partitions) {
        if (RemountPartition(fstab, mounts, entry)) {
            check_result->remounted_anything = true;
        } else {
            ok = false;
        }
    }
    return ok;
}

}  // namespace

int main(int argc, char* argv[]) {
    // Do not use MyLogger() when running as clean_scratch_files, as stdout/stderr of daemon process
    // are discarded.
    if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
        android::fs_mgr::CleanupOldScratchFiles();
        return EXIT_SUCCESS;
    }

    android::base::InitLogging(argv, MyLogger(false /* verbose */));

    const char* fstab_file = nullptr;
    bool auto_reboot = false;
    bool verbose = false;
    std::vector<std::string> partition_args;

    struct option longopts[] = {
            {"fstab", required_argument, nullptr, 'T'},
            {"help", no_argument, nullptr, 'h'},
            {"reboot", no_argument, nullptr, 'R'},
            {"verbose", no_argument, nullptr, 'v'},
            {0, 0, nullptr, 0},
    };
    for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
        switch (opt) {
            case 'h':
                usage();
                return EXIT_SUCCESS;
            case 'R':
                auto_reboot = true;
                break;
            case 'T':
                if (fstab_file) {
                    LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
                    usage();
                    return EXIT_FAILURE;
                }
                fstab_file = optarg;
                break;
            case 'v':
                verbose = true;
                break;
            default:
                LOG(ERROR) << "Bad argument -" << char(opt);
                usage();
                return EXIT_FAILURE;
        }
    }

    if (verbose) {
        android::base::SetLogger(MyLogger(verbose));
    }

    bool remount = false;
    bool enable_verity = false;
    const std::string progname = getprogname();
    if (progname == "enable-verity") {
        enable_verity = true;
    } else if (progname == "disable-verity") {
        enable_verity = false;
    } else if (progname == "set-verity-state") {
        if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
            enable_verity = (argv[optind] == "1"s);
        } else {
            usage();
            return EXIT_FAILURE;
        }
    } else {
        remount = true;
        for (; optind < argc; ++optind) {
            partition_args.emplace_back(argv[optind]);
        }
    }

    // Make sure we are root.
    if (::getuid() != 0) {
        LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
        return EXIT_FAILURE;
    }

    // If somehow this executable is delivered on a "user" build, it can
    // not function, so providing a clear message to the caller rather than
    // letting if fall through and provide a lot of confusing failure messages.
    if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
        LOG(ERROR) << "Device must be userdebug build";
        return EXIT_FAILURE;
    }

    if (android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange") {
        LOG(ERROR) << "Device must be bootloader unlocked";
        return EXIT_FAILURE;
    }

    // Start a threadpool to service waitForService() callbacks as
    // fs_mgr_overlayfs_* might call waitForService() to get the image service.
    android::ProcessState::self()->startThreadPool();

    if (!remount) {
        auto ret = SetVerityState(enable_verity);

        // Disable any overlayfs unconditionally if we want verity enabled.
        // Enable overlayfs only if verity is successfully disabled or is already disabled.
        if (enable_verity || ret.success) {
            ret.want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
        }

        if (ret.want_reboot) {
            if (auto_reboot) {
                reboot(progname);
            }
            std::cout << "Reboot the device for new settings to take effect" << std::endl;
        }
        return ret.success ? EXIT_SUCCESS : EXIT_FAILURE;
    }

    // Make sure checkpointing is disabled if necessary.
    if (!VerifyCheckpointing()) {
        return EXIT_FAILURE;
    }

    // Read the selected fstab.
    Fstab fstab;
    if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
        PLOG(ERROR) << "Failed to read fstab";
        return EXIT_FAILURE;
    }

    RemountCheckResult check_result;
    bool remount_success = do_remount(fstab, partition_args, &check_result);

    if (check_result.disabled_verity && check_result.setup_overlayfs) {
        LOG(INFO) << "Verity disabled; overlayfs enabled.";
    } else if (check_result.disabled_verity) {
        LOG(INFO) << "Verity disabled.";
    } else if (check_result.setup_overlayfs) {
        LOG(INFO) << "Overlayfs enabled.";
    }
    if (remount_success && check_result.remounted_anything) {
        LOG(INFO) << "Remount succeeded";
    } else if (!remount_success) {
        LOG(ERROR) << "Remount failed";
    }
    if (check_result.reboot_later) {
        if (auto_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 (!EnableDsuIfNeeded()) {
                LOG(ERROR) << "Unable to automatically enable DSU";
                return EXIT_FAILURE;
            }
            reboot("remount");
        } else {
            LOG(INFO) << "Now reboot your device for settings to take effect";
        }
        return EXIT_SUCCESS;
    }
    return remount_success ? EXIT_SUCCESS : EXIT_FAILURE;
}
