From dffdb4374be5d58e547eefa8a5063579a28dc6ee Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Thu, 24 Jan 2019 11:08:10 -0800 Subject: [PATCH] fs_mgr: overlayfs: export fs_mgr_overlayfs_candidate_list Refactor fs_mgr_candidate_list into fs_mgr_overlayfs_candidate_list that reports all the possible candidates. The caller is responsible for filtering out any that have verity enabled. Sundry improvements to the adb-remount-test.sh script to improve stability and feedback. Test: adb-remount-test.sh Bug: 122602260 Change-Id: I2399f83d8ed77d8f3d2ad1405d0c187ccbace764 --- fs_mgr/fs_mgr_overlayfs.cpp | 111 +++++++++++++++++------------- fs_mgr/include/fs_mgr_overlayfs.h | 2 + fs_mgr/tests/adb-remount-test.sh | 47 ++++++++++--- 3 files changed, 103 insertions(+), 57 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 87729cda1..9364b2df6 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -78,6 +78,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 +Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) { + return {}; +} + bool fs_mgr_overlayfs_mount_all(Fstab*) { return false; } @@ -238,8 +242,7 @@ std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) { return ret; } -const char* fs_mgr_mount_point(const char* mount_point) { - if (!mount_point) return mount_point; +const std::string fs_mgr_mount_point(const std::string& mount_point) { if ("/"s != mount_point) return mount_point; return "/system"; } @@ -526,40 +529,6 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) { } } -std::vector fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) { - std::vector mounts; - for (auto& entry : *fstab) { - if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) && - !fs_mgr_wants_overlayfs(&entry)) { - continue; - } - std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str())); - if (mount_point && (new_mount_point != mount_point)) continue; - - auto saved_errno = errno; - auto verity_enabled = fs_mgr_is_verity_enabled(entry); - if (errno == ENOENT || errno == ENXIO) errno = saved_errno; - if (verity_enabled) continue; - - auto duplicate_or_more_specific = false; - for (auto it = mounts.begin(); it != mounts.end();) { - if ((*it == new_mount_point) || - (android::base::StartsWith(new_mount_point, *it + "/"))) { - duplicate_or_more_specific = true; - break; - } - if (android::base::StartsWith(*it, new_mount_point + "/")) { - it = mounts.erase(it); - } else { - ++it; - } - } - if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point); - } - - return mounts; -} - // Mount kScratchMountPoint bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type, bool readonly = false) { @@ -802,12 +771,42 @@ bool fs_mgr_overlayfs_invalid() { } // namespace +Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) { + Fstab candidates; + for (const auto& entry : fstab) { + FstabEntry new_entry = entry; + if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) && + !fs_mgr_wants_overlayfs(&new_entry)) { + continue; + } + auto new_mount_point = fs_mgr_mount_point(entry.mount_point); + auto duplicate_or_more_specific = false; + for (auto it = candidates.begin(); it != candidates.end();) { + auto it_mount_point = fs_mgr_mount_point(it->mount_point); + if ((it_mount_point == new_mount_point) || + (android::base::StartsWith(new_mount_point, it_mount_point + "/"))) { + duplicate_or_more_specific = true; + break; + } + if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) { + it = candidates.erase(it); + } else { + ++it; + } + } + if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry)); + } + return candidates; +} + bool fs_mgr_overlayfs_mount_all(Fstab* fstab) { auto ret = false; if (fs_mgr_overlayfs_invalid()) return ret; auto scratch_can_be_mounted = true; - for (const auto& mount_point : fs_mgr_candidate_list(fstab)) { + for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) { + if (fs_mgr_is_verity_enabled(entry)) continue; + auto mount_point = fs_mgr_mount_point(entry.mount_point); if (fs_mgr_overlayfs_already_mounted(mount_point)) { ret = true; continue; @@ -840,8 +839,9 @@ std::vector fs_mgr_overlayfs_required_devices(Fstab* fstab) { return {}; } - for (const auto& mount_point : fs_mgr_candidate_list(fstab)) { - if (fs_mgr_overlayfs_already_mounted(mount_point)) continue; + for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) { + if (fs_mgr_is_verity_enabled(entry)) continue; + if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) continue; auto device = fs_mgr_overlayfs_scratch_device(); if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break; return {device}; @@ -867,8 +867,24 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* return false; } errno = save_errno; - auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point)); - if (mounts.empty()) return ret; + auto candidates = fs_mgr_overlayfs_candidate_list(fstab); + for (auto it = candidates.begin(); it != candidates.end();) { + if (mount_point && + (fs_mgr_mount_point(it->mount_point) != fs_mgr_mount_point(mount_point))) { + it = candidates.erase(it); + continue; + } + save_errno = errno; + auto verity_enabled = fs_mgr_is_verity_enabled(*it); + if (errno == ENOENT || errno == ENXIO) errno = save_errno; + if (verity_enabled) { + it = candidates.erase(it); + continue; + } + ++it; + } + + if (candidates.empty()) return ret; std::string dir; for (const auto& overlay_mount_point : kOverlayMountPoints) { @@ -891,8 +907,8 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* std::string overlay; ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change); - for (const auto& fsrec_mount_point : mounts) { - ret |= fs_mgr_overlayfs_setup_one(overlay, fsrec_mount_point, change); + for (const auto& entry : candidates) { + ret |= fs_mgr_overlayfs_setup_one(overlay, fs_mgr_mount_point(entry.mount_point), change); } return ret; } @@ -901,7 +917,6 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* // If something is altered, set *change. bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { if (change) *change = false; - mount_point = fs_mgr_mount_point(mount_point); auto ret = true; // If scratch exists, but is not mounted, lets gain access to clean // specific override entries. @@ -919,7 +934,8 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) { fs_mgr_overlayfs_scratch_mount_type()); } for (const auto& overlay_mount_point : kOverlayMountPoints) { - ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change); + ret &= fs_mgr_overlayfs_teardown_one( + overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change); } if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) { // After obligatory teardown to make sure everything is clean, but if @@ -946,8 +962,9 @@ bool fs_mgr_overlayfs_is_setup() { return false; } if (fs_mgr_overlayfs_invalid()) return false; - for (const auto& mount_point : fs_mgr_candidate_list(&fstab)) { - if (fs_mgr_overlayfs_already_mounted(mount_point)) return true; + for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) { + if (fs_mgr_is_verity_enabled(entry)) continue; + if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true; } return false; } diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h index 64682cced..6aaf1f3c1 100644 --- a/fs_mgr/include/fs_mgr_overlayfs.h +++ b/fs_mgr/include/fs_mgr_overlayfs.h @@ -21,6 +21,8 @@ #include #include +android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab); + bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab); std::vector fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab); bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr, diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index 8298bf290..7fc951831 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -210,6 +210,21 @@ adb_wait() { fi } +[ "USAGE: usb_status > stdout + +If adb_wait failed, check if device is in fastboot mode and report status + +Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ] +usb_status() { + if inFastboot; then + echo "(In fastboot mode)" + elif inAdb; then + echo "(In adb mode)" + else + echo "(USB stack borken?)" + fi +} + [ "USAGE: fastboot_wait [timeout] Returns: waits until the device has returned for fastboot or optional timeout" ] @@ -383,6 +398,17 @@ skip_administrative_mounts() { -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) " } +[ "USAGE: skip_unrelated_mounts < /proc/mounts + +or output from df + +Filters out all apex and vendor override administrative overlay mounts +uninteresting to the test" ] +skip_unrelated_mounts() { + grep -v "^overlay.* /\(apex\|bionic\|system\|vendor\)/[^ ]" | + grep -v "[%] /\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$" +} + ## ## MAINLINE ## @@ -484,9 +510,9 @@ if ${reboot}; then echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2 adb_reboot && adb_wait 2m || - die "lost device after reboot after wipe (USB stack broken?)" + die "lost device after reboot after wipe `usb_status`" adb_root || - die "lost device after elevation to root after wipe (USB stack broken?)" + die "lost device after elevation to root after wipe `usb_status`" fi D=`adb_sh df -k /dev/null && no_dedupe=false done -D=`adb_sh df -k ${D} &1` adb_reboot && adb_wait 2m || - die "lost device after reboot requested (USB stack broken?)" + die "lost device after reboot requested `usb_status`" adb_root || - die "lost device after elevation to root (USB stack broken?)" + die "lost device after elevation to root `usb_status`" rebooted=true # re-disable verity to see the setup remarks expected T=`adb_date` @@ -593,7 +620,7 @@ adb remount || die -t "${T}" "adb remount failed" D=`adb_sh df -k /dev/null || die "overlay takeover after remount" !(adb_sh grep "^overlay " /proc/mounts &2 || echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2 fi @@ -782,7 +809,7 @@ else adb_root && D=`adb_sh df -k /dev/null || @@ -888,7 +915,7 @@ echo "${GREEN}[ RUN ]${NORMAL} test raw remount commands" >&2 # Prerequisite is a prepped device from above. adb_reboot && adb_wait 2m || - die "lost device after reboot to ro state (USB stack broken?)" + die "lost device after reboot to ro state `usb_status`" adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null && die "/vendor is not read-only" adb_su mount -o rw,remount /vendor ||