From d202c55453b54bb7f4f4e82eaf6e08ebee6cde44 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 12 Dec 2018 10:36:32 -0800 Subject: [PATCH 1/2] fs_mgr: errno handling in fs_mgr_overlayfs_setup() Do not report errno if ENOENT or ENXIO as it is expected when verity is in fact disabled or not setup on platform. Reading the default fstab can also result in ENOENT if fstab or dt are missing on purpose, but if we get an fstab then restore the errno as we move on. fs_mgr_has_shared_blocks sets errno, when all we care about is yes or no answer (EPERM notwithstanding, which indicates do not know). If no candidates are found to override, and not caused by EPERM, then suppress errno. Test: adb-remount-test.sh Bug: 109821005 Change-Id: If7ae257cb6b738a64ba43d32805760cc292b2fae --- fs_mgr/fs_mgr_overlayfs.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index ef043f910..8bfcd8190 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -144,7 +144,10 @@ bool fs_mgr_overlayfs_enabled(FstabEntry* entry) { if (entry->fs_mgr_flags.logical) { fs_mgr_update_logical_partition(entry); } - return fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device); + auto save_errno = errno; + auto has_shared_blocks = fs_mgr_has_shared_blocks(entry->mount_point, entry->blk_device); + errno = save_errno; + return has_shared_blocks; } bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) { @@ -263,8 +266,10 @@ bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overl std::vector fs_mgr_overlayfs_verity_enabled_list() { std::vector ret; + auto save_errno = errno; fs_mgr_update_verity_state( [&ret](const std::string& mount_point, int) { ret.emplace_back(mount_point); }); + if ((errno == ENOENT) || (errno == ENXIO)) errno = save_errno; return ret; } @@ -837,10 +842,12 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* return ret; } + auto save_errno = errno; Fstab fstab; if (!ReadDefaultFstab(&fstab)) { return false; } + errno = save_errno; auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point)); if (mounts.empty()) return ret; @@ -864,7 +871,8 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* break; } if (dir.empty()) { - errno = ESRCH; + if (change && *change) errno = ESRCH; + if (errno == EPERM) errno = save_errno; return ret; } From da27fa0b53c3c56f4f921039487403b56e94748f Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Mon, 10 Dec 2018 13:30:53 -0800 Subject: [PATCH 2/2] fs_mgr: adb-remount-test in non overlayfs world Extend test script to check non overlayfs case too. Establish whether overlayfs is supported, or needed, and adjust expectations. For the flash vendor code, make sure it is the _right_ vendor, skip instead of fail. Improve quality of the testing and handle more cases. Test: adb-remount-test.sh Bug: 109821005 Change-Id: Ic9957cb378d8e7737ffc4ba04078c1cb6bbd1bbd --- fs_mgr/tests/adb-remount-test.sh | 421 +++++++++++++++++++------------ 1 file changed, 259 insertions(+), 162 deletions(-) diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index 561debb86..fde82b422 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -46,7 +46,7 @@ inAdb() { adb devices | grep -v 'List of devices attached' | grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null } -[ "USAGE: adb_sh +[ "USAGE: adb_sh /dev/stdout 2>/dev/stderr Returns: true if the command succeeded" ] adb_sh() { @@ -86,7 +86,7 @@ isDebuggable() { fi } -[ "USAGE: adb_su +[ "USAGE: adb_su /dev/stdout 2>/dev/stderr Returns: true if the command running as root succeeded" ] adb_su() { @@ -284,23 +284,47 @@ isDebuggable || die "device not a debug build" echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2 +overlayfs_supported=true; adb_wait || die "wait for device failed" adb_sh ls -d /sys/module/overlay /dev/null && echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 || - die "overlay module not present" -adb_su ls /sys/module/overlay/parameters/override_creds /dev/null && - echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 || - die "overlay module can not be used on ANDROID" + ( + echo "${ORANGE}[ WARNING ]${NORMAL} overlay module not present" >&2 && + false + ) || + overlayfs_supported=false +if ${overlayfs_supported}; then + case `adb_sh uname -r /dev/null && + echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 || + ( + echo "${ORANGE}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 && + false + ) || + overlayfs_supported=false; + ;; + *) + echo "${GREEN}[ OK ]${NORMAL} overlay module uses callers creds" >&2 + ;; + esac +fi + adb_root || die "initial setup" echo "${GREEN}[ RUN ]${NORMAL} Checking current overlayfs status" >&2 +# We can not universally use adb enable-verity to ensure device is +# in a overlayfs disabled state since it can prevent reboot on +# devices that remount the physical content rather than overlayfs. +# So lets do our best to surgically wipe the overlayfs state without +# having to go through enable-verity transition. reboot=false OVERLAYFS_BACKING="cache mnt/scratch" for d in ${OVERLAYFS_BACKING}; do if adb_sh ls -d /${d}/overlay /dev/null 2>/dev/null; then - echo "${ORANGE}[ WARNING ]${NORMAL} /${d}/overlay is setup, wiping" >&2 + echo "${ORANGE}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2 adb_sh rm -rf /${d}/overlay &2 adb_reboot && - adb_wait 2m && - adb_root || - die "reboot after wipe" + adb_wait 2m || + die "lost device after reboot after wipe" + adb_root || + die "lost device after elevation to root after wipe" fi D=`adb_sh df -k &2 || echo "${GREEN}[ OK ]${NORMAL} no overlay present before setup" >&2 -adb_sh df -k `adb_sh cat /proc/mounts | - skip_administrative_mounts data | - cut -s -d' ' -f1` +overlayfs_needed=true +D=`adb_sh cat /proc/mounts &2 T=`adb_date` -D=`adb disable-verity 2>&1` +H=`adb disable-verity 2>&1` err=${?} -if [ ${err} != 0 -o X"${D}" != X"${D##*setup failed}" ]; then - echo "${D%?Now reboot your device for settings to take effect}" - die -t ${T} "setup for overlay" -fi +L= +D="${H%?Now reboot your device for settings to take effect}" if [ X"${D}" != X"${D##*using overlayfs}" ]; then echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 fi -reboot=false -if [ X"${D}" != X"${D##*Successfully disabled verity}" ]; then - echo "${GREEN}[ OK ]${NORMAL} disabled verity" >&2 - reboot=true -else - echo "${ORANGE}[ WARNING ]${NORMAL} verity already disabled" >&2 +if [ ${err} != 0 ]; then + echo "${H}" + ( [ -n "${L}" ] && echo "${L}" && false ) || + die -t "${T}" "disable-verity" fi -D=`adb_sh df -k &2 + fi + D=`adb_sh df -k &2 L=`adb_logcat -b all -v nsec -t ${T} 2>&1` adb_reboot && adb_wait 2m || - die "reboot after verity disabled failed" - T= + die "lost device after reboot requested" + adb_root || + die "lost device after elevation to root" + rebooted=true + # re-disable verity to see the setup remarks expected + T=`adb_date` + H=`adb disable-verity 2>&1` + err=${?} + D="${H%?Now reboot your device for settings to take effect}" + if [ X"${D}" != X"${D##*using overlayfs}" ]; then + echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 + fi + if [ ${err} != 0 ]; then + T= + fi +fi +if ${overlayfs_supported} && ${overlayfs_needed} && [ X"${D}" != X"${D##*setup failed}" ]; then + echo "${D}" + ( [ -n "${L}" ] && echo "${L}" && false ) || + die -t "${T}" "setup for overlay" +fi +if [ X"${D}" != X"${D##*Successfully disabled verity}" ]; then + echo "${D}" + D=`adb_sh df -k &2 +else + echo "${ORANGE}[ WARNING ]${NORMAL} verity already disabled" >&2 fi echo "${GREEN}[ RUN ]${NORMAL} remount" >&2 -adb_root && - adb remount || +adb remount || ( [ -n "${L}" ] && echo "${L}" && false ) || die -t "${T}" "adb remount failed" D=`adb_sh df -k /dev/null || - echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover not complete" >&2 -scratch_partition=scratch -if echo "${D}" | grep " /mnt/scratch" >/dev/null; then - echo "${BLUE}[ INFO ]${NORMAL} using ${scratch_partition} dynamic partition for overrides" >&2 -fi -M=`adb_sh cat /proc/mounts | sed -n 's@\([^ ]*\) /mnt/scratch \([^ ]*\) .*@\2 on \1@p'` -[ -n "${M}" ] && - echo "${BLUE}[ INFO ]${NORMAL} scratch filesystem ${M}" -uses_dynamic_scratch=true -if [ "${M}" != "${M##*/dev/block/by-name/}" ]; then - uses_dynamic_scratch=false - scratch_partition="${M##*/dev/block/by-name/}" -fi -scratch_size=`adb_sh df -k /mnt/scratch /dev/null | - while read device kblocks used available use mounted on; do - if [ "/mnt/scratch" = "\${mounted}" ]; then - echo \${kblocks} - fi - done` && - [ -n "${scratch_size}" ] || - die "scratch size" -echo "${BLUE}[ INFO ]${NORMAL} scratch size ${scratch_size}KB" >&2 -for d in ${OVERLAYFS_BACKING}; do - if adb_sh ls -d /${d}/overlay/system/upper /dev/null 2>/dev/null; then - echo "${BLUE}[ INFO ]${NORMAL} /${d}/overlay is setup" >&2 + ( [ -n "${L}" ] && echo "${L}" && false ) +ret=${?} +uses_dynamic_scratch=false +scratch_partition= +if ${overlayfs_needed}; then + if [ ${ret} != 0 ]; then + die -t ${T} "overlay takeover failed" fi -done - -echo "${H}" && - echo "${D}" && echo "${D}" | grep "^overlay .* /system\$" >/dev/null || - die "overlay takeover after remount" -!(adb_sh grep "^overlay " /proc/mounts &2 + scratch_partition=scratch + if echo "${D}" | grep " /mnt/scratch" >/dev/null; then + echo "${BLUE}[ INFO ]${NORMAL} using ${scratch_partition} dynamic partition for overrides" >&2 + fi + M=`adb_sh cat /proc/mounts /dev/null | + while read device kblocks used available use mounted on; do + if [ "/mnt/scratch" = "\${mounted}" ]; then + echo \${kblocks} + fi + done` && + [ -n "${scratch_size}" ] || + die "scratch size" + echo "${BLUE}[ INFO ]${NORMAL} scratch size ${scratch_size}KB" >&2 + for d in ${OVERLAYFS_BACKING}; do + if adb_sh ls -d /${d}/overlay/system/upper /dev/null 2>/dev/null; then + echo "${BLUE}[ INFO ]${NORMAL} /${d}/overlay is setup" >&2 + fi + done + + echo "${H}" && + echo "${D}" && + echo "${D}" | grep "^overlay .* /system\$" >/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 + adb_su "sed -n '1,/overlay \\/system/p' /proc/mounts" &2 || + echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2 +fi B="`adb_cat /system/hello`" || die "re-read system hello after reboot" @@ -452,63 +534,75 @@ check_eq "${A}" "${B}" vendor after reboot echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears" >&2 -[ -n "${ANDROID_PRODUCT_OUT}" ] && - adb reboot-fastboot && - fastboot_wait 2m && - fastboot flash vendor || - ( fastboot reboot && false) || - die "fastboot flash vendor" -fastboot_getvar partition-type:${scratch_partition} raw || - ( fastboot reboot && false) || - die "fastboot can not see ${scratch_partition} parameters" -if ${uses_dynamic_scratch}; then - # check ${scratch_partition} via fastboot - fastboot_getvar has-slot:${scratch_partition} no && - fastboot_getvar is-logical:${scratch_partition} yes || - ( fastboot reboot && false) || - die "fastboot can not see ${scratch_partition} parameters" +H=`adb_sh echo '${HOSTNAME}' /dev/null` +if [ -z "${ANDROID_PRODUCT_OUT}" ]; then + echo "${ORANGE}[ WARNING ]${NORMAL} build tree not setup, skipping" +elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then + echo "${ORANGE}[ WARNING ]${NORMAL} vendor image missing, skipping" +elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then + echo "${ORANGE}[ WARNING ]${NORMAL} wrong vendor image, skipping" else - fastboot_getvar is-logical:${scratch_partition} no || + adb reboot-fastboot && + fastboot_wait 2m && + fastboot flash vendor || ( fastboot reboot && false) || - die "fastboot can not see ${scratch_partition} parameters" + die "fastboot flash vendor" + if [ -n "${scratch_paritition}" ]; then + fastboot_getvar partition-type:${scratch_partition} raw || + ( fastboot reboot && false) || + die "fastboot can not see ${scratch_partition} parameters" + if ${uses_dynamic_scratch}; then + # check ${scratch_partition} via fastboot + fastboot_getvar has-slot:${scratch_partition} no && + fastboot_getvar is-logical:${scratch_partition} yes || + ( fastboot reboot && false) || + die "fastboot can not see ${scratch_partition} parameters" + else + fastboot_getvar is-logical:${scratch_partition} no || + ( fastboot reboot && false) || + die "fastboot can not see ${scratch_partition} parameters" + fi + if ! ${uses_dynamic_scratch}; then + fastboot reboot-bootloader || + die "Reboot into fastboot" + fi + if ${uses_dynamic_scratch}; then + echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2 + fastboot erase ${scratch_partition} && + ( fastboot reboot || true) && + die "fastboot can erase ${scratch_partition}" + fi + echo "${BLUE}[ INFO ]${NORMAL} expect fastboot format ${scratch_partition} to fail" >&2 + fastboot format ${scratch_partition} && + ( fastboot reboot || true) && + die "fastboot can format ${scratch_partition}" + fi + fastboot reboot || + die "can not reboot out of fastboot" + echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot ... waiting 2 minutes" + adb_wait 2m || + die "did not reboot after flash" + if ${overlayfs_needed}; then + adb_root && + D=`adb_sh df -k /dev/null || + die "overlay system takeover after flash vendor" + echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null && + die "overlay minus vendor takeover after flash vendor" + fi + B="`adb_cat /system/hello`" || + die "re-read system hello after flash vendor" + check_eq "${A}" "${B}" system after flash vendor + adb_root || + die "adb root" + B="`adb_cat /vendor/hello`" && + die "re-read vendor hello after flash vendor" + check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor fi -if ! ${uses_dynamic_scratch}; then - fastboot reboot-bootloader || - die "Reboot into fastboot" -fi -if ${uses_dynamic_scratch}; then - echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2 - fastboot erase ${scratch_partition} && - ( fastboot reboot || true) && - die "fastboot can erase ${scratch_partition}" -fi -echo "${BLUE}[ INFO ]${NORMAL} expect fastboot format ${scratch_partition} to fail" >&2 -fastboot format ${scratch_partition} && - ( fastboot reboot || true) && - die "fastboot can format ${scratch_partition}" -fastboot reboot || - die "can not reboot out of fastboot" -echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot ... waiting 2 minutes" -adb_wait 2m || - die "did not reboot after flash" -adb_root && - D=`adb_sh df -k /dev/null || - die "overlay system takeover after flash vendor" -echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null && - die "overlay minus vendor takeover after flash vendor" -B="`adb_cat /system/hello`" || - die "re-read system hello after flash vendor" -check_eq "${A}" "${B}" system after flash vendor -adb_root || - die "adb root" -B="`adb_cat /vendor/hello`" && - die "re-read vendor hello after flash vendor" -check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor echo "${GREEN}[ RUN ]${NORMAL} remove test content (cleanup)" >&2 @@ -524,32 +618,35 @@ B="`adb_cat /vendor/hello`" && die "re-read vendor hello after rm" check_eq "cat: /vendor/hello: No such file or directory" "${B}" after flash rm -echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition}" >&2 +if [ -n "${scratch_partition}" ]; then -adb reboot-fastboot || - die "Reboot into fastbootd" -dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null && - fastboot_wait 2m || - ( rm /tmp/adb-remount-test.img && false) || - die "reboot into fastboot" -fastboot flash --force ${scratch_partition} /tmp/adb-remount-test.img -err=${?} -rm /tmp/adb-remount-test.img -fastboot reboot || - die "can not reboot out of fastboot" -[ 0 -eq ${err} ] || - die "fastboot flash ${scratch_partition}" -adb_wait 2m && - adb_root || - die "did not reboot after flash" -T=`adb_date` -D=`adb disable-verity 2>&1` -err=${?} -echo "${D}" -[ ${err} = 0 ] && - [ X"${D}" = X"${D##*setup failed}" ] && - [ X"${D}" != X"${D##*using overlayfs}" ] && - echo "${GREEN}[ OK ]${NORMAL} ${scratch_partition} recreated" >&2 || - die -t ${T} "setup for overlayfs" + echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition}" >&2 + + adb reboot-fastboot || + die "Reboot into fastbootd" + dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null && + fastboot_wait 2m || + ( rm /tmp/adb-remount-test.img && false) || + die "reboot into fastboot" + fastboot flash --force ${scratch_partition} /tmp/adb-remount-test.img + err=${?} + rm /tmp/adb-remount-test.img + fastboot reboot || + die "can not reboot out of fastboot" + [ 0 -eq ${err} ] || + die "fastboot flash ${scratch_partition}" + adb_wait 2m && + adb_root || + die "did not reboot after flash" + T=`adb_date` + D=`adb disable-verity 2>&1` + err=${?} + echo "${D}" + [ ${err} = 0 ] && + [ X"${D}" = X"${D##*setup failed}" ] && + [ X"${D}" != X"${D##*using overlayfs}" ] && + echo "${GREEN}[ OK ]${NORMAL} ${scratch_partition} recreated" >&2 || + die -t ${T} "setup for overlayfs" +fi echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2