diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp index 974e13e44..4ee962442 100644 --- a/fs_mgr/Android.bp +++ b/fs_mgr/Android.bp @@ -111,3 +111,35 @@ cc_library_static { "libgsi_headers", ], } + +cc_binary { + name: "remount", + defaults: ["fs_mgr_defaults"], + static_libs: [ + "libavb_user", + ], + shared_libs: [ + "libbootloader_message", + "libbase", + "libcrypto", + "libfec", + "libfs_mgr", + ], + header_libs: [ + "libcutils_headers", + ], + srcs: [ + "fs_mgr_remount.cpp", + ], + cppflags: [ + "-DALLOW_ADBD_DISABLE_VERITY=0", + ], + product_variables: { + debuggable: { + cppflags: [ + "-UALLOW_ADBD_DISABLE_VERITY", + "-DALLOW_ADBD_DISABLE_VERITY=1", + ], + }, + }, +} diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp new file mode 100644 index 000000000..c0e0ccd8f --- /dev/null +++ b/fs_mgr/fs_mgr_remount.cpp @@ -0,0 +1,348 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +[[noreturn]] void usage(int exit_status) { + LOG(INFO) << getprogname() + << " [-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" + "-R notwithstanding, verity must be disabled."; + + ::exit(exit_status); +} + +bool remountable_partition(const android::fs_mgr::FstabEntry& entry) { + if (entry.fs_mgr_flags.vold_managed) return false; + if (entry.fs_mgr_flags.recovery_only) return false; + if (entry.fs_mgr_flags.slot_select_other) return false; + if (!(entry.flags & MS_RDONLY)) return false; + if (entry.fs_type == "vfat") return false; + return true; +} + +const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) { + if (entry.mount_point == "/") return "/system"; + return entry.mount_point; +} + +const android::fs_mgr::FstabEntry* is_wrapped(const android::fs_mgr::Fstab& overlayfs_candidates, + const android::fs_mgr::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); +} + +void try_unmount_bionic(android::fs_mgr::Fstab* mounts) { + static constexpr const char* kBionic = "/bionic"; + + auto entry = GetEntryForMountPoint(mounts, kBionic); + if (!entry) return; + + struct statfs buf; + if (::statfs(kBionic, &buf) == -1) { + PLOG(ERROR) << "statfs of " << kBionic; + return; + } + if (buf.f_flags & MS_RDONLY) { + // /bionic is on a read-only partition; can happen for + // non-system-as-root-devices. Don' try to unmount. + return; + } + fs_mgr_set_blk_ro(entry->blk_device, false); + if (::mount(entry->blk_device.c_str(), entry->mount_point.c_str(), entry->fs_type.c_str(), + MS_REMOUNT, nullptr) == -1) { + PLOG(ERROR) << "remount of " << kBionic; + } +} + +void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag, + const char* file, unsigned int line, const char* message) { + static const char log_characters[] = "VD\0WEFF"; + if (severity < sizeof(log_characters)) { + auto severity_char = log_characters[severity]; + if (severity_char) fprintf(stderr, "%c ", severity_char); + } + fprintf(stderr, "%s\n", message); + + static auto logd = android::base::LogdLogger(); + 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[]) { + android::base::InitLogging(argv, MyLogger); + + enum { + SUCCESS, + NOT_USERDEBUG, + BADARG, + NOT_ROOT, + NO_FSTAB, + VERITY_PARTITION, + BAD_OVERLAY, + NO_MOUNTS, + REMOUNT_FAILED, + } retval = SUCCESS; + + // 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::GetProperty("ro.debuggable", "0") != "1")) { + LOG(ERROR) << "only functions on userdebug or eng builds"; + return NOT_USERDEBUG; + } + + 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, "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; + usage(BADARG); + } + fstab_file = optarg; + break; + default: + LOG(ERROR) << "Bad Argument -" << char(opt); + usage(BADARG); + break; + case 'h': + usage(SUCCESS); + break; + } + } + + if (argc > optind) { + LOG(ERROR) << "Bad Argument " << argv[optind]; + usage(BADARG); + } + + // Make sure we are root. + if (::getuid() != 0) { + LOG(ERROR) << "must be run as root"; + return NOT_ROOT; + } + + // Read the selected fstab. + android::fs_mgr::Fstab fstab; + auto fstab_read = false; + if (fstab_file) { + fstab_read = android::fs_mgr::ReadFstabFromFile(fstab_file, &fstab); + } else { + fstab_read = android::fs_mgr::ReadDefaultFstab(&fstab); + } + if (!fstab_read || fstab.empty()) { + PLOG(ERROR) << "Failed to read fstab"; + return NO_FSTAB; + } + + // Generate the list of supported overlayfs mount points. + auto overlayfs_candidates = fs_mgr_overlayfs_candidate_list(fstab); + + // Generate the all remountable partitions sub-list + android::fs_mgr::Fstab partitions; + for (auto const& entry : fstab) { + if (!remountable_partition(entry)) continue; + if (overlayfs_candidates.empty() || + GetEntryForMountPoint(&overlayfs_candidates, entry.mount_point) || + (is_wrapped(overlayfs_candidates, entry) == nullptr)) { + partitions.emplace_back(entry); + } + } + + // 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(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); + } else if (fs_mgr_set_blk_ro(entry.blk_device, false)) { + fec::io fh(entry.blk_device.c_str(), O_RDWR); + if (fh && fh.set_verity_status(false)) reboot_later = true; + } + } + } + LOG(ERROR) << "Skipping " << mount_point; + retval = VERITY_PARTITION; + it = partitions.erase(it); + continue; + } + + auto change = false; + errno = 0; + if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change)) { + if (change) { + LOG(INFO) << "Using overlayfs for " << mount_point; + } + } else if (errno) { + PLOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping"; + retval = BAD_OVERLAY; + it = partitions.erase(it); + continue; + } + ++it; + } + + if (partitions.empty()) { + if (reboot_later) reboot(false); + LOG(WARNING) << "No partitions to remount"; + return retval; + } + + // Mount overlayfs. + if (!fs_mgr_overlayfs_mount_all(&partitions)) { + retval = BAD_OVERLAY; + PLOG(ERROR) << "Can not mount overlayfs for partitions"; + } + + // 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"; + retval = NO_MOUNTS; + } + + // Remount selected partitions. + for (auto& entry : partitions) { + // 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; + + for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) { + auto& rentry = *it; + if (mount_point == rentry.mount_point) { + blk_device = rentry.blk_device; + break; + } + if ((mount_point == "/") && (rentry.mount_point == "/system")) { + if (blk_device != "/dev/root") blk_device = rentry.blk_device; + mount_point = "/system"; + break; + } + } + fs_mgr_set_blk_ro(blk_device, false); + + // Now remount! + if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT, + nullptr) == 0) { + continue; + } + if ((errno == EINVAL) && (mount_point != entry.mount_point)) { + mount_point = entry.mount_point; + if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT, + nullptr) == 0) { + 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; 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 fd53ed4b4..1ded95441 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -70,19 +70,37 @@ inFastboot() { Returns: true if device is in adb mode" ] inAdb() { adb devices | - grep -v -e 'List of devices attached' -e '^$' | + grep -v -e 'List of devices attached' -e '^$' -e "[${SPACE}${TAB}]recovery\$" | if [ -n "${ANDROID_SERIAL}" ]; then grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null else wc -l | grep '^1$' >/dev/null fi } +[ "USAGE: inRecovery + +Returns: true if device is in recovery mode" ] +inRecovery() { + local list="`adb devices | + grep -v -e 'List of devices attached' -e '^$'`" + if [ -n "${ANDROID_SERIAL}" ]; then + echo "${list}" | + grep "^${ANDROID_SERIAL}[${SPACE}${TAB}][${SPACE}${TAB}]*recovery\$" >/dev/null + return ${?} + fi + if echo "${list}" | wc -l | grep '^1$' >/dev/null; then + echo "${list}" | + grep "[${SPACE}${TAB}]recovery\$" >/dev/null + return ${?} + fi + false +} [ "USAGE: adb_sh /dev/stdout 2>/dev/stderr Returns: true if the command succeeded" ] adb_sh() { - args= + local args= for i in "${@}"; do [ -z "${args}" ] || args="${args} " if [ X"${i}" != X"${i#\'}" ]; then @@ -143,10 +161,10 @@ adb_su() { Returns: content of file to stdout with carriage returns skipped, true of the file exists" ] adb_cat() { - OUTPUT="`adb_sh cat ${1} &1`" - retval=${?} + local OUTPUT="`adb_sh cat ${1} &1`" + local ret=${?} echo "${OUTPUT}" | tr -d '\r' - return ${retval} + return ${ret} } [ "USAGE: adb_reboot @@ -165,7 +183,7 @@ format_duration() { echo unknown return fi - duration="${1}" + local duration="${1}" if [ X"${duration}" != X"${duration%s}" ]; then duration=${duration%s} elif [ X"${duration}" != X"${duration%m}" ]; then @@ -175,9 +193,9 @@ format_duration() { elif [ X"${duration}" != X"${duration%d}" ]; then duration=`expr ${duration%d} \* 86400` fi - seconds=`expr ${duration} % 60` - minutes=`expr \( ${duration} / 60 \) % 60` - hours=`expr ${duration} / 3600` + local seconds=`expr ${duration} % 60` + local minutes=`expr \( ${duration} / 60 \) % 60` + local hours=`expr ${duration} / 3600` if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then if [ 1 -eq ${duration} ]; then echo 1 second @@ -205,10 +223,10 @@ Returns: waits until the device has returned for adb or optional timeout" ] adb_wait() { if [ -n "${1}" ]; then echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}" - timeout --preserve-status --signal=KILL ${1} adb wait-for-device - retval=${?} + timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null + local ret=${?} echo -n " ${CR}" - return ${retval} + return ${ret} else adb wait-for-device fi @@ -216,12 +234,15 @@ adb_wait() { [ "USAGE: usb_status > stdout -If adb_wait failed, check if device is in fastboot mode and report status +If adb_wait failed, check if device is in adb, recovery or fastboot mode +and report status string. Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ] usb_status() { if inFastboot; then echo "(In fastboot mode)" + elif inRecovery; then + echo "(In recovery mode)" elif inAdb; then echo "(In adb mode)" else @@ -238,15 +259,47 @@ fastboot_wait() { if [ -n "${1}" ]; then echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}" timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null - retval=${?} + local ret=${?} echo -n " ${CR}" - ( exit ${retval} ) + ( exit ${ret} ) else fastboot wait-for-device >/dev/null 2>/dev/null fi || inFastboot } +[ "USAGE: recovery_wait [timeout] + +Returns: waits until the device has returned for recovery or optional timeout" ] +recovery_wait() { + if [ -n "${1}" ]; then + echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}" + timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null + local ret=${?} + echo -n " ${CR}" + return ${ret} + else + adb wait-for-recovery + fi +} + +[ "any_wait [timeout] + +Returns: waits until a device has returned or optional timeout" ] +any_wait() { + ( + adb_wait ${1} & + adb_pid=${!} + fastboot_wait ${1} & + fastboot_pid=${!} + recovery_wait ${1} & + recovery_pid=${!} + wait -n + kill "${adb_pid}" "${fastboot_pid}" "${recovery_pid}" + ) >/dev/null 2>/dev/null + inFastboot || inAdb || inRecovery +} + [ "USAGE: adb_root NB: This can be flakey on devices due to USB state @@ -277,11 +330,11 @@ adb_unroot() { Returns: true if var output matches expected" ] fastboot_getvar() { - O=`fastboot getvar ${1} 2>&1` - err=${?} + local O=`fastboot getvar ${1} 2>&1` + local ret=${?} O="${O#< waiting for * >?}" O="${O%%?Finished. Total time: *}" - if [ 0 -ne ${err} ]; then + if [ 0 -ne ${ret} ]; then echo ${O} >&2 false return @@ -325,7 +378,7 @@ test_duration() { echo "${BLUE}[ INFO ]${NORMAL} end `date`" [ -n "${start_time}" ] || return end_time=`date +%s` - diff_time=`expr ${end_time} - ${start_time}` + local diff_time=`expr ${end_time} - ${start_time}` echo "${BLUE}[ INFO ]${NORMAL} duration `format_duration ${diff_time}`" fi >&2 } @@ -358,8 +411,8 @@ die() { Returns true if (regex) lval matches rval" ] EXPECT_EQ() { - lval="${1}" - rval="${2}" + local lval="${1}" + local rval="${2}" shift 2 if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval% @@ -404,10 +457,10 @@ EXPECT_EQ() { Exits if (regex) lval mismatches rval" ] check_eq() { - left="${1}" - right="${2}" + local lval="${1}" + local rval="${2}" shift 2 - EXPECT_EQ "${left}" "${right}" || + EXPECT_EQ "${lval}" "${rval}" || die "${@}" } @@ -498,15 +551,16 @@ if ${print_time}; then fi inFastboot && die "device in fastboot mode" +inRecovery && die "device in recovery mode" if ! inAdb; then - echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" + echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" >&2 adb_wait 2m fi inAdb || die "specified device not in adb mode" isDebuggable || die "device not a debug build" enforcing=true if ! adb_su getenforce /dev/null; then - echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" + echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2 enforcing=false fi @@ -563,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 @@ -577,7 +644,7 @@ adb_sh ls -d /sys/module/overlay /dev/null 2>/dev/null || ) || overlayfs_supported=false if ${overlayfs_supported}; then - adb_su ls /sys/module/overlay/parameters/override_creds /dev/null && + adb_su ls /sys/module/overlay/parameters/override_creds /dev/null 2>/dev/null && echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 || case `adb_sh uname -r &2 fi -B="`adb_cat /system/hello`" || - die "re-read /system/hello after reboot" -check_eq "${A}" "${B}" /system after reboot -echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2 -# Only root can read vendor if sepolicy permissions are as expected. if ${enforcing}; then - adb_unroot - B="`adb_cat /vendor/hello`" && - die "re-read /vendor/hello after reboot w/o root" + adb_unroot || + die "device not in unroot'd state" + B="`adb_cat /vendor/hello 2>&1`" check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root echo "${GREEN}[ OK ]${NORMAL} /vendor content correct MAC after reboot" >&2 fi -adb_root && - B="`adb_cat /vendor/hello`" || - die "re-read /vendor/hello after reboot" +B="`adb_cat /system/hello`" +check_eq "${A}" "${B}" /system after reboot +echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2 +# Only root can read vendor if sepolicy permissions are as expected. +adb_root || + die "adb root" +B="`adb_cat /vendor/hello`" check_eq "${A}" "${B}" vendor after reboot echo "${GREEN}[ OK ]${NORMAL} /vendor content remains after reboot" >&2 @@ -901,8 +967,9 @@ elif [ -z "${ANDROID_HOST_OUT}" ]; then else adb reboot-fastboot || die "fastbootd not supported (wrong adb in path?)" - fastboot_wait 2m || - die "reboot into fastboot to flash vendor `usb_status`" + any_wait 2m && + inFastboot || + die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)" fastboot flash vendor || ( fastboot reboot && false) || die "fastboot flash vendor" @@ -956,12 +1023,11 @@ else if ${is_userspace_fastboot}; then die "overlay supposed to be minus /vendor takeover after flash vendor" else - echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing, ignoring a failure" - ( die "overlay supposed to be minus /vendor takeover after flash vendor" ) + echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 + echo "${ORANGE}[ WARNING ]${NORMAL} overlay supposed to be minus /vendor takeover after flash vendor" >&2 fi fi - B="`adb_cat /system/hello`" || - die "re-read /system/hello after flash vendor" + B="`adb_cat /system/hello`" check_eq "${A}" "${B}" system after flash vendor adb_root || die "adb root" @@ -969,13 +1035,21 @@ else if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then die "re-read /vendor/hello after flash vendor" else - echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing, ignoring a failure" - ( die "re-read /vendor/hello after flash vendor" ) + echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 + echo "${ORANGE}[ WARNING ]${NORMAL} re-read /vendor/hello after flash vendor" >&2 fi if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then - check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor + check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ + vendor content after flash vendor else - ( check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor ) + ( + echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 + restore() { + true + } + check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ + vendor content after flash vendor + ) fi fi @@ -1003,12 +1077,10 @@ echo "${H}" adb_sh rm /system/hello /dev/null &2 +# Prerequisite is a prepped device from above. +adb_reboot && + adb_wait 2m || + die "lost device after reboot to ro state (USB stack broken?)" +adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null /dev/null &2 + +# Prerequisite is an overlayfs deconstructed device but with verity disabled. +# This also saves a lot of 'noise' from the command doing a mkfs on backing +# storage and all the related tuning and adjustment. +for d in ${OVERLAYFS_BACKING}; do + adb_su rm -rf /${d}/overlay /dev/null /dev/null &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 }