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