diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh index e6625e74a..c52389345 100755 --- a/fs_mgr/tests/adb-remount-test.sh +++ b/fs_mgr/tests/adb-remount-test.sh @@ -33,6 +33,7 @@ Conditions: ## Helper Variables ## +EMPTY="" SPACE=" " # A _real_ embedded tab character TAB="`echo | tr '\n' '\t'`" @@ -50,6 +51,9 @@ print_time=false start_time=`date +%s` ACTIVE_SLOT= +ADB_WAIT=3m +FASTBOOT_WAIT=2m + ## ## Helper Functions ## @@ -131,10 +135,30 @@ Returns: the logcat output" ] adb_logcat() { echo "${RED}[ INFO ]${NORMAL} logcat ${@}" >&2 && adb logcat "${@}" /dev/stderr + +Returns: worrisome avc violations" ] +avc_check() { + if ! ${overlayfs_supported:-false}; then + return + fi + local L=`adb_logcat -b all -v brief -d \ + -e 'context=u:object_r:unlabeled:s0' 2>/dev/null | + sed -n 's/.*avc: //p' | + sort -u` + if [ -z "${L}" ]; then + return + fi + echo "${ORANGE}[ WARNING ]${NORMAL} unlabeled sepolicy violations:" >&2 + echo "${L}" | + sed 's/^/ /' >&2 +} + [ "USAGE: get_property Returns the property value" ] @@ -173,6 +197,7 @@ adb_cat() { Returns: true if the reboot command succeeded" ] adb_reboot() { + avc_check adb reboot remount-test /dev/null ret=${?} echo -n " ${CR}" @@ -258,9 +286,45 @@ adb_wait() { echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2 fi fi + local end=`date +%s` + local diff_time=`expr ${end} - ${start}` + local _print_time=${print_time} + if [ ${diff_time} -lt 15 ]; then + _print_time=false + fi + diff_time=`format_duration ${diff_time}` + if [ "${diff_time}" = "${duration}" ]; then + _print_time=false + fi + + local reason= + if inAdb; then + reason=`get_property ro.boot.bootreason` + fi + case ${reason} in + reboot*) + reason= + ;; + ${EMPTY}) + ;; + *) + reason=" for boot reason ${reason}" + ;; + esac + if ${_print_time} || [ -n "${reason}" ]; then + echo "${BLUE}[ INFO ]${NORMAL} adb wait duration ${diff_time}${reason}" + fi >&2 + return ${ret} } +[ "USAGE: adb_user > /dev/stdout + +Returns: the adb daemon user" ] +adb_user() { + adb_sh echo '${USER}' stdout 2> stderr Assumes referenced right after adb_wait or fastboot_wait failued. @@ -276,7 +340,7 @@ usb_status() { elif inRecovery; then echo "(In recovery mode)" elif inAdb; then - echo "(In adb mode)" + echo "(In adb mode `adb_user`)" else echo "(USB stack borken for ${USB_ADDRESS})" USB_DEVICE=`usb_devnum` @@ -366,17 +430,68 @@ any_wait() { inFastboot || inAdb || inRecovery } +wait_for_screen_timeout=900 +[ "USAGE: wait_for_screen [-n] [TIMEOUT] + +-n - echo newline at exit +TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ] +wait_for_screen() { + exit_function=true + if [ X"-n" = X"${1}" ]; then + exit_function=echo + shift + fi + timeout=${wait_for_screen_timeout} + if [ ${#} -gt 0 ]; then + timeout=${1} + shift + fi + counter=0 + while true; do + if inFastboot; then + fastboot reboot + elif inAdb; then + if [ 0 != ${counter} ]; then + adb_wait + fi + if [ -n "`get_property sys.boot.reason`" ] + then + vals=`get_property | + sed -n 's/[[]sys[.]\(boot_completed\|logbootcomplete\)[]]: [[]\([01]\)[]]$/\1=\2/p'` + if [ "${vals}" = "`echo boot_completed=1 ; echo logbootcomplete=1`" ] + then + sleep 1 + break + fi + if [ "${vals}" = "`echo logbootcomplete=1 ; echo boot_completed=1`" ] + then + sleep 1 + break + fi + fi + fi + counter=`expr ${counter} + 1` + if [ ${counter} -gt ${timeout} ]; then + ${exit_function} + echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2 + return 1 + fi + sleep 1 + done + ${exit_function} +} + [ "USAGE: adb_root NB: This can be flakey on devices due to USB state Returns: true if device in root state" ] adb_root() { - [ root != "`adb_sh echo '${USER}' /dev/null /dev/null sleep 2 - adb_wait 2m && - [ root = "`adb_sh echo '${USER}' /dev/null /dev/null sleep 2 - adb_wait 2m && - [ root != "`adb_sh echo '${USER}' /dev/stderr @@ -540,6 +655,30 @@ EXPECT_EQ() { return 0 } +[ "USAGE: EXPECT_NE [--warning [message]] + +Returns true if lval matches rval" ] +EXPECT_NE() { + local lval="${1}" + local rval="${2}" + shift 2 + local error=1 + local prefix="${RED}[ ERROR ]${NORMAL}" + if [ X"${1}" = X"--warning" ]; then + prefix="${RED}[ WARNING ]${NORMAL}" + error=0 + shift 1 + fi + if [ X"${rval}" = X"${lval}" ]; then + echo "${prefix} did not expect \"${lval}\" ${*}" >&2 + return ${error} + fi + if [ -n "${*}" ] ; then + echo "${prefix} ok \"${lval}\" not \"${rval}\" ${*}" >&2 + fi + return 0 +} + [ "USAGE: check_eq [--warning [message]] Exits if (regex) lval mismatches rval" ] @@ -555,6 +694,21 @@ check_eq() { die "${@}" } +[ "USAGE: check_ne [--warning [message]] + +Exits if lval matches rval" ] +check_ne() { + local lval="${1}" + local rval="${2}" + shift 2 + if [ X"${1}" = X"--warning" ]; then + EXPECT_NE "${lval}" "${rval}" ${*} + return + fi + EXPECT_NE "${lval}" "${rval}" || + die "${@}" +} + [ "USAGE: skip_administrative_mounts [data] < /proc/mounts Filters out all administrative (eg: sysfs) mounts uninteresting to the test" ] @@ -645,7 +799,7 @@ inFastboot && die "device in fastboot mode" inRecovery && die "device in recovery mode" if ! inAdb; then echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" >&2 - adb_wait 2m + adb_wait ${ADB_WAIT} fi inAdb || die "specified device not in adb mode" isDebuggable || die "device not a debug build" @@ -697,6 +851,8 @@ adb_sh ls -l /dev/block/by-name/ /dev/null | esac done +# If reboot too soon after fresh flash, could trip device update failure logic +wait_for_screen # Can we test remount -R command? overlayfs_supported=true if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \ @@ -705,19 +861,20 @@ if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \ ${overlayfs_supported} || return 0 inFastboot && fastboot reboot && - adb_wait 2m + adb_wait ${ADB_WAIT} inAdb && adb_root && adb enable-verity >/dev/null 2>/dev/null && adb_reboot && - adb_wait 2m + adb_wait ${ADB_WAIT} } echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2 + avc_check adb_su remount -R system &2 adb_reboot && - adb_wait 2m || + adb_wait ${ADB_WAIT} || die "lost device after reboot after wipe `usb_status`" adb_root || die "lost device after elevation to root after wipe `usb_status`" @@ -840,7 +997,7 @@ if [ X"${D}" != X"${H}" ]; then echo "${GREEN}[ INFO ]${NORMAL} rebooting as requested" >&2 L=`adb_logcat -b all -v nsec -t ${T} 2>&1` adb_reboot && - adb_wait 2m || + adb_wait ${ADB_WAIT} || die "lost device after reboot requested `usb_status`" adb_root || die "lost device after elevation to root `usb_status`" @@ -881,6 +1038,11 @@ fi echo "${GREEN}[ RUN ]${NORMAL} remount" >&2 +# Feed log with selinux denials as baseline before overlays +adb_unroot +adb_sh find /system /vendor /dev/null 2>/dev/null +adb_root + D=`adb remount 2>&1` ret=${?} echo "${D}" @@ -981,6 +1143,26 @@ check_eq "${A}" "${B}" /system before reboot B="`adb_cat /vendor/hello`" || die "vendor hello" check_eq "${A}" "${B}" /vendor before reboot +SYSTEM_DEVT=`adb_sh stat --format=%D /system/hello &2 adb reboot &2 + # Feed unprivileged log with selinux denials as a result of overlays + wait_for_screen + adb_sh find /system /vendor /dev/null 2>/dev/null fi B="`adb_cat /system/hello`" check_eq "${A}" "${B}" /system after reboot @@ -1044,6 +1229,17 @@ B="`adb_cat /vendor/hello`" check_eq "${A}" "${B}" vendor after reboot echo "${GREEN}[ OK ]${NORMAL} /vendor content remains after reboot" >&2 +check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello /dev/null 2>/dev/null + # Check if the updated libc.so is persistent after reboot. adb_root && adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || @@ -1073,10 +1269,17 @@ elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then echo "${ORANGE}[ WARNING ]${NORMAL} wrong vendor image, skipping" elif [ -z "${ANDROID_HOST_OUT}" ]; then echo "${ORANGE}[ WARNING ]${NORMAL} please run lunch, skipping" +elif ! ( + adb_cat /vendor/build.prop | + cmp -s ${ANDROID_PRODUCT_OUT}/vendor/build.prop + ) >/dev/null 2>/dev/null; then + echo "${ORANGE}[ WARNING ]${NORMAL} vendor image signature mismatch, skipping" else + wait_for_screen + avc_check adb reboot fastboot &2 T=`adb_date` @@ -1163,7 +1373,7 @@ if [ X"${H}" != X"${D}" ]; then echo "${ORANGE}[ WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)" L=`adb_logcat -b all -v nsec -t ${T} 2>&1` adb_reboot && - adb_wait 2m && + adb_wait ${ADB_WAIT} && adb_root || die "failed to reboot" T=`adb_date` @@ -1185,6 +1395,7 @@ if [ -n "${scratch_partition}" ]; then echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition} recovery" >&2 + avc_check adb reboot fastboot /dev/null && - fastboot_wait 2m || + fastboot_wait ${FASTBOOT_WAIT} || die "reboot into fastboot `usb_status`" fastboot flash --force ${scratch_partition} ${img} err=${?} @@ -1204,7 +1415,7 @@ if [ -n "${scratch_partition}" ]; then die "can not reboot out of fastboot" [ 0 -eq ${err} ] || die "fastboot flash ${scratch_partition}" - adb_wait 2m && + adb_wait ${ADB_WAIT} && adb_root || die "did not reboot after flash" T=`adb_date` @@ -1214,7 +1425,7 @@ if [ -n "${scratch_partition}" ]; then then echo "${ORANGE}[ WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash" adb_reboot && - adb_wait 2m && + adb_wait ${ADB_WAIT} && adb_root || die "failed to reboot" T=`adb_date` @@ -1252,12 +1463,12 @@ fixup_from_fastboot() { fastboot --set-active=${ACTIVE_SLOT} fi fastboot reboot - adb_wait 2m + adb_wait ${ADB_WAIT} } # Prerequisite is a prepped device from above. adb_reboot && - adb_wait 2m || + adb_wait ${ADB_WAIT} || fixup_from_fastboot || die "lost device after reboot to ro state `usb_status`" adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null &2 # Prerequisite is a prepped device from above. adb_reboot && - adb_wait 2m || + adb_wait ${ADB_WAIT} || fixup_from_fastboot || die "lost device after reboot to ro state `usb_status`" adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null /dev/null &2 + avc_check adb_root && adb remount -R && - adb_wait 2m || + adb_wait ${ADB_WAIT} || die "adb remount -R" if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ "2" = "`get_property partition.system.verified`" ]; then