fs_mgr: harden adb-remount-test.sh

Harden adb-remount-test.sh script.  Add --no-color and --color
options.  Allows --serial to be passed in.  Add a recovery handler
that restores the device to verity enabled if possible.  List the
partitions sizes as they may be relevant to triaging errors.  Allow
for devices that have a mixed set of remounts, some direct, some
with overlayfs.  Allow two scripts to run at the same time on a host
machine targetting different devices.  Detect if wrong adb is used
for adb reboot-fastboot.

Add a build target for adb-remount-test.sh so that the script
is landed into the host tools bin for easy pickup.

Test: adb-remount-test.sh
Bug: 123079041
Change-Id: I6369a245a656419067ec4350a4dbdf78c9b0533e
This commit is contained in:
Mark Salyzyn 2019-02-13 13:06:15 -08:00
parent cd67fa9c1a
commit bbe33f7826
2 changed files with 198 additions and 50 deletions

View File

@ -36,3 +36,20 @@ cc_test {
"-Werror",
],
}
cc_prebuilt_binary {
name: "adb-remount-test.sh",
srcs: ["adb-remount-test.sh"],
target: {
darwin: {
enabled: false,
},
windows: {
enabled: false,
},
android: {
enabled: false,
},
},
host_supported: true,
}

View File

@ -11,23 +11,23 @@
## USAGE
##
USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]
USAGE="USAGE: `basename ${0}` [--help] [--serial <SerialNumber>] [--color]
adb remount tests (overlayfs focus)
adb remount tests
--help This help
--serial Specify device (must if multiple are present)
--color Dress output with highlighting colors
Conditions:
- Must be a userdebug build.
- Must be in adb mode.
- Kernel must have overlayfs enabled and patched to support override_creds.
- Must have either squashfs, ext4-dedupe or right-sized partitions.
- Minimum expectation system and vender are overlayfs covered partitions.
- 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.
"
if [ X"${1}" = X"--help" -o X"${1}" = X"-h" -o X"${1}" = X"-?" ]; then
echo "${USAGE}" >&2
exit 0
fi
##
## Helper Variables
##
@ -44,6 +44,7 @@ RED="${ESCAPE}[38;5;196m"
ORANGE="${ESCAPE}[38;5;255:165:0m"
BLUE="${ESCAPE}[35m"
NORMAL="${ESCAPE}[0m"
TMPDIR=${TMPDIR:-/tmp}
##
## Helper Functions
@ -293,13 +294,22 @@ fastboot_getvar() {
echo ${O} >&2
}
[ "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, reverses configurations" ]
cleanup () {
:
Returns: cleans up any latent resources" ]
cleanup() {
true
}
[ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr
@ -321,6 +331,7 @@ die() {
fi
echo "${RED}[ FAILED ]${NORMAL} ${@}" >&2
cleanup
restore
exit 1
}
@ -413,9 +424,48 @@ skip_unrelated_mounts() {
## MAINLINE
##
if [ X"-s" = X"${1}" -a -n "${2}" ]; then
export ANDROID_SERIAL="${2}"
shift 2
OPTIONS=`getopt --alternative --unquoted --longoptions help,serial:,colour,color,no-colour,no-color -- "?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
;;
--)
shift
break
;;
-*)
echo "${USAGE}" >&2
die "${0}: error unknown option ${1}"
;;
*)
break
;;
esac
shift
done
if ! ${color}; then
GREEN=""
RED=""
ORANGE=""
BLUE=""
NORMAL=""
fi
inFastboot && die "device in fastboot mode"
@ -451,15 +501,43 @@ BUILD_DESCRIPTION=`get_property ro.build.description`
[ -z "${BUILD_DESCRIPTION}" ] ||
echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
VERITY_WAS_ENABLED=false
# 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
VERITY_WAS_ENABLED=true
restore() {
${overlayfs_supported} || return 0
echo "${GREEN}[ INFO ]${NORMAL} restoring verity" >&2
inFastboot &&
fastboot reboot &&
adb_wait 2m
adb_root &&
adb enable-verity &&
adb_reboot &&
adb_wait 2m
}
fi
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 >/dev/null 2>/dev/null ||
adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null &&
@ -478,7 +556,7 @@ if ${overlayfs_supported}; then
echo "${ORANGE}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 &&
false
) ||
overlayfs_supported=false;
overlayfs_supported=false
;;
*)
echo "${GREEN}[ OK ]${NORMAL} overlay module uses callers creds" >&2
@ -550,8 +628,8 @@ 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##*using overlayfs}" ]; then
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
@ -583,8 +661,8 @@ if [ X"${D}" != X"${H}" ]; then
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
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
@ -615,7 +693,11 @@ fi
echo "${GREEN}[ RUN ]${NORMAL} remount" >&2
adb remount ||
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` &&
@ -665,10 +747,33 @@ if ${overlayfs_needed}; then
die "overlay takeover after remount"
!(adb_sh grep "^overlay " /proc/mounts </dev/null |
skip_unrelated_mounts |
grep " overlay ro,") &&
!(adb_sh grep " rw," /proc/mounts </dev/null |
skip_administrative_mounts data) ||
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 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"
@ -721,7 +826,7 @@ if ${overlayfs_needed}; then
adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null |
skip_administrative_mounts |
grep -v ' \(squashfs\|ext4\|f2fs\|vfat\) ' &&
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
@ -749,7 +854,10 @@ 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 -r ${tempdir}
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
@ -762,10 +870,14 @@ 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 &&
fastboot_wait 2m &&
fastboot flash vendor ||
adb reboot-fastboot ||
die "fastbootd not supported (wrong adb in path?)"
fastboot_wait 2m ||
die "reboot into fastboot to flash vendor `usb_status`"
fastboot flash vendor ||
( fastboot reboot && false) ||
die "fastboot flash vendor"
fastboot_getvar is-userspace yes &&
@ -804,7 +916,7 @@ else
die "can not reboot out of fastboot"
echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot"
adb_wait 2m ||
die "did not reboot after flash"
die "did not reboot after flash `usb_status`"
if ${overlayfs_needed}; then
adb_root &&
D=`adb_sh df -k </dev/null` &&
@ -847,7 +959,7 @@ T=`adb_date`
H=`adb remount 2>&1`
err=${?}
L=
D="${H%?Now reboot your device for settings to take effect}"
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`
@ -878,17 +990,18 @@ if [ -n "${scratch_partition}" ]; then
adb reboot-fastboot ||
die "Reboot into fastbootd"
img=${TMPDIR}/adb-remount-test-${$}.img
cleanup() {
rm /tmp/adb-remount-test.img
rm ${img}
}
dd if=/dev/zero of=/tmp/adb-remount-test.img bs=4096 count=16 2>/dev/null &&
dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
fastboot_wait 2m ||
die "reboot into fastboot"
fastboot flash --force ${scratch_partition} /tmp/adb-remount-test.img
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"
@ -900,14 +1013,32 @@ if [ -n "${scratch_partition}" ]; then
T=`adb_date`
D=`adb disable-verity 2>&1`
err=${?}
adb remount ||
die "remount failed"
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##*using overlayfs}" ] &&
[ 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
@ -924,12 +1055,12 @@ adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null ||
die "/vendor is not read-write"
echo "${GREEN}[ OK ]${NORMAL} mount -o rw,remount command works" >&2
if $VERITY_WAS_ENABLED && $overlayfs_supported; then
adb_root &&
adb enable-verity &&
adb_reboot &&
adb_wait 2m ||
die "failed to restore verity" >&2
fi
restore
err=${?}
restore() {
true
}
[ ${err} = 0 ] ||
die "failed to restore verity" >&2
echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2