| #! /bin/bash |
| # |
| # Divided into four section: |
| # |
| ## USAGE |
| ## Helper Variables |
| ## Helper Functions |
| ## MAINLINE |
| |
| ## |
| ## USAGE |
| ## |
| |
| USAGE="USAGE: `basename ${0}` [--help] [--serial <SerialNumber>] [options] |
| |
| adb remount tests |
| |
| --help This help |
| --serial Specify device (must if multiple are present) |
| --color Dress output with highlighting colors |
| --print-time Report the test duration |
| |
| Conditions: |
| - Must be a userdebug build. |
| - Must be in adb mode. |
| - Also tests overlayfs |
| - Kernel must have overlayfs enabled and patched to support override_creds. |
| - Must have either erofs, squashfs, ext4-dedupe or full partitions. |
| - Minimum expectation system and vender are overlayfs covered partitions. |
| " |
| |
| ## |
| ## Helper Variables |
| ## |
| |
| SPACE=" " |
| # A _real_ embedded tab character |
| TAB="`echo | tr '\n' '\t'`" |
| # A _real_ embedded escape character |
| ESCAPE="`echo | tr '\n' '\033'`" |
| # A _real_ embedded carriage return character |
| CR="`echo | tr '\n' '\r'`" |
| GREEN="${ESCAPE}[38;5;40m" |
| RED="${ESCAPE}[38;5;196m" |
| ORANGE="${ESCAPE}[38;5;255:165:0m" |
| BLUE="${ESCAPE}[35m" |
| NORMAL="${ESCAPE}[0m" |
| TMPDIR=${TMPDIR:-/tmp} |
| print_time=false |
| start_time=`date +%s` |
| ACTIVE_SLOT= |
| |
| ## |
| ## Helper Functions |
| ## |
| |
| [ "USAGE: inFastboot |
| |
| Returns: true if device is in fastboot mode" ] |
| inFastboot() { |
| fastboot devices | |
| if [ -n "${ANDROID_SERIAL}" ]; then |
| grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null |
| else |
| wc -l | grep '^1$' >/dev/null |
| fi |
| } |
| |
| [ "USAGE: inAdb |
| |
| Returns: true if device is in adb mode" ] |
| inAdb() { |
| adb devices | |
| 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 <commands> </dev/stdin >/dev/stdout 2>/dev/stderr |
| |
| Returns: true if the command succeeded" ] |
| adb_sh() { |
| local args= |
| for i in "${@}"; do |
| [ -z "${args}" ] || args="${args} " |
| if [ X"${i}" != X"${i#\'}" ]; then |
| args="${args}${i}" |
| elif [ X"${i}" != X"${i#* }" ]; then |
| args="${args}'${i}'" |
| elif [ X"${i}" != X"${i#*${TAB}}" ]; then |
| args="${args}'${i}'" |
| else |
| args="${args}${i}" |
| fi |
| done |
| adb shell "${args}" |
| } |
| |
| [ "USAGE: adb_date >/dev/stdout |
| |
| Returns: report device epoch time (suitable for logcat -t)" ] |
| adb_date() { |
| adb_sh date +%s.%N </dev/null |
| } |
| |
| [ "USAGE: adb_logcat [arguments] >/dev/stdout |
| |
| Returns: the logcat output" ] |
| adb_logcat() { |
| echo "${RED}[ INFO ]${NORMAL} logcat ${@}" >&2 && |
| adb logcat "${@}" </dev/null | |
| grep -v 'logd : logdr: UID=' | |
| sed -e '${/------- beginning of kernel/d}' -e 's/^[0-1][0-9]-[0-3][0-9] //' |
| } |
| |
| [ "USAGE: get_property <prop> |
| |
| Returns the property value" ] |
| get_property() { |
| adb_sh getprop ${1} </dev/null |
| } |
| |
| [ "USAGE: isDebuggable |
| |
| Returns: true if device is (likely) a debug build" ] |
| isDebuggable() { |
| if inAdb && [ 1 != "`get_property ro.debuggable`" ]; then |
| false |
| fi |
| } |
| |
| [ "USAGE: adb_su <commands> </dev/stdin >/dev/stdout 2>/dev/stderr |
| |
| Returns: true if the command running as root succeeded" ] |
| adb_su() { |
| adb_sh su root "${@}" |
| } |
| |
| [ "USAGE: adb_cat <file> >stdout |
| |
| Returns: content of file to stdout with carriage returns skipped, |
| true of the file exists" ] |
| adb_cat() { |
| local OUTPUT="`adb_sh cat ${1} </dev/null 2>&1`" |
| local ret=${?} |
| echo "${OUTPUT}" | tr -d '\r' |
| return ${ret} |
| } |
| |
| [ "USAGE: adb_reboot |
| |
| Returns: true if the reboot command succeeded" ] |
| adb_reboot() { |
| adb reboot remount-test || true |
| sleep 2 |
| } |
| |
| [ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d] |
| |
| human readable output whole seconds, whole minutes or mm:ss" ] |
| format_duration() { |
| if [ -z "${1}" ]; then |
| echo unknown |
| return |
| fi |
| local duration="${1}" |
| if [ X"${duration}" != X"${duration%s}" ]; then |
| duration=${duration%s} |
| elif [ X"${duration}" != X"${duration%m}" ]; then |
| duration=`expr ${duration%m} \* 60` |
| elif [ X"${duration}" != X"${duration%h}" ]; then |
| duration=`expr ${duration%h} \* 3600` |
| elif [ X"${duration}" != X"${duration%d}" ]; then |
| duration=`expr ${duration%d} \* 86400` |
| fi |
| 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 |
| return |
| fi |
| echo ${duration} seconds |
| return |
| elif [ 60 -eq ${duration} ]; then |
| echo 1 minute |
| return |
| elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then |
| echo ${minutes} minutes |
| return |
| fi |
| if [ 0 -eq ${hours} ]; then |
| echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10` |
| return |
| fi |
| echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10` |
| } |
| |
| [ "USAGE: adb_wait [timeout] |
| |
| Returns: waits until the device has returned for adb or optional timeout" ] |
| adb_wait() { |
| local ret |
| 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 2>/dev/null |
| ret=${?} |
| echo -n " ${CR}" |
| else |
| adb wait-for-device |
| ret=${?} |
| fi |
| if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then |
| local active_slot=`get_active_slot` |
| if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2 |
| fi |
| fi |
| return ${ret} |
| } |
| |
| [ "USAGE: usb_status > stdout |
| |
| 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 |
| echo "(USB stack borken?)" |
| fi |
| } |
| |
| [ "USAGE: fastboot_wait [timeout] |
| |
| Returns: waits until the device has returned for fastboot or optional timeout" ] |
| fastboot_wait() { |
| local ret |
| # fastboot has no wait-for-device, but it does an automatic |
| # wait and requires (even a nonsensical) command to do so. |
| 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 |
| ret=${?} |
| echo -n " ${CR}" |
| ( exit ${ret} ) |
| else |
| fastboot wait-for-device >/dev/null 2>/dev/null |
| fi || |
| inFastboot |
| ret=${?} |
| if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then |
| local active_slot=`get_active_slot` |
| if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2 |
| fi |
| fi |
| return ${ret} |
| } |
| |
| [ "USAGE: recovery_wait [timeout] |
| |
| Returns: waits until the device has returned for recovery or optional timeout" ] |
| recovery_wait() { |
| local ret |
| 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 |
| ret=${?} |
| echo -n " ${CR}" |
| else |
| adb wait-for-recovery |
| ret=${?} |
| fi |
| if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then |
| local active_slot=`get_active_slot` |
| if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2 |
| fi |
| fi |
| return ${ret} |
| } |
| |
| [ "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 |
| |
| Returns: true if device in root state" ] |
| adb_root() { |
| [ root != "`adb_sh echo '${USER}' </dev/null`" ] || return 0 |
| adb root >/dev/null </dev/null 2>/dev/null |
| sleep 2 |
| adb_wait 2m && |
| [ root = "`adb_sh echo '${USER}' </dev/null`" ] |
| } |
| |
| [ "USAGE: adb_unroot |
| |
| NB: This can be flakey on devices due to USB state |
| |
| Returns: true if device in un root state" ] |
| adb_unroot() { |
| [ root = "`adb_sh echo '${USER}' </dev/null`" ] || return 0 |
| adb unroot >/dev/null </dev/null 2>/dev/null |
| sleep 2 |
| adb_wait 2m && |
| [ root != "`adb_sh echo '${USER}' </dev/null`" ] |
| } |
| |
| [ "USAGE: fastboot_getvar var expected >/dev/stderr |
| |
| Returns: true if var output matches expected" ] |
| fastboot_getvar() { |
| local O=`fastboot getvar ${1} 2>&1` |
| local ret=${?} |
| O="${O#< waiting for * >?}" |
| O="${O%%?Finished. Total time: *}" |
| if [ 0 -ne ${ret} ]; then |
| echo ${O} >&2 |
| false |
| return |
| fi |
| if [ "${O}" != "${O#*FAILED}" ]; then |
| O="${1}: <empty>" |
| fi |
| if [ -n "${2}" -a "${1}: ${2}" != "${O}" ]; then |
| echo "${2} != ${O}" >&2 |
| false |
| return |
| fi |
| echo ${O} >&2 |
| } |
| |
| [ "USAGE: get_active_slot >/dev/stdout |
| |
| Returns: with a or b string reporting active slot" ] |
| get_active_slot() { |
| if inAdb || inRecovery; then |
| get_property ro.boot.slot_suffix | tr -d _ |
| elif inFastboot; then |
| fastboot_getvar current-slot 2>&1 | sed -n 's/current-slot: //p' |
| else |
| false |
| fi |
| } |
| |
| [ "USAGE: restore |
| |
| Do nothing: should be redefined when necessary. Called after cleanup. |
| |
| Returns: reverses configurations" ] |
| restore() { |
| true |
| } |
| |
| [ "USAGE: cleanup |
| |
| Do nothing: should be redefined when necessary |
| |
| Returns: cleans up any latent resources" ] |
| cleanup() { |
| true |
| } |
| |
| [ "USAGE: test_duration >/dev/stderr |
| |
| Prints the duration of the test |
| |
| Returns: reports duration" ] |
| test_duration() { |
| if ${print_time}; then |
| echo "${BLUE}[ INFO ]${NORMAL} end `date`" |
| [ -n "${start_time}" ] || return |
| end_time=`date +%s` |
| local diff_time=`expr ${end_time} - ${start_time}` |
| echo "${BLUE}[ INFO ]${NORMAL} duration `format_duration ${diff_time}`" |
| fi >&2 |
| } |
| |
| [ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr |
| |
| If -d, or -t <epoch> argument is supplied, dump logcat. |
| |
| Returns: exit failure, report status" ] |
| die() { |
| if [ X"-d" = X"${1}" ]; then |
| adb_logcat -b all -v nsec -d >&2 |
| shift |
| elif [ X"-t" = X"${1}" ]; then |
| if [ -n "${2}" ]; then |
| adb_logcat -b all -v nsec -t ${2} >&2 |
| else |
| adb_logcat -b all -v nsec -d >&2 |
| fi |
| shift 2 |
| fi |
| echo "${RED}[ FAILED ]${NORMAL} ${@}" >&2 |
| cleanup |
| restore |
| test_duration |
| exit 1 |
| } |
| |
| [ "USAGE: EXPECT_EQ <lval> <rval> [--warning [message]] |
| |
| Returns true if (regex) lval matches rval" ] |
| EXPECT_EQ() { |
| 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 ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then |
| if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval% |
| *}" ]; then |
| echo "${prefix} expected \"${lval}\"" >&2 |
| echo "${prefix} got \"${rval}\"" | |
| sed ': again |
| N |
| s/\(\n\)\([^ ]\)/\1 \2/ |
| t again' >&2 |
| if [ -n "${*}" ] ; then |
| echo "${prefix} ${*}" >&2 |
| fi |
| else |
| echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}" >&2 |
| fi |
| return ${error} |
| fi |
| if [ -n "${*}" ] ; then |
| prefix="${GREEN}[ INFO ]${NORMAL}" |
| if [ X"${lval}" != X"${rval}" ]; then # we were supplied a regex? |
| if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval% *}" ]; then |
| echo "${prefix} ok \"${lval}\"" >&2 |
| echo " = \"${rval}\"" | |
| sed ': again |
| N |
| s/\(\n\)\([^ ]\)/\1 \2/ |
| t again' >&2 |
| if [ -n "${*}" ] ; then |
| echo "${prefix} ${*}" >&2 |
| fi |
| else |
| echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}" >&2 |
| fi |
| else |
| echo "${prefix} ok \"${lval}\" ${*}" >&2 |
| fi |
| fi |
| return 0 |
| } |
| |
| [ "USAGE: check_eq <lval> <rval> [--warning [message]] |
| |
| Exits if (regex) lval mismatches rval" ] |
| check_eq() { |
| local lval="${1}" |
| local rval="${2}" |
| shift 2 |
| if [ X"${1}" = X"--warning" ]; then |
| EXPECT_EQ "${lval}" "${rval}" ${*} |
| return |
| fi |
| EXPECT_EQ "${lval}" "${rval}" || |
| die "${@}" |
| } |
| |
| [ "USAGE: skip_administrative_mounts [data] < /proc/mounts |
| |
| Filters out all administrative (eg: sysfs) mounts uninteresting to the test" ] |
| skip_administrative_mounts() { |
| if [ "data" = "${1}" ]; then |
| grep -v " /data " |
| else |
| cat - |
| fi | |
| grep -v \ |
| -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\|bpf\) " \ |
| -e "^\(binfmt_misc\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \ |
| -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \ |
| -e "^rootfs / rootfs rw," \ |
| -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 |
| ## |
| |
| OPTIONS=`getopt --alternative --unquoted \ |
| --longoptions help,serial:,colour,color,no-colour,no-color \ |
| --longoptions gtest_print_time,print-time \ |
| -- "?hs:" ${*}` || |
| ( echo "${USAGE}" >&2 ; false ) || |
| die "getopt failure" |
| set -- ${OPTIONS} |
| |
| color=false |
| while [ ${#} -gt 0 ]; do |
| case ${1} in |
| -h | --help | -\?) |
| echo "${USAGE}" >&2 |
| exit 0 |
| ;; |
| -s | --serial) |
| export ANDROID_SERIAL=${2} |
| shift |
| ;; |
| --color | --colour) |
| color=true |
| ;; |
| --no-color | --no-colour) |
| color=false |
| ;; |
| --print-time | --gtest_print_time) |
| print_time=true |
| ;; |
| --) |
| shift |
| break |
| ;; |
| -*) |
| echo "${USAGE}" >&2 |
| die "${0}: error unknown option ${1}" |
| ;; |
| *) |
| break |
| ;; |
| esac |
| shift |
| done |
| if ! ${color}; then |
| GREEN="" |
| RED="" |
| ORANGE="" |
| BLUE="" |
| NORMAL="" |
| fi |
| |
| if ${print_time}; then |
| echo "${BLUE}[ INFO ]${NORMAL}" start `date` >&2 |
| 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" >&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 | grep 'Enforcing' >/dev/null; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2 |
| enforcing=false |
| fi |
| |
| # Do something. |
| |
| D=`get_property ro.serialno` |
| [ -n "${D}" ] || D=`get_property ro.boot.serialno` |
| [ -z "${D}" -o -n "${ANDROID_SERIAL}" ] || ANDROID_SERIAL=${D} |
| USB_SERIAL= |
| [ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial | |
| grep usb | |
| xargs grep -l ${ANDROID_SERIAL}` |
| USB_ADDRESS= |
| if [ -n "${USB_SERIAL}" ]; then |
| USB_ADDRESS=${USB_SERIAL%/serial} |
| USB_ADDRESS=usb${USB_ADDRESS##*/} |
| fi |
| [ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] || |
| echo "${BLUE}[ INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} >&2 |
| BUILD_DESCRIPTION=`get_property ro.build.description` |
| [ -z "${BUILD_DESCRIPTION}" ] || |
| echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2 |
| ACTIVE_SLOT=`get_active_slot` |
| [ -z "${ACTIVE_SLOT}" ] || |
| echo "${BLUE}[ INFO ]${NORMAL} active slot is ${ACTIVE_SLOT}" >&2 |
| |
| # Report existing partition sizes |
| adb_sh ls -l /dev/block/by-name/ </dev/null 2>/dev/null | |
| sed -n 's@.* \([^ ]*\) -> /dev/block/\([^ ]*\)$@\1 \2@p' | |
| while read name device; do |
| case ${name} in |
| system_[ab] | system | vendor_[ab] | vendor | super | cache) |
| case ${device} in |
| sd*) |
| device=${device%%[0-9]*}/${device} |
| ;; |
| esac |
| size=`adb_su cat /sys/block/${device}/size 2>/dev/null </dev/null` && |
| size=`expr ${size} / 2` && |
| echo "${BLUE}[ INFO ]${NORMAL} partition ${name} device ${device} size ${size}K" >&2 |
| ;; |
| esac |
| done |
| |
| # Can we test remount -R command? |
| overlayfs_supported=true |
| if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \ |
| "2" = "`get_property partition.system.verified`" ]; then |
| restore() { |
| ${overlayfs_supported} || return 0 |
| inFastboot && |
| fastboot reboot && |
| adb_wait 2m |
| inAdb && |
| adb_root && |
| adb enable-verity >/dev/null 2>/dev/null && |
| adb_reboot && |
| adb_wait 2m |
| } |
| |
| echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2 |
| |
| adb_su remount -R system </dev/null || true |
| sleep 2 |
| adb_wait 2m || |
| die "waiting for device after remount -R `usb_status`" |
| if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ |
| "2" = "`get_property partition.system.verified`" ]; then |
| die "remount -R command failed" |
| fi |
| |
| echo "${GREEN}[ OK ]${NORMAL} adb shell su root remount -R command" >&2 |
| fi |
| |
| echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2 |
| |
| adb_wait || die "wait for device failed" |
| adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null || |
| adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null && |
| echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 || |
| ( |
| echo "${ORANGE}[ WARNING ]${NORMAL} overlay module not present" >&2 && |
| false |
| ) || |
| overlayfs_supported=false |
| if ${overlayfs_supported}; then |
| adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null 2>/dev/null && |
| echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 || |
| case `adb_sh uname -r </dev/null` in |
| 4.[456789].* | 4.[1-9][0-9]* | [56789].*) |
| echo "${ORANGE}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 && |
| overlayfs_supported=false |
| ;; |
| *) |
| echo "${GREEN}[ OK ]${NORMAL} overlay module uses caller's 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 >/dev/null 2>/dev/null; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2 |
| adb_sh rm -rf /${d}/overlay </dev/null || |
| die "/${d}/overlay wipe" |
| reboot=true |
| fi |
| done |
| if ${reboot}; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2 |
| adb_reboot && |
| adb_wait 2m || |
| die "lost device after reboot after wipe `usb_status`" |
| adb_root || |
| die "lost device after elevation to root after wipe `usb_status`" |
| fi |
| D=`adb_sh df -k </dev/null` && |
| H=`echo "${D}" | head -1` && |
| D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` && |
| echo "${H}" && |
| echo "${D}" && |
| echo "${ORANGE}[ WARNING ]${NORMAL} overlays present before setup" >&2 || |
| echo "${GREEN}[ OK ]${NORMAL} no overlay present before setup" >&2 |
| overlayfs_needed=true |
| D=`adb_sh cat /proc/mounts </dev/null | |
| skip_administrative_mounts data` |
| if echo "${D}" | grep /dev/root >/dev/null; then |
| D=`echo / / |
| echo "${D}" | grep -v /dev/root` |
| fi |
| D=`echo "${D}" | cut -s -d' ' -f1 | sort -u` |
| no_dedupe=true |
| for d in ${D}; do |
| adb_sh tune2fs -l $d </dev/null 2>&1 | |
| grep "Filesystem features:.*shared_blocks" >/dev/null && |
| no_dedupe=false |
| done |
| D=`adb_sh df -k ${D} </dev/null | |
| sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` |
| echo "${D}" |
| if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then |
| overlayfs_needed=false |
| elif ! ${overlayfs_supported}; then |
| die "need overlayfs, but do not have it" |
| fi |
| |
| echo "${GREEN}[ RUN ]${NORMAL} disable verity" >&2 |
| |
| T=`adb_date` |
| H=`adb disable-verity 2>&1` |
| err=${?} |
| L= |
| D="${H%?Now reboot your device for settings to take effect*}" |
| if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then |
| echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 |
| fi |
| if [ ${err} != 0 ]; then |
| echo "${H}" |
| ( [ -n "${L}" ] && echo "${L}" && false ) || |
| die -t "${T}" "disable-verity" |
| fi |
| rebooted=false |
| if [ X"${D}" != X"${H}" ]; then |
| echo "${H}" |
| if [ X"${D}" != X"${D##*setup failed}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} overlayfs setup whined" >&2 |
| fi |
| D=`adb_sh df -k </dev/null` && |
| H=`echo "${D}" | head -1` && |
| D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` && |
| [ -z "${D}" ] || |
| ( echo "${H}" && echo "${D}" && false ) || |
| die -t ${T} "overlay takeover unexpected at this phase" |
| echo "${GREEN}[ INFO ]${NORMAL} rebooting as requested" >&2 |
| L=`adb_logcat -b all -v nsec -t ${T} 2>&1` |
| adb_reboot && |
| adb_wait 2m || |
| die "lost device after reboot requested `usb_status`" |
| adb_root || |
| die "lost device after elevation to root `usb_status`" |
| 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##*[Uu]sing 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 "${H}" |
| D=`adb_sh df -k </dev/null` && |
| H=`echo "${D}" | head -1` && |
| D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` && |
| [ -z "${D}" ] || |
| ( echo "${H}" && echo "${D}" && false ) || |
| ( [ -n "${L}" ] && echo "${L}" && false ) || |
| die -t "${T}" "overlay takeover unexpected" |
| [ -n "${L}" ] && echo "${L}" |
| die -t "${T}" "unexpected report of verity being disabled a second time" |
| elif ${rebooted}; then |
| echo "${GREEN}[ OK ]${NORMAL} verity already disabled" >&2 |
| else |
| echo "${ORANGE}[ WARNING ]${NORMAL} verity already disabled" >&2 |
| fi |
| |
| echo "${GREEN}[ RUN ]${NORMAL} remount" >&2 |
| |
| D=`adb remount 2>&1` |
| ret=${?} |
| echo "${D}" |
| [ ${ret} != 0 ] || |
| [ X"${D}" = X"${D##*remount failed}" ] || |
| ( [ -n "${L}" ] && echo "${L}" && false ) || |
| die -t "${T}" "adb remount failed" |
| D=`adb_sh df -k </dev/null` && |
| H=`echo "${D}" | head -1` && |
| D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` || |
| ( [ -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 |
| echo "${D}" | grep "^overlay .* /system\$" >/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 </dev/null | |
| 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 2>/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 >/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 </dev/null | |
| skip_unrelated_mounts | |
| grep " overlay ro,") || |
| die "remount overlayfs missed a spot (ro)" |
| D=`adb_sh grep " rw," /proc/mounts </dev/null | |
| skip_administrative_mounts data` |
| if echo "${D}" | grep /dev/root >/dev/null; then |
| D=`echo / / |
| echo "${D}" | grep -v /dev/root` |
| fi |
| D=`echo "${D}" | cut -s -d' ' -f1 | sort -u` |
| bad_rw=false |
| for d in ${D}; do |
| if adb_sh tune2fs -l $d </dev/null 2>&1 | |
| grep "Filesystem features:.*shared_blocks" >/dev/null; then |
| bad_rw=true |
| else |
| d=`adb_sh df -k ${D} </dev/null | |
| sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` |
| [ X"${d}" = X"${d##* 100[%] }" ] || |
| bad_rw=true |
| fi |
| done |
| [ -z "${D}" ] || |
| D=`adb_sh df -k ${D} </dev/null | |
| sed -e 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@' \ |
| -e 's/^Filesystem /Filesystem (rw) /'` |
| [ -z "${D}" ] || echo "${D}" |
| ${bad_rw} && die "remount overlayfs missed a spot (rw)" |
| else |
| if [ ${ret} = 0 ]; then |
| die -t ${T} "unexpected overlay takeover" |
| fi |
| fi |
| |
| # Check something. |
| |
| echo "${GREEN}[ RUN ]${NORMAL} push content to /system and /vendor" >&2 |
| |
| A="Hello World! $(date)" |
| echo "${A}" | adb_sh cat - ">/system/hello" |
| echo "${A}" | adb_sh cat - ">/vendor/hello" |
| B="`adb_cat /system/hello`" || |
| die "sytem hello" |
| check_eq "${A}" "${B}" /system before reboot |
| B="`adb_cat /vendor/hello`" || |
| die "vendor hello" |
| check_eq "${A}" "${B}" /vendor before reboot |
| |
| # Download libc.so, append some gargage, push back, and check if the file |
| # is updated. |
| tempdir="`mktemp -d`" |
| cleanup() { |
| rm -rf ${tempdir} |
| } |
| adb pull /system/lib/bootstrap/libc.so ${tempdir} >/dev/null || |
| die "pull libc.so from device" |
| garbage="`hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random`" |
| echo ${garbage} >> ${tempdir}/libc.so |
| adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so >/dev/null || |
| die "push libc.so to device" |
| adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || |
| die "pull libc.so from device" |
| diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || |
| die "libc.so differ" |
| |
| echo "${GREEN}[ RUN ]${NORMAL} reboot to confirm content persistent" >&2 |
| |
| adb_reboot && |
| adb_wait 2m || |
| die "reboot after override content added failed `usb_status`" |
| |
| if ${overlayfs_needed}; then |
| D=`adb_su df -k </dev/null` && |
| H=`echo "${D}" | head -1` && |
| D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` || |
| ( echo "${L}" && false ) || |
| die -d "overlay takeover failed after reboot" |
| |
| adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null | |
| skip_administrative_mounts | |
| grep -v ' \(erofs\|squashfs\|ext4\|f2fs\|vfat\) ' && |
| echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 || |
| echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2 |
| fi |
| |
| if ${enforcing}; then |
| 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 |
| 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 |
| |
| # 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 || |
| die "pull libc.so from device" |
| diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ" |
| rm -rf ${tempdir} |
| cleanup() { |
| true |
| } |
| echo "${GREEN}[ OK ]${NORMAL} /system/lib/bootstrap/libc.so content remains after reboot" >&2 |
| |
| echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears" >&2 |
| |
| H=`adb_sh echo '${HOSTNAME}' </dev/null 2>/dev/null` |
| is_bootloader_fastboot=false |
| # cuttlefish? |
| [ X"${H}" != X"${H#vsoc}" ] || is_bootloader_fastboot=true |
| is_userspace_fastboot=false |
| |
| if ! ${is_bootloader_fastboot}; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} does not support fastboot, skipping" |
| elif [ -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" |
| elif [ -z "${ANDROID_HOST_OUT}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} please run lunch, skipping" |
| else |
| adb reboot fastboot || |
| die "fastbootd not supported (wrong adb in path?)" |
| 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" |
| fastboot_getvar is-userspace yes && |
| is_userspace_fastboot=true |
| 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" |
| adb_wait 2m || |
| die "did not reboot after flash `usb_status`" |
| if ${overlayfs_needed}; then |
| adb_root && |
| D=`adb_sh df -k </dev/null` && |
| H=`echo "${D}" | head -1` && |
| D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` && |
| echo "${H}" && |
| echo "${D}" && |
| echo "${D}" | grep "^overlay .* /system\$" >/dev/null || |
| die "overlay /system takeover after flash vendor" |
| echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null && |
| if ${is_userspace_fastboot}; then |
| die "overlay supposed to be minus /vendor takeover after flash vendor" |
| else |
| 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`" |
| check_eq "${A}" "${B}" system after flash vendor |
| adb_root || |
| die "adb root" |
| B="`adb_cat /vendor/hello`" |
| if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then |
| check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ |
| vendor content after flash vendor |
| else |
| echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 |
| check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ |
| --warning vendor content after flash vendor |
| fi |
| fi |
| |
| echo "${GREEN}[ RUN ]${NORMAL} remove test content (cleanup)" >&2 |
| |
| T=`adb_date` |
| H=`adb remount 2>&1` |
| err=${?} |
| L= |
| D="${H%?Now reboot your device for settings to take effect*}" |
| 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_root || |
| die "failed to reboot" |
| T=`adb_date` |
| H=`adb remount 2>&1` |
| err=${?} |
| fi |
| echo "${H}" |
| [ ${err} = 0 ] && |
| ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) && |
| adb_sh rm /system/hello </dev/null || |
| ( [ -n "${L}" ] && echo "${L}" && false ) || |
| die -t ${T} "cleanup hello" |
| B="`adb_cat /system/hello`" |
| check_eq "cat: /system/hello: No such file or directory" "${B}" after rm |
| B="`adb_cat /vendor/hello`" |
| check_eq "cat: /vendor/hello: No such file or directory" "${B}" after rm |
| |
| if [ -n "${scratch_partition}" ]; then |
| |
| echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition} recovery" >&2 |
| |
| adb reboot fastboot || |
| die "Reboot into fastbootd" |
| img=${TMPDIR}/adb-remount-test-${$}.img |
| cleanup() { |
| rm ${img} |
| } |
| dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null && |
| fastboot_wait 2m || |
| die "reboot into fastboot `usb_status`" |
| fastboot flash --force ${scratch_partition} ${img} |
| err=${?} |
| cleanup |
| cleanup() { |
| true |
| } |
| 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=${?} |
| if [ X"${D}" != "${D%?Now reboot your device for settings to take effect*}" ] |
| then |
| echo "${ORANGE}[ WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash" |
| adb_reboot && |
| adb_wait 2m && |
| adb_root || |
| die "failed to reboot" |
| T=`adb_date` |
| D="${D} |
| `adb disable-verity 2>&1`" |
| err=${?} |
| fi |
| |
| echo "${D}" |
| [ ${err} = 0 ] && |
| [ X"${D}" = X"${D##*setup failed}" ] && |
| [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] && |
| echo "${GREEN}[ OK ]${NORMAL} ${scratch_partition} recreated" >&2 || |
| die -t ${T} "setup for overlayfs" |
| D=`adb remount 2>&1` |
| err=${?} |
| echo "${D}" |
| [ ${err} != 0 ] || |
| [ X"${D}" = X"${D##*remount failed}" ] || |
| ( echo "${D}" && false ) || |
| die -t ${T} "remount failed" |
| fi |
| |
| 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_status`" |
| adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && |
| die "/vendor is not read-only" |
| adb_su mount -o rw,remount /vendor </dev/null || |
| die "remount command" |
| adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || |
| die "/vendor is not read-write" |
| echo "${GREEN}[ OK ]${NORMAL} mount -o rw,remount command works" >&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 && |
| die "/vendor is not read-only" |
| adb_su remount vendor </dev/null || |
| die "remount command" |
| adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || |
| die "/vendor is not read-write" |
| adb_sh grep " /system .* rw," /proc/mounts >/dev/null </dev/null && |
| die "/vendor is not read-only" |
| echo "${GREEN}[ OK ]${NORMAL} remount command works from setup" >&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 || |
| die "/${d}/overlay wipe" |
| done |
| adb_reboot && |
| adb_wait 2m || |
| die "lost device after reboot after wipe (USB stack broken?)" |
| adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && |
| die "/vendor is not read-only" |
| adb_su remount vendor </dev/null || |
| die "remount command" |
| adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || |
| die "/vendor is not read-write" |
| adb_sh grep " /system .* rw," /proc/mounts >/dev/null </dev/null && |
| die "/system is not read-only" |
| 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 |
| } |
| |
| [ ${err} = 0 ] || |
| die "failed to restore verity" >&2 |
| |
| echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2 |
| |
| test_duration |