From e8d85b5814e6c0199cf22b2ca36ce5ca38aead33 Mon Sep 17 00:00:00 2001 From: Yi-Yo Chiang Date: Mon, 31 Oct 2022 19:45:11 +0800 Subject: [PATCH] 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 --- fs_mgr/Android.bp | 37 +----- fs_mgr/fs_mgr_remount.cpp | 158 +++++++++++++++++++--- fs_mgr/set-verity-state.cpp | 258 ------------------------------------ 3 files changed, 145 insertions(+), 308 deletions(-) delete mode 100644 fs_mgr/set-verity-state.cpp diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp index bebf19e9c..dd612720f 100644 --- a/fs_mgr/Android.bp +++ b/fs_mgr/Android.bp @@ -251,41 +251,8 @@ cc_binary { }, 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 dfc89836c..eac3ff298 100644 --- a/fs_mgr/fs_mgr_remount.cpp +++ b/fs_mgr/fs_mgr_remount.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -50,17 +52,34 @@ using android::fs_mgr::FstabEntry; 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 @@ static android::sp GetVold() { } } -} // namespace - enum RemountStatus { REMOUNT_SUCCESS = 0, UNKNOWN_PARTITION = 5, @@ -421,6 +438,68 @@ static RemountStatus RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& e 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 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& partition_args, RemountCheckResult* check_result) { Fstab partitions; @@ -466,6 +545,8 @@ static int do_remount(Fstab& fstab, const std::vector& partition_ar 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 @@ int main(int argc, char* argv[]) { 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 @@ int main(int argc, char* argv[]) { 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 84ee01f48..000000000 --- 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 -#include - -#include -#include -#include -#include -#include -#include -#include - -#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 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; -}