1#! /bin/bash 2# 3# Divided into four section: 4# 5## USAGE 6## Helper Variables 7## Helper Functions 8## MAINLINE 9 10## 11## USAGE 12## 13 14USAGE="USAGE: `basename ${0}` [--help] [--serial <SerialNumber>] [options] 15 16adb remount tests 17 18-c --color Dress output with highlighting colors 19-h --help This help 20-D --no-wait-screen Do not wait for display screen to settle 21-t --print-time Report the test duration 22-s --serial Specify device (must if multiple are present)" 23if [ -n "`which timeout`" ]; then 24 USAGE="${USAGE} 25-a --wait-adb <duration> adb wait timeout 26-f --wait-fastboot <duration> fastboot wait timeout" 27fi 28USAGE="${USAGE} 29 30Conditions: 31 - Must be a userdebug build. 32 - Must be in adb mode. 33 - Also tests overlayfs 34 - Kernel must have overlayfs enabled and patched to support override_creds. 35 - Must have either erofs, squashfs, ext4-dedupe or full partitions. 36 - Minimum expectation system and vender are overlayfs covered partitions. 37" 38 39## 40## Helper Variables 41## 42 43EMPTY="" 44SPACE=" " 45# Line up wrap to [ XXXXXXX ] messages. 46INDENT=" " 47# A _real_ embedded tab character 48TAB="`echo | tr '\n' '\t'`" 49# A _real_ embedded escape character 50ESCAPE="`echo | tr '\n' '\033'`" 51# A _real_ embedded carriage return character 52CR="`echo | tr '\n' '\r'`" 53GREEN="${ESCAPE}[32m" 54RED="${ESCAPE}[31m" 55YELLOW="${ESCAPE}[33m" 56BLUE="${ESCAPE}[34m" 57NORMAL="${ESCAPE}[0m" 58TMPDIR=${TMPDIR:-/tmp} 59print_time=false 60start_time=`date +%s` 61ACTIVE_SLOT= 62 63ADB_WAIT=4m 64FASTBOOT_WAIT=2m 65screen_wait=true 66 67## 68## Helper Functions 69## 70 71[ "USAGE: inFastboot 72 73Returns: true if device is in fastboot mode" ] 74inFastboot() { 75 fastboot devices | 76 if [ -n "${ANDROID_SERIAL}" ]; then 77 grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null 78 else 79 wc -l | grep "^[${SPACE}${TAB}]*1\$" >/dev/null 80 fi 81} 82 83[ "USAGE: inAdb 84 85Returns: true if device is in adb mode" ] 86inAdb() { 87 adb devices | 88 grep -v -e 'List of devices attached' -e '^$' -e "[${SPACE}${TAB}]recovery\$" | 89 if [ -n "${ANDROID_SERIAL}" ]; then 90 grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null 91 else 92 wc -l | grep "^[${SPACE}${TAB}]*1\$" >/dev/null 93 fi 94} 95 96[ "USAGE: inRecovery 97 98Returns: true if device is in recovery mode" ] 99inRecovery() { 100 local list="`adb devices | 101 grep -v -e 'List of devices attached' -e '^$'`" 102 if [ -n "${ANDROID_SERIAL}" ]; then 103 echo "${list}" | 104 grep "^${ANDROID_SERIAL}[${SPACE}${TAB}][${SPACE}${TAB}]*recovery\$" >/dev/null 105 return ${?} 106 fi 107 if echo "${list}" | wc -l | grep "^[${SPACE}${TAB}]*1\$" >/dev/null; then 108 echo "${list}" | 109 grep "[${SPACE}${TAB}]recovery\$" >/dev/null 110 return ${?} 111 fi 112 false 113} 114 115[ "USAGE: adb_sh <commands> </dev/stdin >/dev/stdout 2>/dev/stderr 116 117Returns: true if the command succeeded" ] 118adb_sh() { 119 local args= 120 for i in "${@}"; do 121 [ -z "${args}" ] || args="${args} " 122 if [ X"${i}" != X"${i#\'}" ]; then 123 args="${args}${i}" 124 elif [ X"${i}" != X"${i#* }" ]; then 125 args="${args}'${i}'" 126 elif [ X"${i}" != X"${i#*${TAB}}" ]; then 127 args="${args}'${i}'" 128 else 129 args="${args}${i}" 130 fi 131 done 132 adb shell "${args}" 133} 134 135[ "USAGE: adb_date >/dev/stdout 136 137Returns: report device epoch time (suitable for logcat -t)" ] 138adb_date() { 139 adb_sh date +%s.%N </dev/null 140} 141 142[ "USAGE: adb_logcat [arguments] >/dev/stdout 143 144Returns: the logcat output" ] 145adb_logcat() { 146 echo "${RED}[ INFO ]${NORMAL} logcat ${@}" >&2 && 147 adb logcat "${@}" </dev/null | 148 tr -d '\r' | 149 grep -v 'logd : logdr: UID=' | 150 sed -e '${ /------- beginning of kernel/d }' -e 's/^[0-1][0-9]-[0-3][0-9] //' 151} 152 153[ "USAGE: avc_check >/dev/stderr 154 155Returns: worrisome avc violations" ] 156avc_check() { 157 if ! ${overlayfs_supported:-false}; then 158 return 159 fi 160 local L=`adb_logcat -b all -v brief -d \ 161 -e 'context=u:object_r:unlabeled:s0' 2>/dev/null | 162 sed -n 's/.*avc: //p' | 163 sort -u` 164 if [ -z "${L}" ]; then 165 return 166 fi 167 echo "${YELLOW}[ WARNING ]${NORMAL} unlabeled sepolicy violations:" >&2 168 echo "${L}" | sed "s/^/${INDENT}/" >&2 169} 170 171[ "USAGE: get_property <prop> 172 173Returns the property value" ] 174get_property() { 175 adb_sh getprop ${1} </dev/null 176} 177 178[ "USAGE: isDebuggable 179 180Returns: true if device is (likely) a debug build" ] 181isDebuggable() { 182 if inAdb && [ 1 != "`get_property ro.debuggable`" ]; then 183 false 184 fi 185} 186 187[ "USAGE: adb_su <commands> </dev/stdin >/dev/stdout 2>/dev/stderr 188 189Returns: true if the command running as root succeeded" ] 190adb_su() { 191 adb_sh su root "${@}" 192} 193 194[ "USAGE: adb_cat <file> >stdout 195 196Returns: content of file to stdout with carriage returns skipped, 197 true if the file exists" ] 198adb_cat() { 199 local OUTPUT="`adb_sh cat ${1} </dev/null 2>&1`" 200 local ret=${?} 201 echo "${OUTPUT}" | tr -d '\r' 202 return ${ret} 203} 204 205[ "USAGE: adb_ls <dirfile> >stdout 206 207Returns: filename or directoru content to stdout with carriage returns skipped, 208 true if the ls had no errors" ] 209adb_ls() { 210 local OUTPUT="`adb_sh ls ${1} </dev/null 2>/dev/null`" 211 local ret=${?} 212 echo "${OUTPUT}" | tr -d '\r' 213 return ${ret} 214} 215 216[ "USAGE: adb_test <expression> 217 218Returns: exit status of the test expression" ] 219adb_test() { 220 adb_sh test "${@}" </dev/null 221} 222 223[ "USAGE: adb_reboot 224 225Returns: true if the reboot command succeeded" ] 226adb_reboot() { 227 avc_check 228 adb reboot remount-test </dev/null || true 229 sleep 2 230} 231 232[ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d] 233 234human readable output whole seconds, whole minutes or mm:ss" ] 235format_duration() { 236 if [ -z "${1}" ]; then 237 echo unknown 238 return 239 fi 240 local duration="${1}" 241 if [ X"${duration}" != X"${duration%s}" ]; then 242 duration=${duration%s} 243 elif [ X"${duration}" != X"${duration%m}" ]; then 244 duration=`expr ${duration%m} \* 60` 245 elif [ X"${duration}" != X"${duration%h}" ]; then 246 duration=`expr ${duration%h} \* 3600` 247 elif [ X"${duration}" != X"${duration%d}" ]; then 248 duration=`expr ${duration%d} \* 86400` 249 fi 250 local seconds=`expr ${duration} % 60` 251 local minutes=`expr \( ${duration} / 60 \) % 60` 252 local hours=`expr ${duration} / 3600` 253 if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then 254 if [ 1 -eq ${duration} ]; then 255 echo 1 second 256 return 257 fi 258 echo ${duration} seconds 259 return 260 elif [ 60 -eq ${duration} ]; then 261 echo 1 minute 262 return 263 elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then 264 echo ${minutes} minutes 265 return 266 fi 267 if [ 0 -eq ${hours} ]; then 268 echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10` 269 return 270 fi 271 echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10` 272} 273 274[ "USAGE: USB_DEVICE=\`usb_devnum [--next]\` 275 276USB_DEVICE contains cache. Update if system changes. 277 278Returns: the devnum for the USB_SERIAL device" ] 279usb_devnum() { 280 if [ -n "${USB_SERIAL}" ]; then 281 local usb_device=`cat ${USB_SERIAL%/serial}/devnum 2>/dev/null | tr -d ' \t\r\n'` 282 if [ -n "${usb_device}" ]; then 283 USB_DEVICE=dev${usb_device} 284 elif [ -n "${USB_DEVICE}" -a "${1}" ]; then 285 USB_DEVICE=dev`expr ${USB_DEVICE#dev} + 1` 286 fi 287 echo "${USB_DEVICE}" 288 fi 289} 290 291[ "USAGE: adb_wait [timeout] 292 293Returns: waits until the device has returned for adb or optional timeout" ] 294adb_wait() { 295 local start=`date +%s` 296 local duration= 297 local ret 298 if [ -n "${1}" -a -n "`which timeout`" ]; then 299 USB_DEVICE=`usb_devnum --next` 300 duration=`format_duration ${1}` 301 echo -n ". . . waiting ${duration}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}" 302 timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null 303 ret=${?} 304 echo -n " ${CR}" 305 else 306 adb wait-for-device 307 ret=${?} 308 fi 309 USB_DEVICE=`usb_devnum` 310 if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then 311 local active_slot=`get_active_slot` 312 if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then 313 echo "${YELLOW}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2 314 fi 315 fi 316 local end=`date +%s` 317 local diff_time=`expr ${end} - ${start}` 318 local _print_time=${print_time} 319 if [ ${diff_time} -lt 15 ]; then 320 _print_time=false 321 fi 322 diff_time=`format_duration ${diff_time}` 323 if [ "${diff_time}" = "${duration}" ]; then 324 _print_time=false 325 fi 326 327 local reason= 328 if inAdb; then 329 reason=`get_property ro.boot.bootreason` 330 fi 331 case ${reason} in 332 reboot*) 333 reason= 334 ;; 335 ${EMPTY}) 336 ;; 337 *) 338 reason=" for boot reason ${reason}" 339 ;; 340 esac 341 if ${_print_time} || [ -n "${reason}" ]; then 342 echo "${BLUE}[ INFO ]${NORMAL} adb wait duration ${diff_time}${reason}" 343 fi >&2 344 345 return ${ret} 346} 347 348[ "USAGE: adb_user > /dev/stdout 349 350Returns: the adb daemon user" ] 351adb_user() { 352 adb_sh echo '${USER}' </dev/null 353} 354 355[ "USAGE: usb_status > stdout 2> stderr 356 357Assumes referenced right after adb_wait or fastboot_wait failued. 358If wait failed, check if device is in adb, recovery or fastboot mode 359and report status strings like \"(USB stack borken?)\", 360\"(In fastboot mode)\", \"(In recovery mode)\" or \"(in adb mode)\". 361Additional diagnostics may be provided to the stderr output. 362 363Returns: USB status string" ] 364usb_status() { 365 if inFastboot; then 366 echo "(In fastboot mode)" 367 elif inRecovery; then 368 echo "(In recovery mode)" 369 elif inAdb; then 370 echo "(In adb mode `adb_user`)" 371 else 372 echo "(USB stack borken for ${USB_ADDRESS})" 373 if [ -n "`which usb_devnum`" ]; then 374 USB_DEVICE=`usb_devnum` 375 if [ -n "`which lsusb`" ]; then 376 if [ -n "${USB_DEVICE}" ]; then 377 echo "# lsusb -v -s ${USB_DEVICE#dev}" 378 local D=`lsusb -v -s ${USB_DEVICE#dev} 2>&1` 379 if [ -n "${D}" ]; then 380 echo "${D}" 381 else 382 lsusb -v 383 fi 384 else 385 echo "# lsusb -v (expected device missing)" 386 lsusb -v 387 fi 388 fi 389 fi >&2 390 fi 391} 392 393[ "USAGE: fastboot_wait [timeout] 394 395Returns: waits until the device has returned for fastboot or optional timeout" ] 396fastboot_wait() { 397 local ret 398 # fastboot has no wait-for-device, but it does an automatic 399 # wait and requires (even a nonsensical) command to do so. 400 if [ -n "${1}" -a -n "`which timeout`" ]; then 401 USB_DEVICE=`usb_devnum --next` 402 echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}" 403 timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null 404 ret=${?} 405 echo -n " ${CR}" 406 ( exit ${ret} ) 407 else 408 fastboot wait-for-device >/dev/null 2>/dev/null 409 fi || 410 inFastboot 411 ret=${?} 412 USB_DEVICE=`usb_devnum` 413 if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then 414 local active_slot=`get_active_slot` 415 if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then 416 echo "${YELLOW}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" 417 fi >&2 418 fi 419 return ${ret} 420} 421 422[ "USAGE: recovery_wait [timeout] 423 424Returns: waits until the device has returned for recovery or optional timeout" ] 425recovery_wait() { 426 local ret 427 if [ -n "${1}" -a -n "`which timeout`" ]; then 428 USB_DEVICE=`usb_devnum --next` 429 echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}" 430 timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null 431 ret=${?} 432 echo -n " ${CR}" 433 else 434 adb wait-for-recovery 435 ret=${?} 436 fi 437 USB_DEVICE=`usb_devnum` 438 if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then 439 local active_slot=`get_active_slot` 440 if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then 441 echo "${YELLOW}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" 442 fi >&2 443 fi 444 return ${ret} 445} 446 447[ "any_wait [timeout] 448 449Returns: waits until a device has returned or optional timeout" ] 450any_wait() { 451 ( 452 adb_wait ${1} & 453 adb_pid=${!} 454 fastboot_wait ${1} & 455 fastboot_pid=${!} 456 recovery_wait ${1} & 457 recovery_pid=${!} 458 wait -n 459 kill "${adb_pid}" "${fastboot_pid}" "${recovery_pid}" 460 ) >/dev/null 2>/dev/null 461 inFastboot || inAdb || inRecovery 462} 463 464wait_for_screen_timeout=900 465[ "USAGE: wait_for_screen [-n] [TIMEOUT] 466 467-n - echo newline at exit 468TIMEOUT - default `format_duration ${wait_for_screen_timeout}`" ] 469wait_for_screen() { 470 if ! ${screen_wait}; then 471 adb_wait 472 return 473 fi 474 exit_function=true 475 if [ X"-n" = X"${1}" ]; then 476 exit_function=echo 477 shift 478 fi 479 timeout=${wait_for_screen_timeout} 480 if [ ${#} -gt 0 ]; then 481 timeout=${1} 482 shift 483 fi 484 counter=0 485 while true; do 486 if inFastboot; then 487 fastboot reboot 488 elif inAdb; then 489 if [ 0 != ${counter} ]; then 490 adb_wait 491 fi 492 if [ "1" = "`get_property sys.boot_completed`" ]; then 493 sleep 1 494 break 495 fi 496 fi 497 counter=`expr ${counter} + 1` 498 if [ ${counter} -gt ${timeout} ]; then 499 ${exit_function} 500 echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2 501 return 1 502 fi 503 sleep 1 504 done 505 ${exit_function} 506} 507 508[ "USAGE: adb_root 509 510NB: This can be flakey on devices due to USB state 511 512Returns: true if device in root state" ] 513adb_root() { 514 [ root != "`adb_user`" ] || return 0 515 adb root >/dev/null </dev/null 2>/dev/null 516 sleep 2 517 adb_wait ${ADB_WAIT} && 518 [ root = "`adb_user`" ] 519} 520 521[ "USAGE: adb_unroot 522 523NB: This can be flakey on devices due to USB state 524 525Returns: true if device in un root state" ] 526adb_unroot() { 527 [ root = "`adb_user`" ] || return 0 528 adb unroot >/dev/null </dev/null 2>/dev/null 529 sleep 2 530 adb_wait ${ADB_WAIT} && 531 [ root != "`adb_user`" ] 532} 533 534[ "USAGE: fastboot_getvar var expected >/dev/stderr 535 536Returns: true if var output matches expected" ] 537fastboot_getvar() { 538 local O=`fastboot getvar ${1} 2>&1` 539 local ret=${?} 540 O="${O#< waiting for * >?}" 541 O="${O%%?Finished. Total time: *}" 542 if [ 0 -ne ${ret} ]; then 543 echo ${O} >&2 544 false 545 return 546 fi 547 if [ "${O}" != "${O#*FAILED}" ]; then 548 O="${1}: <empty>" 549 fi 550 if [ -n "${2}" -a "${1}: ${2}" != "${O}" ]; then 551 echo "${2} != ${O}" 552 false 553 return 554 fi >&2 555 echo ${O} >&2 556} 557 558[ "USAGE: get_active_slot >/dev/stdout 559 560Returns: with a or b string reporting active slot" ] 561get_active_slot() { 562 if inAdb || inRecovery; then 563 get_property ro.boot.slot_suffix | tr -d _ 564 elif inFastboot; then 565 fastboot_getvar current-slot 2>&1 | sed -n 's/current-slot: //p' 566 else 567 false 568 fi 569} 570 571[ "USAGE: restore 572 573Do nothing: should be redefined when necessary. Called after cleanup. 574 575Returns: reverses configurations" ] 576restore() { 577 true 578} 579 580[ "USAGE: cleanup 581 582Do nothing: should be redefined when necessary 583 584Returns: cleans up any latent resources" ] 585cleanup() { 586 true 587} 588 589[ "USAGE: test_duration >/dev/stderr 590 591Prints the duration of the test 592 593Returns: reports duration" ] 594test_duration() { 595 if ${print_time}; then 596 echo "${BLUE}[ INFO ]${NORMAL} end `date`" 597 [ -n "${start_time}" ] || return 598 end_time=`date +%s` 599 local diff_time=`expr ${end_time} - ${start_time}` 600 echo "${BLUE}[ INFO ]${NORMAL} duration `format_duration ${diff_time}`" 601 fi >&2 602} 603 604[ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr 605 606If -d, or -t <epoch> argument is supplied, dump logcat. 607 608Returns: exit failure, report status" ] 609die() { 610 if [ X"-d" = X"${1}" ]; then 611 adb_logcat -b all -v nsec -d 612 shift 613 elif [ X"-t" = X"${1}" ]; then 614 if [ -n "${2}" ]; then 615 adb_logcat -b all -v nsec -t ${2} 616 else 617 adb_logcat -b all -v nsec -d 618 fi 619 shift 2 620 fi >&2 621 echo "${RED}[ FAILED ]${NORMAL} ${@}" >&2 622 cleanup 623 restore 624 test_duration 625 exit 1 626} 627 628[ "USAGE: EXPECT_EQ <lval> <rval> [--warning [message]] 629 630Returns true if (regex) lval matches rval" ] 631EXPECT_EQ() { 632 local lval="${1}" 633 local rval="${2}" 634 shift 2 635 local error=1 636 local prefix="${RED}[ ERROR ]${NORMAL}" 637 if [ X"${1}" = X"--warning" ]; then 638 prefix="${RED}[ WARNING ]${NORMAL}" 639 error=0 640 shift 1 641 fi 642 if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then 643 if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval% 644*}" ]; then 645 echo "${prefix} expected \"${lval}\"" 646 echo "${prefix} got \"${rval}\"" | 647 sed ": again 648 N 649 s/\(\n\)\([^ ]\)/\1${INDENT}\2/ 650 t again" 651 if [ -n "${*}" ] ; then 652 echo "${prefix} ${*}" 653 fi 654 else 655 echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}" 656 fi >&2 657 return ${error} 658 fi 659 if [ -n "${*}" ] ; then 660 prefix="${GREEN}[ INFO ]${NORMAL}" 661 if [ X"${lval}" != X"${rval}" ]; then # we were supplied a regex? 662 if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval% *}" ]; then 663 echo "${prefix} ok \"${lval}\"" 664 echo " = \"${rval}\"" | 665 sed ": again 666 N 667 s/\(\n\)\([^ ]\)/\1${INDENT}\2/ 668 t again" 669 if [ -n "${*}" ] ; then 670 echo "${prefix} ${*}" 671 fi 672 else 673 echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}" 674 fi 675 else 676 echo "${prefix} ok \"${lval}\" ${*}" 677 fi >&2 678 fi 679 return 0 680} 681 682[ "USAGE: EXPECT_NE <lval> <rval> [--warning [message]] 683 684Returns true if lval matches rval" ] 685EXPECT_NE() { 686 local lval="${1}" 687 local rval="${2}" 688 shift 2 689 local error=1 690 local prefix="${RED}[ ERROR ]${NORMAL}" 691 if [ X"${1}" = X"--warning" ]; then 692 prefix="${RED}[ WARNING ]${NORMAL}" 693 error=0 694 shift 1 695 fi 696 if [ X"${rval}" = X"${lval}" ]; then 697 echo "${prefix} did not expect \"${lval}\" ${*}" >&2 698 return ${error} 699 fi 700 if [ -n "${*}" ] ; then 701 echo "${prefix} ok \"${lval}\" not \"${rval}\" ${*}" >&2 702 fi 703 return 0 704} 705 706[ "USAGE: check_eq <lval> <rval> [--warning [message]] 707 708Exits if (regex) lval mismatches rval" ] 709check_eq() { 710 local lval="${1}" 711 local rval="${2}" 712 shift 2 713 if [ X"${1}" = X"--warning" ]; then 714 EXPECT_EQ "${lval}" "${rval}" ${*} 715 return 716 fi 717 if ! EXPECT_EQ "${lval}" "${rval}"; then 718 die "${@}" 719 fi 720} 721 722[ "USAGE: check_ne <lval> <rval> [--warning [message]] 723 724Exits if lval matches rval" ] 725check_ne() { 726 local lval="${1}" 727 local rval="${2}" 728 shift 2 729 if [ X"${1}" = X"--warning" ]; then 730 EXPECT_NE "${lval}" "${rval}" ${*} 731 return 732 fi 733 if ! EXPECT_NE "${lval}" "${rval}"; then 734 die "${@}" 735 fi 736} 737 738[ "USAGE: join_with <delimiter> <strings> 739 740Joins strings with delimiter" ] 741join_with() { 742 if [ "${#}" -lt 2 ]; then 743 echo 744 return 745 fi 746 local delimiter="${1}" 747 local result="${2}" 748 shift 2 749 for element in "${@}"; do 750 result+="${delimiter}${element}" 751 done 752 echo "${result}" 753} 754 755[ "USAGE: skip_administrative_mounts [data] < /proc/mounts 756 757Filters out all administrative (eg: sysfs) mounts uninteresting to the test" ] 758skip_administrative_mounts() { 759 local exclude_filesystems=( 760 "overlay" "tmpfs" "none" "sysfs" "proc" "selinuxfs" "debugfs" "bpf" 761 "binfmt_misc" "cg2_bpf" "pstore" "tracefs" "adb" "mtp" "ptp" "devpts" 762 "ramdumpfs" "binder" "securityfs" "functionfs" "rootfs" 763 ) 764 local exclude_devices=( 765 "\/sys\/kernel\/debug" "\/data\/media" "\/dev\/block\/loop[0-9]*" 766 "${exclude_filesystems[@]}" 767 ) 768 local exclude_mount_points=( 769 "\/cache" "\/mnt\/scratch" "\/mnt\/vendor\/persist" "\/persist" 770 "\/metadata" 771 ) 772 if [ "data" = "${1}" ]; then 773 exclude_mount_points+=("\/data") 774 fi 775 awk '$1 !~ /^('"$(join_with "|" "${exclude_devices[@]}")"')$/ && 776 $2 !~ /^('"$(join_with "|" "${exclude_mount_points[@]}")"')$/ && 777 $3 !~ /^('"$(join_with "|" "${exclude_filesystems[@]}")"')$/' 778} 779 780[ "USAGE: skip_unrelated_mounts < /proc/mounts 781 782or output from df 783 784Filters out all apex and vendor override administrative overlay mounts 785uninteresting to the test" ] 786skip_unrelated_mounts() { 787 grep -v "^overlay.* /\(apex\|bionic\|system\|vendor\)/[^ ]" | 788 grep -v "[%] /\(data_mirror\|apex\|bionic\|system\|vendor\)/[^ ][^ ]*$" 789} 790 791## 792## MAINLINE 793## 794 795HOSTOS=`uname` 796GETOPTS="--alternative --unquoted 797 --longoptions help,serial:,colour,color,no-colour,no-color 798 --longoptions wait-adb:,wait-fastboot: 799 --longoptions wait-screen,wait-display 800 --longoptions no-wait-screen,no-wait-display 801 --longoptions gtest_print_time,print-time 802 --" 803if [ "Darwin" = "${HOSTOS}" ]; then 804 GETOPTS= 805 USAGE="`echo \"${USAGE}\" | 806 sed 's/--color/ /g 807 1s/--help/-h/ 808 s/--help/ /g 809 s/--no-wait-screen/ /g 810 s/--print-time/ /g 811 1s/--serial/-s/ 812 s/--serial/ /g 813 s/--wait-adb/ /g 814 s/--wait-fastboot/ /g'`" 815fi 816OPTIONS=`getopt ${GETOPTS} "?a:cCdDf:hs:t" ${*}` || 817 ( echo "${USAGE}" >&2 ; false ) || 818 die "getopt failure" 819set -- ${OPTIONS} 820 821color=false 822while [ ${#} -gt 0 ]; do 823 case ${1} in 824 -h | --help | -\?) 825 echo "${USAGE}" >&2 826 exit 0 827 ;; 828 -s | --serial) 829 export ANDROID_SERIAL=${2} 830 shift 831 ;; 832 -c | --color | --colour) 833 color=true 834 ;; 835 -C | --no-color | --no-colour) 836 color=false 837 ;; 838 -D | --no-wait-display | --no-wait-screen) 839 screen_wait=false 840 ;; 841 -d | --wait-display | --wait-screen) 842 screen_wait=true 843 ;; 844 -t | --print-time | --gtest_print_time) 845 print_time=true 846 ;; 847 -a | --wait-adb) 848 ADB_WAIT=${2} 849 shift 850 ;; 851 -f | --wait-fastboot) 852 FASTBOOT_WAIT=${2} 853 shift 854 ;; 855 --) 856 shift 857 break 858 ;; 859 -*) 860 echo "${USAGE}" >&2 861 die "${0}: error unknown option ${1}" 862 ;; 863 *) 864 break 865 ;; 866 esac 867 shift 868done 869if ! ${color}; then 870 GREEN="" 871 RED="" 872 YELLOW="" 873 BLUE="" 874 NORMAL="" 875fi 876 877# Set an ERR trap handler to report any unhandled error 878trap 'die "line ${LINENO}: unhandled error"' ERR 879 880if ${print_time}; then 881 echo "${BLUE}[ INFO ]${NORMAL}" start `date` >&2 882fi 883 884inFastboot && die "device in fastboot mode" 885inRecovery && die "device in recovery mode" 886if ! inAdb; then 887 echo "${YELLOW}[ WARNING ]${NORMAL} device not in adb mode" >&2 888 adb_wait ${ADB_WAIT} 889fi 890inAdb || die "specified device not in adb mode" 891isDebuggable || die "device not a debug build" 892enforcing=true 893if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then 894 echo "${YELLOW}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2 895 enforcing=false 896fi 897 898# Do something. 899 900# Collect characteristics of the device and report. 901 902D=`get_property ro.serialno` 903[ -n "${D}" ] || D=`get_property ro.boot.serialno` 904[ -z "${D}" -o -n "${ANDROID_SERIAL}" ] || ANDROID_SERIAL=${D} 905USB_SERIAL= 906if [ -n "${ANDROID_SERIAL}" -a "Darwin" != "${HOSTOS}" ]; then 907 USB_SERIAL="`find /sys/devices -name serial | grep usb || true`" 908 if [ -n "${USB_SERIAL}" ]; then 909 USB_SERIAL=`echo "${USB_SERIAL}" | 910 xargs grep -l ${ANDROID_SERIAL} || true` 911 fi 912fi 913USB_ADDRESS= 914if [ -n "${USB_SERIAL}" ]; then 915 USB_ADDRESS=${USB_SERIAL%/serial} 916 USB_ADDRESS=usb${USB_ADDRESS##*/} 917fi 918[ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] || 919 USB_DEVICE=`usb_devnum` 920 echo "${BLUE}[ INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} >&2 921BUILD_DESCRIPTION=`get_property ro.build.description` 922[ -z "${BUILD_DESCRIPTION}" ] || 923 echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2 924KERNEL_VERSION="`adb_su cat /proc/version </dev/null 2>/dev/null`" 925[ -z "${KERNEL_VERSION}" ] || 926 echo "${BLUE}[ INFO ]${NORMAL} ${KERNEL_VERSION}" >&2 927ACTIVE_SLOT=`get_active_slot` 928[ -z "${ACTIVE_SLOT}" ] || 929 echo "${BLUE}[ INFO ]${NORMAL} active slot is ${ACTIVE_SLOT}" >&2 930 931# Acquire list of system partitions 932 933# KISS (assume system partition mount point is "/<partition name>") 934PARTITIONS=`adb_su cat /vendor/etc/fstab* </dev/null | 935 grep -v "^[#${SPACE}${TAB}]" | 936 skip_administrative_mounts | 937 awk '$1 ~ /^[^\/]+$/ && "/"$1 == $2 && $4 ~ /(^|,)ro(,|$)/ { print $1 }' | 938 sort -u | 939 tr '\n' ' '` 940PARTITIONS="${PARTITIONS:-system vendor}" 941# KISS (we do not support sub-mounts for system partitions currently) 942MOUNTS="`for i in ${PARTITIONS}; do 943 echo /${i} 944 done | 945 tr '\n' ' '`" 946echo "${BLUE}[ INFO ]${NORMAL} System Partitions list: ${PARTITIONS}" >&2 947 948# Report existing partition sizes 949adb_sh ls -l /dev/block/by-name/ /dev/block/mapper/ </dev/null 2>/dev/null | 950 sed -n 's@.* \([^ ]*\) -> /dev/block/\([^ ]*\)$@\1 \2@p' | 951 while read name device; do 952 [ super = ${name} -o cache = ${name} ] || 953 ( 954 for i in ${PARTITIONS}; do 955 [ ${i} = ${name} -o ${i} = ${name%_[ab]} ] && exit 956 done 957 exit 1 958 ) || 959 continue 960 961 case ${device} in 962 sd*) 963 device=${device%%[0-9]*}/${device} 964 ;; 965 esac 966 size=`adb_su cat /sys/block/${device}/size 2>/dev/null </dev/null` && 967 size=`expr ${size} / 2` && 968 echo "${BLUE}[ INFO ]${NORMAL} partition ${name} device ${device} size ${size}K" >&2 969 done 970 971# If reboot too soon after fresh flash, could trip device update failure logic 972if ${screen_wait}; then 973 echo "${YELLOW}[ WARNING ]${NORMAL} waiting for screen to come up. Consider --no-wait-screen option" >&2 974fi 975if ! wait_for_screen && ${screen_wait}; then 976 screen_wait=false 977 echo "${YELLOW}[ WARNING ]${NORMAL} not healthy, no launcher, skipping wait for screen" >&2 978fi 979 980# Can we test remount -R command? 981OVERLAYFS_BACKING="cache mnt/scratch" 982overlayfs_supported=true 983if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ 984 "2" != "`get_property partition.system.verified`" ]; then 985 restore() { 986 ${overlayfs_supported} || return 0 987 inFastboot && 988 fastboot reboot && 989 adb_wait ${ADB_WAIT} || 990 true 991 if inAdb; then 992 reboot=false 993 for d in ${OVERLAYFS_BACKING}; do 994 if adb_test -d /${d}/overlay; then 995 adb_su rm -rf /${d}/overlay </dev/null 996 reboot=true 997 fi 998 done 999 if ${reboot}; then 1000 adb_reboot && 1001 adb_wait ${ADB_WAIT} 1002 fi 1003 fi 1004 } 1005else 1006 restore() { 1007 ${overlayfs_supported} || return 0 1008 inFastboot && 1009 fastboot reboot && 1010 adb_wait ${ADB_WAIT} || 1011 true 1012 inAdb && 1013 adb_root && 1014 adb enable-verity >/dev/null 2>/dev/null && 1015 adb_reboot && 1016 adb_wait ${ADB_WAIT} 1017 } 1018 1019 echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2 1020 1021 avc_check 1022 T=`adb_date` 1023 adb_su remount -R system </dev/null 1024 err=${?} 1025 if [ "${err}" != 0 ]; then 1026 echo "${YELLOW}[ WARNING ]${NORMAL} adb shell su root remount -R system = ${err}, likely did not reboot!" >&2 1027 T="-t ${T}" 1028 else 1029 # Rebooted, logcat will be meaningless, and last logcat will likely be clear 1030 T="" 1031 fi 1032 sleep 2 1033 adb_wait ${ADB_WAIT} || 1034 die "waiting for device after adb shell su root remount -R system `usb_status`" 1035 if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ 1036 "2" = "`get_property partition.system.verified`" ]; then 1037 die ${T} "remount -R command failed 1038${INDENT}ro.boot.verifiedbootstate=\"`get_property ro.boot.verifiedbootstate`\" 1039${INDENT}partition.system.verified=\"`get_property partition.system.verified`\"" 1040 fi 1041 1042 echo "${GREEN}[ OK ]${NORMAL} adb shell su root remount -R command" >&2 1043fi 1044 1045echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2 1046 1047adb_wait || die "wait for device failed" 1048adb_root || 1049 die "initial setup" 1050 1051adb_test -d /sys/module/overlay || 1052 adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null && 1053 echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 || 1054 ( 1055 echo "${YELLOW}[ WARNING ]${NORMAL} overlay module not present" >&2 && 1056 false 1057 ) || 1058 overlayfs_supported=false 1059if ${overlayfs_supported}; then 1060 adb_test -f /sys/module/overlay/parameters/override_creds && 1061 echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 || 1062 case `adb_sh uname -r </dev/null` in 1063 4.[456789].* | 4.[1-9][0-9]* | [56789].*) 1064 echo "${YELLOW}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 && 1065 overlayfs_supported=false 1066 ;; 1067 *) 1068 echo "${GREEN}[ OK ]${NORMAL} overlay module uses caller's creds" >&2 1069 ;; 1070 esac 1071fi 1072 1073echo "${GREEN}[ RUN ]${NORMAL} Checking current overlayfs status" >&2 1074 1075# We can not universally use adb enable-verity to ensure device is 1076# in a overlayfs disabled state since it can prevent reboot on 1077# devices that remount the physical content rather than overlayfs. 1078# So lets do our best to surgically wipe the overlayfs state without 1079# having to go through enable-verity transition. 1080reboot=false 1081for d in ${OVERLAYFS_BACKING}; do 1082 if adb_test -d /${d}/overlay; then 1083 echo "${YELLOW}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2 1084 adb_sh rm -rf /${d}/overlay </dev/null || 1085 die "/${d}/overlay wipe" 1086 reboot=true 1087 fi 1088done 1089if ${reboot}; then 1090 echo "${YELLOW}[ WARNING ]${NORMAL} rebooting before test" >&2 1091 adb_reboot && 1092 adb_wait ${ADB_WAIT} || 1093 die "lost device after reboot after wipe `usb_status`" 1094 adb_root || 1095 die "lost device after elevation to root after wipe `usb_status`" 1096fi 1097D=`adb_sh df -k </dev/null` && 1098 H=`echo "${D}" | head -1` && 1099 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` && 1100 echo "${H}" && 1101 echo "${D}" && 1102 echo "${YELLOW}[ WARNING ]${NORMAL} overlays present before setup" >&2 || 1103 echo "${GREEN}[ OK ]${NORMAL} no overlay present before setup" >&2 1104overlayfs_needed=true 1105D=`adb_sh cat /proc/mounts </dev/null | 1106 skip_administrative_mounts data` 1107if echo "${D}" | grep /dev/root >/dev/null; then 1108 D=`echo / / 1109 echo "${D}" | grep -v /dev/root` 1110fi 1111D=`echo "${D}" | cut -s -d' ' -f1 | sort -u` 1112no_dedupe=true 1113for d in ${D}; do 1114 adb_sh tune2fs -l $d </dev/null 2>&1 | 1115 grep "Filesystem features:.*shared_blocks" >/dev/null && 1116 no_dedupe=false 1117done 1118D=`adb_sh df -k ${D} </dev/null | 1119 sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` 1120echo "${D}" 1121if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then 1122 overlayfs_needed=false 1123 # if device does not need overlays, then adb enable-verity will brick device 1124 restore() { 1125 ${overlayfs_supported} || return 0 1126 inFastboot && 1127 fastboot reboot && 1128 adb_wait ${ADB_WAIT} 1129 inAdb && 1130 adb_wait ${ADB_WAIT} 1131 } 1132elif ! ${overlayfs_supported}; then 1133 die "need overlayfs, but do not have it" 1134fi 1135 1136echo "${GREEN}[ RUN ]${NORMAL} disable verity" >&2 1137 1138T=`adb_date` 1139H=`adb disable-verity 2>&1` 1140err=${?} 1141L= 1142D="${H%?Now reboot your device for settings to take effect*}" 1143if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then 1144 echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 1145fi 1146if [ ${err} != 0 ]; then 1147 echo "${H}" 1148 ( [ -n "${L}" ] && echo "${L}" && false ) || 1149 die -t "${T}" "disable-verity" 1150fi 1151rebooted=false 1152if [ X"${D}" != X"${H}" ]; then 1153 echo "${H}" 1154 if [ X"${D}" != X"${D##*setup failed}" ]; then 1155 echo "${YELLOW}[ WARNING ]${NORMAL} overlayfs setup whined" >&2 1156 fi 1157 D=`adb_sh df -k </dev/null` && 1158 H=`echo "${D}" | head -1` && 1159 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` && 1160 [ -z "${D}" ] || 1161 ( echo "${H}" && echo "${D}" && false ) || 1162 die -t ${T} "overlay takeover unexpected at this phase" 1163 echo "${GREEN}[ INFO ]${NORMAL} rebooting as requested" >&2 1164 L=`adb_logcat -b all -v nsec -t ${T} 2>&1` 1165 adb_reboot && 1166 adb_wait ${ADB_WAIT} || 1167 die "lost device after reboot requested `usb_status`" 1168 adb_root || 1169 die "lost device after elevation to root `usb_status`" 1170 rebooted=true 1171 # re-disable verity to see the setup remarks expected 1172 T=`adb_date` 1173 H=`adb disable-verity 2>&1` 1174 err=${?} 1175 D="${H%?Now reboot your device for settings to take effect*}" 1176 if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then 1177 echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 1178 fi 1179 if [ ${err} != 0 ]; then 1180 T= 1181 fi 1182fi 1183if ${overlayfs_supported} && ${overlayfs_needed} && [ X"${D}" != X"${D##*setup failed}" ]; then 1184 echo "${D}" 1185 ( [ -n "${L}" ] && echo "${L}" && false ) || 1186 die -t "${T}" "setup for overlay" 1187fi 1188if [ X"${D}" != X"${D##*Successfully disabled verity}" ]; then 1189 echo "${H}" 1190 D=`adb_sh df -k </dev/null` && 1191 H=`echo "${D}" | head -1` && 1192 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` && 1193 [ -z "${D}" ] || 1194 ( echo "${H}" && echo "${D}" && false ) || 1195 ( [ -n "${L}" ] && echo "${L}" && false ) || 1196 die -t "${T}" "overlay takeover unexpected" 1197 [ -n "${L}" ] && echo "${L}" 1198 die -t "${T}" "unexpected report of verity being disabled a second time" 1199elif ${rebooted}; then 1200 echo "${GREEN}[ OK ]${NORMAL} verity already disabled" >&2 1201else 1202 echo "${YELLOW}[ WARNING ]${NORMAL} verity already disabled" >&2 1203fi 1204 1205echo "${GREEN}[ RUN ]${NORMAL} remount" >&2 1206 1207# Feed log with selinux denials as baseline before overlays 1208adb_unroot 1209adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null || true 1210adb_root 1211 1212D=`adb remount 2>&1` 1213ret=${?} 1214echo "${D}" 1215[ ${ret} != 0 ] || 1216 [ X"${D}" = X"${D##*remount failed}" ] || 1217 ( [ -n "${L}" ] && echo "${L}" && false ) || 1218 die -t "${T}" "adb remount failed" 1219D=`adb_sh df -k </dev/null` && 1220 H=`echo "${D}" | head -1` && 1221 D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` || 1222 ( [ -n "${L}" ] && echo "${L}" && false ) 1223ret=${?} 1224uses_dynamic_scratch=false 1225scratch_partition= 1226virtual_ab=`get_property ro.virtual_ab.enabled` 1227if ${overlayfs_needed}; then 1228 if [ ${ret} != 0 ]; then 1229 die -t ${T} "overlay takeover failed" 1230 fi 1231 echo "${D}" | grep "^overlay .* /system\$" >/dev/null || 1232 echo "${YELLOW}[ WARNING ]${NORMAL} overlay takeover not complete" >&2 1233 if [ -z "${virtual_ab}" ]; then 1234 scratch_partition=scratch 1235 fi 1236 if echo "${D}" | grep " /mnt/scratch" >/dev/null; then 1237 echo "${BLUE}[ INFO ]${NORMAL} using ${scratch_partition} dynamic partition for overrides" >&2 1238 fi 1239 M=`adb_sh cat /proc/mounts </dev/null | 1240 sed -n 's@\([^ ]*\) /mnt/scratch \([^ ]*\) .*@\2 on \1@p'` 1241 [ -n "${M}" ] && 1242 echo "${BLUE}[ INFO ]${NORMAL} scratch filesystem ${M}" 1243 uses_dynamic_scratch=true 1244 if [ "${M}" != "${M##*/dev/block/by-name/}" ]; then 1245 uses_dynamic_scratch=false 1246 scratch_partition="${M##*/dev/block/by-name/}" 1247 fi 1248 scratch_size=`adb_sh df -k /mnt/scratch </dev/null 2>/dev/null | 1249 while read device kblocks used available use mounted on; do 1250 if [ "/mnt/scratch" = "\${mounted}" ]; then 1251 echo \${kblocks} 1252 fi 1253 done` && 1254 [ -n "${scratch_size}" ] || 1255 die "scratch size" 1256 echo "${BLUE}[ INFO ]${NORMAL} scratch size ${scratch_size}KB" >&2 1257 for d in ${OVERLAYFS_BACKING}; do 1258 if adb_test -d /${d}/overlay/system/upper; then 1259 echo "${BLUE}[ INFO ]${NORMAL} /${d}/overlay is setup" >&2 1260 fi 1261 done 1262 1263 echo "${H}" && 1264 echo "${D}" && 1265 echo "${D}" | grep "^overlay .* /system\$" >/dev/null || 1266 die "overlay takeover after remount" 1267 !(adb_sh grep "^overlay " /proc/mounts </dev/null | 1268 skip_unrelated_mounts | 1269 grep " overlay ro,") || 1270 die "remount overlayfs missed a spot (ro)" 1271 !(adb_sh grep -v noatime /proc/mounts </dev/null | 1272 skip_administrative_mounts data | 1273 skip_unrelated_mounts | 1274 grep -v ' ro,') || 1275 die "mounts are not noatime" 1276 D=`adb_sh grep " rw," /proc/mounts </dev/null | 1277 skip_administrative_mounts data` 1278 if echo "${D}" | grep /dev/root >/dev/null; then 1279 D=`echo / / 1280 echo "${D}" | grep -v /dev/root` 1281 fi 1282 D=`echo "${D}" | cut -s -d' ' -f1 | sort -u` 1283 bad_rw=false 1284 for d in ${D}; do 1285 if adb_sh tune2fs -l $d </dev/null 2>&1 | 1286 grep "Filesystem features:.*shared_blocks" >/dev/null; then 1287 bad_rw=true 1288 else 1289 d=`adb_sh df -k ${D} </dev/null | 1290 sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` 1291 [ X"${d}" = X"${d##* 100[%] }" ] || 1292 bad_rw=true 1293 fi 1294 done 1295 [ -z "${D}" ] || 1296 D=`adb_sh df -k ${D} </dev/null | 1297 sed -e 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@' \ 1298 -e 's/^Filesystem /Filesystem (rw) /'` 1299 [ -z "${D}" ] || echo "${D}" 1300 ${bad_rw} && die "remount overlayfs missed a spot (rw)" 1301else 1302 if [ ${ret} = 0 ]; then 1303 die -t ${T} "unexpected overlay takeover" 1304 fi 1305fi 1306 1307# Check something. 1308 1309echo "${GREEN}[ RUN ]${NORMAL} push content to ${MOUNTS}" >&2 1310 1311A="Hello World! $(date)" 1312for i in ${MOUNTS}; do 1313 echo "${A}" | adb_sh cat - ">${i}/hello" 1314 B="`adb_cat ${i}/hello`" || 1315 die "${i#/} hello" 1316 check_eq "${A}" "${B}" ${i} before reboot 1317done 1318echo "${A}" | adb_sh cat - ">/system/priv-app/hello" 1319B="`adb_cat /system/priv-app/hello`" || 1320 die "system priv-app hello" 1321check_eq "${A}" "${B}" /system/priv-app before reboot 1322SYSTEM_DEVT=`adb_sh stat --format=%D /system/hello </dev/null` 1323VENDOR_DEVT=`adb_sh stat --format=%D /vendor/hello </dev/null` 1324SYSTEM_INO=`adb_sh stat --format=%i /system/hello </dev/null` 1325VENDOR_INO=`adb_sh stat --format=%i /vendor/hello </dev/null` 1326BASE_SYSTEM_DEVT=`adb_sh stat --format=%D /system/bin/stat </dev/null` 1327BASE_VENDOR_DEVT=`adb_sh stat --format=%D /vendor/bin/stat </dev/null` 1328check_eq "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" vendor and system devt 1329check_ne "${SYSTEM_INO}" "${VENDOR_INO}" vendor and system inode 1330if ${overlayfs_needed}; then 1331 check_ne "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt 1332 check_ne "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt 1333else 1334 check_eq "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt 1335 check_eq "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt 1336fi 1337check_ne "${BASE_SYSTEM_DEVT}" "${BASE_VENDOR_DEVT}" --warning system/vendor devt 1338[ -n "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] || 1339 echo "${YELLOW}[ WARNING ]${NORMAL} system devt ${SYSTEM_DEVT} major 0" >&2 1340[ -n "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] || 1341 echo "${YELLOW}[ WARNING ]${NORMAL} vendor devt ${VENDOR_DEVT} major 0" >&2 1342 1343# Download libc.so, append some garbage, push back, and check if the file 1344# is updated. 1345tempdir="`mktemp -d`" 1346cleanup() { 1347 rm -rf ${tempdir} 1348} 1349adb pull /system/lib/bootstrap/libc.so ${tempdir} >/dev/null || 1350 die "pull libc.so from device" 1351garbage="D105225BBFCB1EB8AB8EBDB7094646F0" 1352echo "${garbage}" >> ${tempdir}/libc.so 1353adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so >/dev/null || 1354 die "push libc.so to device" 1355adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || 1356 die "pull libc.so from device" 1357diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || 1358 die "libc.so differ" 1359 1360echo "${GREEN}[ RUN ]${NORMAL} reboot to confirm content persistent" >&2 1361 1362fixup_from_recovery() { 1363 inRecovery || return 1 1364 echo "${YELLOW}[ ERROR ]${NORMAL} Device in recovery" >&2 1365 adb reboot </dev/null 1366 adb_wait ${ADB_WAIT} 1367} 1368 1369adb_reboot && 1370 adb_wait ${ADB_WAIT} || 1371 fixup_from_recovery || 1372 die "reboot after override content added failed `usb_status`" 1373 1374if ${overlayfs_needed}; then 1375 D=`adb_su df -k </dev/null` && 1376 H=`echo "${D}" | head -1` && 1377 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` || 1378 ( echo "${L}" && false ) || 1379 die -d "overlay takeover failed after reboot" 1380 1381 adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null | 1382 skip_administrative_mounts | 1383 grep -v ' \(erofs\|squashfs\|ext4\|f2fs\|vfat\) ' && 1384 echo "${YELLOW}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 || 1385 echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2 1386fi 1387 1388if ${enforcing}; then 1389 adb_unroot || 1390 die "device not in unroot'd state" 1391 B="`adb_cat /vendor/hello 2>&1`" 1392 check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root 1393 echo "${GREEN}[ OK ]${NORMAL} /vendor content correct MAC after reboot" >&2 1394 # Feed unprivileged log with selinux denials as a result of overlays 1395 wait_for_screen 1396 adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null || true 1397fi 1398# If overlayfs has a nested security problem, this will fail. 1399B="`adb_ls /system/`" || 1400 die "adb ls /system" 1401[ X"${B}" != X"${B#*priv-app}" ] || 1402 die "adb ls /system/priv-app" 1403B="`adb_cat /system/priv-app/hello`" 1404check_eq "${A}" "${B}" /system/priv-app after reboot 1405# Only root can read vendor if sepolicy permissions are as expected. 1406adb_root || 1407 die "adb root" 1408for i in ${MOUNTS}; do 1409 B="`adb_cat ${i}/hello`" 1410 check_eq "${A}" "${B}" ${i#/} after reboot 1411 echo "${GREEN}[ OK ]${NORMAL} ${i} content remains after reboot" >&2 1412done 1413 1414check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot 1415check_eq "${VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/hello </dev/null`" vendor devt after reboot 1416check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot 1417check_eq "${VENDOR_INO}" "`adb_sh stat --format=%i /vendor/hello </dev/null`" vendor inode after reboot 1418check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" --warning base system devt after reboot 1419check_eq "${BASE_VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/bin/stat </dev/null`" --warning base vendor devt after reboot 1420check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" --warning devt for su after reboot 1421 1422# Feed log with selinux denials as a result of overlays 1423adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null || true 1424 1425# Check if the updated libc.so is persistent after reboot. 1426adb_root && 1427 adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || 1428 die "pull libc.so from device" 1429diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ" 1430rm -rf ${tempdir} 1431cleanup() { 1432 true 1433} 1434echo "${GREEN}[ OK ]${NORMAL} /system/lib/bootstrap/libc.so content remains after reboot" >&2 1435 1436echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears" >&2 1437 1438H=`adb_sh echo '${HOSTNAME}' </dev/null 2>/dev/null` 1439is_bootloader_fastboot=false 1440# cuttlefish? 1441[ X"${H}" != X"${H#vsoc}" ] || is_bootloader_fastboot=true 1442is_userspace_fastboot=false 1443 1444if ! ${is_bootloader_fastboot}; then 1445 echo "${YELLOW}[ WARNING ]${NORMAL} does not support fastboot, skipping" 1446elif [ -z "${ANDROID_PRODUCT_OUT}" ]; then 1447 echo "${YELLOW}[ WARNING ]${NORMAL} build tree not setup, skipping" 1448elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then 1449 echo "${YELLOW}[ WARNING ]${NORMAL} vendor image missing, skipping" 1450elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then 1451 echo "${YELLOW}[ WARNING ]${NORMAL} wrong vendor image, skipping" 1452elif [ -z "${ANDROID_HOST_OUT}" ]; then 1453 echo "${YELLOW}[ WARNING ]${NORMAL} please run lunch, skipping" 1454elif ! ( 1455 adb_cat /vendor/build.prop | 1456 cmp -s ${ANDROID_PRODUCT_OUT}/vendor/build.prop 1457 ) >/dev/null 2>/dev/null; then 1458 echo "${YELLOW}[ WARNING ]${NORMAL} vendor image signature mismatch, skipping" 1459else 1460 wait_for_screen 1461 avc_check 1462 adb reboot fastboot </dev/null || 1463 die "fastbootd not supported (wrong adb in path?)" 1464 any_wait ${ADB_WAIT} && 1465 inFastboot || 1466 die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)" 1467 fastboot flash vendor || 1468 ( fastboot reboot && false) || 1469 die "fastboot flash vendor" 1470 fastboot_getvar is-userspace yes && 1471 is_userspace_fastboot=true 1472 if [ -n "${scratch_paritition}" ]; then 1473 fastboot_getvar partition-type:${scratch_partition} raw || 1474 ( fastboot reboot && false) || 1475 die "fastboot can not see ${scratch_partition} parameters" 1476 if ${uses_dynamic_scratch}; then 1477 # check ${scratch_partition} via fastboot 1478 fastboot_getvar has-slot:${scratch_partition} no && 1479 fastboot_getvar is-logical:${scratch_partition} yes || 1480 ( fastboot reboot && false) || 1481 die "fastboot can not see ${scratch_partition} parameters" 1482 else 1483 fastboot_getvar is-logical:${scratch_partition} no || 1484 ( fastboot reboot && false) || 1485 die "fastboot can not see ${scratch_partition} parameters" 1486 fi 1487 if ! ${uses_dynamic_scratch}; then 1488 fastboot reboot-bootloader || 1489 die "Reboot into fastboot" 1490 fi 1491 if ${uses_dynamic_scratch}; then 1492 echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2 1493 fastboot erase ${scratch_partition} && 1494 ( fastboot reboot || true) && 1495 die "fastboot can erase ${scratch_partition}" 1496 fi 1497 echo "${BLUE}[ INFO ]${NORMAL} expect fastboot format ${scratch_partition} to fail" >&2 1498 fastboot format ${scratch_partition} && 1499 ( fastboot reboot || true) && 1500 die "fastboot can format ${scratch_partition}" 1501 fi 1502 fastboot reboot || 1503 die "can not reboot out of fastboot" 1504 echo "${YELLOW}[ WARNING ]${NORMAL} adb after fastboot" 1505 adb_wait ${ADB_WAIT} || 1506 fixup_from_recovery || 1507 die "did not reboot after formatting ${scratch_partition} `usb_status`" 1508 if ${overlayfs_needed}; then 1509 adb_root && 1510 D=`adb_sh df -k </dev/null` && 1511 H=`echo "${D}" | head -1` && 1512 D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` && 1513 echo "${H}" && 1514 echo "${D}" && 1515 echo "${D}" | grep "^overlay .* /system\$" >/dev/null || 1516 die "overlay /system takeover after flash vendor" 1517 echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null && 1518 if ${is_userspace_fastboot}; then 1519 die "overlay supposed to be minus /vendor takeover after flash vendor" 1520 else 1521 echo "${YELLOW}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 1522 echo "${YELLOW}[ WARNING ]${NORMAL} overlay supposed to be minus /vendor takeover after flash vendor" >&2 1523 fi 1524 fi 1525 B="`adb_cat /system/hello`" 1526 check_eq "${A}" "${B}" system after flash vendor 1527 B="`adb_ls /system/`" || 1528 die "adb ls /system" 1529 [ X"${B}" != X"${B#*priv-app}" ] || 1530 die "adb ls /system/priv-app" 1531 B="`adb_cat /system/priv-app/hello`" 1532 check_eq "${A}" "${B}" system/priv-app after flash vendor 1533 adb_root || 1534 die "adb root" 1535 B="`adb_cat /vendor/hello`" 1536 if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then 1537 check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ 1538 vendor content after flash vendor 1539 else 1540 echo "${YELLOW}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 1541 check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ 1542 --warning vendor content after flash vendor 1543 fi 1544 1545 check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot 1546 check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot 1547 check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" --warning base system devt after reboot 1548 check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" --warning devt for su after reboot 1549 1550fi 1551 1552wait_for_screen 1553echo "${GREEN}[ RUN ]${NORMAL} remove test content (cleanup)" >&2 1554 1555T=`adb_date` 1556H=`adb remount 2>&1` 1557err=${?} 1558L= 1559D="${H%?Now reboot your device for settings to take effect*}" 1560if [ X"${H}" != X"${D}" ]; then 1561 echo "${YELLOW}[ WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)" 1562 L=`adb_logcat -b all -v nsec -t ${T} 2>&1` 1563 adb_reboot && 1564 adb_wait ${ADB_WAIT} && 1565 adb_root || 1566 die "failed to reboot" 1567 T=`adb_date` 1568 H=`adb remount 2>&1` 1569 err=${?} 1570fi 1571echo "${H}" 1572[ ${err} = 0 ] && 1573 ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) && 1574 adb_sh rm /system/hello /system/priv-app/hello </dev/null || 1575 ( [ -n "${L}" ] && echo "${L}" && false ) || 1576 die -t ${T} "cleanup hello" 1577B="`adb_cat /system/hello`" 1578check_eq "cat: /system/hello: No such file or directory" "${B}" after rm 1579B="`adb_cat /system/priv-app/hello`" 1580check_eq "cat: /system/priv-app/hello: No such file or directory" "${B}" after rm 1581B="`adb_cat /vendor/hello`" 1582check_eq "cat: /vendor/hello: No such file or directory" "${B}" after rm 1583for i in ${MOUNTS}; do 1584 adb_sh rm ${i}/hello </dev/null 2>/dev/null || true 1585done 1586 1587if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then 1588 1589 echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition} recovery" >&2 1590 1591 avc_check 1592 adb reboot fastboot </dev/null || 1593 die "Reboot into fastbootd" 1594 img=${TMPDIR}/adb-remount-test-${$}.img 1595 cleanup() { 1596 rm ${img} 1597 } 1598 dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null && 1599 fastboot_wait ${FASTBOOT_WAIT} || 1600 die "reboot into fastboot to flash scratch `usb_status`" 1601 fastboot flash --force ${scratch_partition} ${img} 1602 err=${?} 1603 cleanup 1604 cleanup() { 1605 true 1606 } 1607 fastboot reboot || 1608 die "can not reboot out of fastboot" 1609 [ 0 -eq ${err} ] || 1610 die "fastboot flash ${scratch_partition}" 1611 adb_wait ${ADB_WAIT} && 1612 adb_root || 1613 die "did not reboot after flashing empty ${scratch_partition} `usb_status`" 1614 T=`adb_date` 1615 D=`adb disable-verity 2>&1` 1616 err=${?} 1617 if [ X"${D}" != "${D%?Now reboot your device for settings to take effect*}" ] 1618 then 1619 echo "${YELLOW}[ WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash" 1620 adb_reboot && 1621 adb_wait ${ADB_WAIT} && 1622 adb_root || 1623 die "failed to reboot" 1624 T=`adb_date` 1625 D="${D} 1626`adb disable-verity 2>&1`" 1627 err=${?} 1628 fi 1629 1630 echo "${D}" 1631 [ ${err} = 0 ] && 1632 [ X"${D}" = X"${D##*setup failed}" ] && 1633 [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] && 1634 echo "${GREEN}[ OK ]${NORMAL} ${scratch_partition} recreated" >&2 || 1635 die -t ${T} "setup for overlayfs" 1636 D=`adb remount 2>&1` 1637 err=${?} 1638 echo "${D}" 1639 [ ${err} != 0 ] || 1640 [ X"${D}" = X"${D##*remount failed}" ] || 1641 ( echo "${D}" && false ) || 1642 die -t ${T} "remount failed" 1643fi 1644 1645echo "${GREEN}[ RUN ]${NORMAL} test raw remount commands" >&2 1646 1647fixup_from_fastboot() { 1648 inFastboot || return 1 1649 if [ -n "${ACTIVE_SLOT}" ]; then 1650 local active_slot=`get_active_slot` 1651 if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then 1652 echo "${YELLOW}[ ERROR ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" 1653 else 1654 echo "${YELLOW}[ ERROR ]${NORMAL} Active slot to be set to ${ACTIVE_SLOT}" 1655 fi >&2 1656 fastboot --set-active=${ACTIVE_SLOT} 1657 fi 1658 fastboot reboot 1659 adb_wait ${ADB_WAIT} 1660} 1661 1662# Prerequisite is a prepped device from above. 1663adb_reboot && 1664 adb_wait ${ADB_WAIT} || 1665 fixup_from_fastboot || 1666 die "lost device after reboot to ro state `usb_status`" 1667adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && 1668 die "/vendor is not read-only" 1669adb_su mount -o rw,remount /vendor </dev/null || 1670 die "remount command" 1671adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || 1672 die "/vendor is not read-write" 1673echo "${GREEN}[ OK ]${NORMAL} mount -o rw,remount command works" >&2 1674 1675# Prerequisite is a prepped device from above. 1676adb_reboot && 1677 adb_wait ${ADB_WAIT} || 1678 fixup_from_fastboot || 1679 die "lost device after reboot to ro state `usb_status`" 1680adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && 1681 die "/vendor is not read-only" 1682adb_su remount vendor </dev/null || 1683 die "remount command" 1684adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || 1685 die "/vendor is not read-write" 1686adb_sh grep " /system .* rw," /proc/mounts >/dev/null </dev/null && 1687 die "/vendor is not read-only" 1688echo "${GREEN}[ OK ]${NORMAL} remount command works from setup" >&2 1689 1690# Prerequisite is an overlayfs deconstructed device but with verity disabled. 1691# This also saves a lot of 'noise' from the command doing a mkfs on backing 1692# storage and all the related tuning and adjustment. 1693for d in ${OVERLAYFS_BACKING}; do 1694 if adb_test -d /${d}/overlay; then 1695 adb_su rm -rf /${d}/overlay </dev/null || 1696 die "/${d}/overlay wipe" 1697 fi 1698done 1699adb_reboot && 1700 adb_wait ${ADB_WAIT} || 1701 fixup_from_fastboot || 1702 die "lost device after reboot after wipe `usb_status`" 1703adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && 1704 die "/vendor is not read-only" 1705adb_su remount vendor </dev/null || 1706 die "remount command" 1707adb_su df -k </dev/null | skip_unrelated_mounts 1708adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || 1709 die "/vendor is not read-write" 1710adb_sh grep " \(/system\|/\) .* rw," /proc/mounts >/dev/null </dev/null && 1711 die "/system is not read-only" 1712echo "${GREEN}[ OK ]${NORMAL} remount command works from scratch" >&2 1713 1714if ! restore; then 1715 restore() { 1716 true 1717 } 1718 die "failed to restore verity after remount from scratch test" 1719fi 1720 1721err=0 1722 1723if ${overlayfs_supported}; then 1724 echo "${GREEN}[ RUN ]${NORMAL} test 'adb remount -R'" >&2 1725 avc_check 1726 adb_root || 1727 die "adb root in preparation for adb remount -R" 1728 T=`adb_date` 1729 adb remount -R 1730 err=${?} 1731 if [ "${err}" != 0 ]; then 1732 die -t ${T} "adb remount -R = ${err}" 1733 fi 1734 sleep 2 1735 adb_wait ${ADB_WAIT} || 1736 die "waiting for device after adb remount -R `usb_status`" 1737 if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ 1738 "2" = "`get_property partition.system.verified`" ] && 1739 [ -n "`get_property ro.boot.verifiedbootstate`" -o \ 1740 -n "`get_property partition.system.verified`" ]; then 1741 die "remount -R command failed to disable verity 1742${INDENT}ro.boot.verifiedbootstate=\"`get_property ro.boot.verifiedbootstate`\" 1743${INDENT}partition.system.verified=\"`get_property partition.system.verified`\"" 1744 fi 1745 1746 echo "${GREEN}[ OK ]${NORMAL} 'adb remount -R' command" >&2 1747 1748 restore 1749 err=${?} 1750fi 1751 1752restore() { 1753 true 1754} 1755 1756[ ${err} = 0 ] || 1757 die "failed to restore verity" 1758 1759echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2 1760 1761test_duration 1762