From 1188ce4e1dd4355a340ef7d00e105fb3d7475909 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Fri, 25 Jan 2019 11:05:40 -0800 Subject: [PATCH] fs_mgr: remount: add -R argument The -R flag tells remount it can reboot to disable verity or to run fsck on an ext4 deduped filesystem, or both. Testing may include a manual component because adb-remount-test.sh needs to run from a device in an enable-verity state to test this. Only recognizes chained avb. Test: adb-remount-test.sh Bug: 122602260 Change-Id: I6ce4372532d9b933dcca9e2bec544d525b76c4d9 --- fs_mgr/Android.bp | 7 ++++ fs_mgr/fs_mgr_remount.cpp | 72 +++++++++++++++++++++++++------- fs_mgr/tests/adb-remount-test.sh | 30 +++++++++++++ 3 files changed, 94 insertions(+), 15 deletions(-) diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp index a476cd85d..0a048f9c0 100644 --- a/fs_mgr/Android.bp +++ b/fs_mgr/Android.bp @@ -115,10 +115,17 @@ cc_library_static { cc_binary { name: "remount", defaults: ["fs_mgr_defaults"], + static_libs: [ + "libavb_user", + ], shared_libs: [ + "libbootloader_message", "libbase", "libfs_mgr", ], + header_libs: [ + "libcutils_headers", + ], srcs: [ "fs_mgr_remount.cpp", ], diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp index 6e9ab2a77..105d18c2f 100644 --- a/fs_mgr/fs_mgr_remount.cpp +++ b/fs_mgr/fs_mgr_remount.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -38,12 +41,13 @@ namespace { [[noreturn]] void usage(int exit_status) { LOG(INFO) << getprogname() - << " [-h] [-T fstab_file]\n" + << " [-h] [-R] [-T fstab_file]\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" "\n" "Remount all partitions read-write.\n" - "Verity must be disabled."; + "-R notwithstanding, verity must be disabled."; ::exit(exit_status); } @@ -110,6 +114,18 @@ void MyLogger(android::base::LogId id, android::base::LogSeverity severity, cons logd(id, severity, tag, file, line, message); } +[[noreturn]] void reboot(bool dedupe) { + if (dedupe) { + LOG(INFO) << "The device will now reboot to recovery and attempt un-deduplication."; + } else { + LOG(INFO) << "Successfully disabled verity\nrebooting device"; + } + ::sync(); + android::base::SetProperty(ANDROID_RB_PROPERTY, dedupe ? "reboot,recovery" : "reboot,remount"); + ::sleep(60); + ::exit(0); // SUCCESS +} + } // namespace int main(int argc, char* argv[]) { @@ -136,14 +152,19 @@ int main(int argc, char* argv[]) { } const char* fstab_file = nullptr; + auto can_reboot = false; struct option longopts[] = { {"fstab", required_argument, nullptr, 'T'}, {"help", no_argument, nullptr, 'h'}, + {"reboot", no_argument, nullptr, 'R'}, {0, 0, nullptr, 0}, }; - for (int opt; (opt = ::getopt_long(argc, argv, "hT:", longopts, nullptr)) != -1;) { + for (int opt; (opt = ::getopt_long(argc, argv, "hRT:", longopts, nullptr)) != -1;) { switch (opt) { + case 'R': + can_reboot = true; + break; case 'T': if (fstab_file) { LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg; @@ -200,11 +221,32 @@ int main(int argc, char* argv[]) { } // Check verity and optionally setup overlayfs backing. + auto reboot_later = 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)) { - LOG(ERROR) << "Verity enabled on " << mount_point << ", skipping"; + LOG(WARNING) << "Verity enabled on " << mount_point; + if (can_reboot && + (android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked")) { + if (AvbOps* ops = avb_ops_user_new()) { + auto ret = avb_user_verity_set( + ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(), + false); + avb_ops_user_free(ops); + if (ret) { + if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) { + retval = VERITY_PARTITION; + // w/o overlayfs available, also check for dedupe + reboot_later = true; + ++it; + continue; + } + reboot(false); + } + } + } + LOG(ERROR) << "Skipping " << mount_point; retval = VERITY_PARTITION; it = partitions.erase(it); continue; @@ -278,23 +320,23 @@ int main(int argc, char* argv[]) { continue; } } + PLOG(WARNING) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point; // If errno = EROFS at this point, we are dealing with r/o // filesystem types like squashfs, erofs or ext4 dedupe. We will // consider such a device that does not have CONFIG_OVERLAY_FS - // in the kernel as a misconfigured and take no action. - // - // ext4 dedupe _can_ be worked around by performing a reboot into - // recovery and fsck'ing. However the current decision is to not - // reboot to reserve only one shell command to do so (reboot). In - // the future, if this is a problem, a -R flag could be introduced - // to give permission to do so and as a convenience also implement - // verity disable operations. We will require this functionality - // in order for adb remount to call this executable instead of its - // current internal code that recognizes the -R flag and logistics. - PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point; + // in the kernel as a misconfigured; except for ext4 dedupe. + if ((errno == EROFS) && can_reboot) { + const std::vector msg = {"--fsck_unshare_blocks"}; + std::string err; + if (write_bootloader_message(msg, &err)) reboot(true); + LOG(ERROR) << "Failed to set bootloader message: " << err; + errno = EROFS; + } retval = REMOUNT_FAILED; } + if (reboot_later) reboot(false); + try_unmount_bionic(&mounts); return retval; diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index 19562151d..1ded95441 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -617,6 +617,19 @@ if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \ adb_reboot && adb_wait 2m } + + echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2 + + adb_su remount -R &2 fi echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2 @@ -1173,6 +1186,23 @@ echo "${GREEN}[ OK ]${NORMAL} remount command works from scratch" >&2 restore err=${?} +if [ ${err} = 0 ] && ${overlayfs_supported}; then + echo "${GREEN}[ RUN ]${NORMAL} test 'adb remount -R'" >&2 + adb_root && + adb remount -R && + adb_wait 2m || + die "adb remount -R" + if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ + "2" = "`get_property partition.system.verified`" ]; then + die "remount -R command failed to disable verity" + fi + + echo "${GREEN}[ OK ]${NORMAL} 'adb remount -R' command" >&2 + + restore + err=${?} +fi + restore() { true }