remount: Merge 'remount' and 'set-verity-state'

Dedup fs_mgr_remount.cpp and set-verity-state.cpp by merging them
together and make '/system/bin/set-verity-state' a symlink to
'/system/bin/remount'.

Bug: 241688845
Test: adb-remount-test
Change-Id: I42a2344b9bdac112bf8767d428a99cb020267546
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index bebf19e..dd61272 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -251,41 +251,8 @@
     },
     symlinks: [
         "clean_scratch_files",
-    ],
-}
-
-cc_binary {
-    name: "set-verity-state",
-    srcs: ["set-verity-state.cpp"],
-    shared_libs: [
-        "libbase",
-        "libbinder",
-        "libcrypto",
-        "libcrypto_utils",
-        "libfs_mgr_binder",
-        "libutils",
-    ],
-    static_libs: [
-        "libavb_user",
-    ],
-    header_libs: [
-        "libcutils_headers",
-    ],
-
-    cflags: ["-Werror"],
-    cppflags: [
-        "-DALLOW_DISABLE_VERITY=0",
-    ],
-    product_variables: {
-        debuggable: {
-            cppflags: [
-                "-UALLOW_DISABLE_VERITY",
-                "-DALLOW_DISABLE_VERITY=1",
-            ],
-        },
-    },
-    symlinks: [
-        "enable-verity",
         "disable-verity",
+        "enable-verity",
+        "set-verity-state",
     ],
 }
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index dfc8983..eac3ff2 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -22,6 +22,7 @@
 #include <sys/vfs.h>
 #include <unistd.h>
 
+#include <iostream>
 #include <string>
 #include <thread>
 #include <utility>
@@ -33,6 +34,7 @@
 #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>
@@ -50,17 +52,34 @@
 namespace {
 
 void usage() {
-    LOG(INFO) << getprogname()
-              << " [-h] [-R] [-T fstab_file] [partition]...\n"
-                 "\t-h --help\tthis help\n"
-                 "\t-R --reboot\tdisable verity & reboot to facilitate remount\n"
-                 "\t-T --fstab\tcustom fstab file location\n"
-                 "\tpartition\tspecific partition(s) (empty does all)\n"
-                 "\n"
-                 "Remount specified partition(s) read-write, by name or mount point.\n"
-                 "-R notwithstanding, verity must be disabled on partition(s).\n"
-                 "-R within a DSU guest system reboots into the DSU instead of the host system,\n"
-                 "this command would enable DSU (one-shot) if not already enabled.";
+    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) {
@@ -120,8 +139,6 @@
     }
 }
 
-}  // namespace
-
 enum RemountStatus {
     REMOUNT_SUCCESS = 0,
     UNKNOWN_PARTITION = 5,
@@ -421,6 +438,68 @@
     return REMOUNT_FAILED;
 }
 
+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", "");
+    bool verity_enabled = false;
+
+    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_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
+        LOG(ERROR) << "Error getting verity state";
+        return {};
+    }
+
+    if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
+        LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
+        return {.success = true, .want_reboot = false};
+    }
+
+    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
+        LOG(ERROR) << "Error setting verity state";
+        return {};
+    }
+
+    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
+    return {.success = true, .want_reboot = true};
+}
+
+bool SetupOrTeardownOverlayfs(bool enable) {
+    bool want_reboot = false;
+    if (enable) {
+        if (!fs_mgr_overlayfs_setup(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;
+}
+
 static int do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
                       RemountCheckResult* check_result) {
     Fstab partitions;
@@ -466,6 +545,8 @@
     return retval;
 }
 
+}  // 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.
@@ -518,8 +599,25 @@
         android::base::SetLogger(MyLogger(verbose));
     }
 
-    for (; argc > optind; ++optind) {
-        partition_args.emplace_back(argv[optind]);
+    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 1;
+        }
+    } else {
+        remount = true;
+        for (; optind < argc; ++optind) {
+            partition_args.emplace_back(argv[optind]);
+        }
     }
 
     // Make sure we are root.
@@ -541,6 +639,36 @@
         return 1;
     }
 
+    // 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) {
+        // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+        // contract, androidboot.vbmeta.digest is set by the bootloader
+        // when using AVB).
+        if (android::base::GetProperty("ro.boot.vbmeta.digest", "").empty()) {
+            LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
+            return 1;
+        }
+
+        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 ? 0 : 1;
+    }
+
     // Make sure checkpointing is disabled if necessary.
     if (auto rv = VerifyCheckpointing(); rv != REMOUNT_SUCCESS) {
         return rv;
diff --git a/fs_mgr/set-verity-state.cpp b/fs_mgr/set-verity-state.cpp
deleted file mode 100644
index 84ee01f..0000000
--- a/fs_mgr/set-verity-state.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * 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 <getopt.h>
-#include <stdio.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <binder/ProcessState.h>
-#include <cutils/android_reboot.h>
-#include <fs_mgr_overlayfs.h>
-#include <libavb_user/libavb_user.h>
-
-#include "fs_mgr_priv_overlayfs.h"
-
-using namespace std::string_literals;
-
-namespace {
-
-void print_usage() {
-    printf("Usage:\n"
-           "\tdisable-verity\n"
-           "\tenable-verity\n"
-           "\tset-verity-state [0|1]\n"
-           "Options:\n"
-           "\t-h --help\tthis help\n"
-           "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
-           "\t-v --verbose\tbe noisy\n");
-}
-
-#ifdef ALLOW_DISABLE_VERITY
-const bool kAllowDisableVerity = true;
-#else
-const bool kAllowDisableVerity = false;
-#endif
-
-static bool SetupOrTeardownOverlayfs(bool enable) {
-    bool want_reboot = false;
-    if (enable) {
-        if (!fs_mgr_overlayfs_setup(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;
-}
-
-/* Helper function to get A/B suffix, if any. If the device isn't
- * using A/B the empty string is returned. Otherwise either "_a",
- * "_b", ... is returned.
- */
-std::string get_ab_suffix() {
-    return android::base::GetProperty("ro.boot.slot_suffix", "");
-}
-
-bool is_avb_device_locked() {
-    return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
-}
-
-bool is_debuggable() {
-    return android::base::GetBoolProperty("ro.debuggable", false);
-}
-
-bool is_using_avb() {
-    // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
-    // contract, androidboot.vbmeta.digest is set by the bootloader
-    // when using AVB).
-    return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
-}
-
-[[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);
-}
-
-struct SetVerityStateResult {
-    bool success = false;
-    bool want_reboot = false;
-};
-
-/* Use AVB to turn verity on/off */
-SetVerityStateResult SetVerityState(bool enable_verity) {
-    std::string ab_suffix = get_ab_suffix();
-    bool verity_enabled = false;
-
-    if (is_avb_device_locked()) {
-        LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
-        return {};
-    }
-
-    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_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
-        LOG(ERROR) << "Error getting verity state";
-        return {};
-    }
-
-    if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
-        LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
-        return {.success = true, .want_reboot = false};
-    }
-
-    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
-        LOG(ERROR) << "Error setting verity state";
-        return {};
-    }
-
-    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
-    return {.success = true, .want_reboot = true};
-}
-
-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) {
-        // Hide log starting with '[fs_mgr]' unless it's an error.
-        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_;
-};
-
-}  // namespace
-
-int main(int argc, char* argv[]) {
-    bool auto_reboot = false;
-    bool verbose = false;
-
-    struct option longopts[] = {
-            {"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, "hRv", longopts, nullptr)) != -1;) {
-        switch (opt) {
-            case 'h':
-                print_usage();
-                return 0;
-            case 'R':
-                auto_reboot = true;
-                break;
-            case 'v':
-                verbose = true;
-                break;
-            default:
-                print_usage();
-                return 1;
-        }
-    }
-
-    android::base::InitLogging(argv, MyLogger(verbose));
-
-    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 (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
-        // progname "set-verity-state"
-        enable_verity = (argv[optind] == "1"s);
-    } else {
-        print_usage();
-        return 1;
-    }
-
-    if (!kAllowDisableVerity || !is_debuggable()) {
-        errno = EPERM;
-        PLOG(ERROR) << "Cannot disable/enable verity on user build";
-        return 1;
-    }
-
-    if (getuid() != 0) {
-        errno = EACCES;
-        PLOG(ERROR) << "Must be running as root (adb root)";
-        return 1;
-    }
-
-    if (!is_using_avb()) {
-        LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
-        return 1;
-    }
-
-    int exit_code = 0;
-    bool want_reboot = false;
-
-    auto ret = SetVerityState(enable_verity);
-    if (ret.success) {
-        want_reboot |= ret.want_reboot;
-    } else {
-        exit_code = 1;
-    }
-
-    // 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) {
-        // Start a threadpool to service waitForService() callbacks as
-        // fs_mgr_overlayfs_* might call waitForService() to get the image service.
-        android::ProcessState::self()->startThreadPool();
-        want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
-    }
-
-    if (want_reboot) {
-        if (auto_reboot) {
-            reboot(progname);
-        }
-        printf("Reboot the device for new settings to take effect\n");
-    }
-
-    return exit_code;
-}