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 [ "1" = "`get_property sys.boot_completed`" ]; then 478 sleep 1 479 break 480 fi 481 fi 482 counter=`expr ${counter} + 1` 483 if [ ${counter} -gt ${timeout} ]; then 484 ${exit_function} 485 echo "ERROR: wait_for_screen() timed out (`format_duration ${timeout}`)" >&2 486 return 1 487 fi 488 sleep 1 489 done 490 ${exit_function} 491} 492 493[ "USAGE: adb_root 494 495NB: This can be flakey on devices due to USB state 496 497Returns: true if device in root state" ] 498adb_root() { 499 [ root != "`adb_user`" ] || return 0 500 adb root >/dev/null </dev/null 2>/dev/null 501 sleep 2 502 adb_wait ${ADB_WAIT} && 503 [ root = "`adb_user`" ] 504} 505 506[ "USAGE: adb_unroot 507 508NB: This can be flakey on devices due to USB state 509 510Returns: true if device in un root state" ] 511adb_unroot() { 512 [ root = "`adb_user`" ] || return 0 513 adb unroot >/dev/null </dev/null 2>/dev/null 514 sleep 2 515 adb_wait ${ADB_WAIT} && 516 [ root != "`adb_user`" ] 517} 518 519[ "USAGE: fastboot_getvar var expected >/dev/stderr 520 521Returns: true if var output matches expected" ] 522fastboot_getvar() { 523 local O=`fastboot getvar ${1} 2>&1` 524 local ret=${?} 525 O="${O#< waiting for * >?}" 526 O="${O%%?Finished. Total time: *}" 527 if [ 0 -ne ${ret} ]; then 528 echo ${O} >&2 529 false 530 return 531 fi 532 if [ "${O}" != "${O#*FAILED}" ]; then 533 O="${1}: <empty>" 534 fi 535 if [ -n "${2}" -a "${1}: ${2}" != "${O}" ]; then 536 echo "${2} != ${O}" 537 false 538 return 539 fi >&2 540 echo ${O} >&2 541} 542 543[ "USAGE: get_active_slot >/dev/stdout 544 545Returns: with a or b string reporting active slot" ] 546get_active_slot() { 547 if inAdb || inRecovery; then 548 get_property ro.boot.slot_suffix | tr -d _ 549 elif inFastboot; then 550 fastboot_getvar current-slot 2>&1 | sed -n 's/current-slot: //p' 551 else 552 false 553 fi 554} 555 556[ "USAGE: restore 557 558Do nothing: should be redefined when necessary. Called after cleanup. 559 560Returns: reverses configurations" ] 561restore() { 562 true 563} 564 565[ "USAGE: cleanup 566 567Do nothing: should be redefined when necessary 568 569Returns: cleans up any latent resources" ] 570cleanup() { 571 true 572} 573 574[ "USAGE: test_duration >/dev/stderr 575 576Prints the duration of the test 577 578Returns: reports duration" ] 579test_duration() { 580 if ${print_time}; then 581 echo "${BLUE}[ INFO ]${NORMAL} end `date`" 582 [ -n "${start_time}" ] || return 583 end_time=`date +%s` 584 local diff_time=`expr ${end_time} - ${start_time}` 585 echo "${BLUE}[ INFO ]${NORMAL} duration `format_duration ${diff_time}`" 586 fi >&2 587} 588 589[ "USAGE: die [-d|-t <epoch>] [message] >/dev/stderr 590 591If -d, or -t <epoch> argument is supplied, dump logcat. 592 593Returns: exit failure, report status" ] 594die() { 595 if [ X"-d" = X"${1}" ]; then 596 adb_logcat -b all -v nsec -d 597 shift 598 elif [ X"-t" = X"${1}" ]; then 599 if [ -n "${2}" ]; then 600 adb_logcat -b all -v nsec -t ${2} 601 else 602 adb_logcat -b all -v nsec -d 603 fi 604 shift 2 605 fi >&2 606 echo "${RED}[ FAILED ]${NORMAL} ${@}" >&2 607 cleanup 608 restore 609 test_duration 610 exit 1 611} 612 613[ "USAGE: EXPECT_EQ <lval> <rval> [--warning [message]] 614 615Returns true if (regex) lval matches rval" ] 616EXPECT_EQ() { 617 local lval="${1}" 618 local rval="${2}" 619 shift 2 620 local error=1 621 local prefix="${RED}[ ERROR ]${NORMAL}" 622 if [ X"${1}" = X"--warning" ]; then 623 prefix="${RED}[ WARNING ]${NORMAL}" 624 error=0 625 shift 1 626 fi 627 if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then 628 if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval% 629*}" ]; then 630 echo "${prefix} expected \"${lval}\"" 631 echo "${prefix} got \"${rval}\"" | 632 sed ": again 633 N 634 s/\(\n\)\([^ ]\)/\1${INDENT}\2/ 635 t again" 636 if [ -n "${*}" ] ; then 637 echo "${prefix} ${*}" 638 fi 639 else 640 echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}" 641 fi >&2 642 return ${error} 643 fi 644 if [ -n "${*}" ] ; then 645 prefix="${GREEN}[ INFO ]${NORMAL}" 646 if [ X"${lval}" != X"${rval}" ]; then # we were supplied a regex? 647 if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval% *}" ]; then 648 echo "${prefix} ok \"${lval}\"" 649 echo " = \"${rval}\"" | 650 sed ": again 651 N 652 s/\(\n\)\([^ ]\)/\1${INDENT}\2/ 653 t again" 654 if [ -n "${*}" ] ; then 655 echo "${prefix} ${*}" 656 fi 657 else 658 echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}" 659 fi 660 else 661 echo "${prefix} ok \"${lval}\" ${*}" 662 fi >&2 663 fi 664 return 0 665} 666 667[ "USAGE: EXPECT_NE <lval> <rval> [--warning [message]] 668 669Returns true if lval matches rval" ] 670EXPECT_NE() { 671 local lval="${1}" 672 local rval="${2}" 673 shift 2 674 local error=1 675 local prefix="${RED}[ ERROR ]${NORMAL}" 676 if [ X"${1}" = X"--warning" ]; then 677 prefix="${RED}[ WARNING ]${NORMAL}" 678 error=0 679 shift 1 680 fi 681 if [ X"${rval}" = X"${lval}" ]; then 682 echo "${prefix} did not expect \"${lval}\" ${*}" >&2 683 return ${error} 684 fi 685 if [ -n "${*}" ] ; then 686 echo "${prefix} ok \"${lval}\" not \"${rval}\" ${*}" >&2 687 fi 688 return 0 689} 690 691[ "USAGE: check_eq <lval> <rval> [--warning [message]] 692 693Exits if (regex) lval mismatches rval" ] 694check_eq() { 695 local lval="${1}" 696 local rval="${2}" 697 shift 2 698 if [ X"${1}" = X"--warning" ]; then 699 EXPECT_EQ "${lval}" "${rval}" ${*} 700 return 701 fi 702 if ! EXPECT_EQ "${lval}" "${rval}"; then 703 die "${@}" 704 fi 705} 706 707[ "USAGE: check_ne <lval> <rval> [--warning [message]] 708 709Exits if lval matches rval" ] 710check_ne() { 711 local lval="${1}" 712 local rval="${2}" 713 shift 2 714 if [ X"${1}" = X"--warning" ]; then 715 EXPECT_NE "${lval}" "${rval}" ${*} 716 return 717 fi 718 if ! EXPECT_NE "${lval}" "${rval}"; then 719 die "${@}" 720 fi 721} 722 723[ "USAGE: skip_administrative_mounts [data] < /proc/mounts 724 725Filters out all administrative (eg: sysfs) mounts uninteresting to the test" ] 726skip_administrative_mounts() { 727 if [ "data" = "${1}" ]; then 728 grep -v " /data " 729 else 730 cat - 731 fi | 732 grep -v \ 733 -e "^\(overlay\|tmpfs\|none\|sysfs\|proc\|selinuxfs\|debugfs\|bpf\) " \ 734 -e "^\(binfmt_misc\|cg2_bpf\|pstore\|tracefs\|adb\|mtp\|ptp\|devpts\) " \ 735 -e " functionfs " \ 736 -e "^\(/data/media\|/dev/block/loop[0-9]*\) " \ 737 -e "^rootfs / rootfs rw," \ 738 -e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) " 739} 740 741[ "USAGE: skip_unrelated_mounts < /proc/mounts 742 743or output from df 744 745Filters out all apex and vendor override administrative overlay mounts 746uninteresting to the test" ] 747skip_unrelated_mounts() { 748 grep -v "^overlay.* /\(apex\|bionic\|system\|vendor\)/[^ ]" | 749 grep -v "[%] /\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$" 750} 751 752## 753## MAINLINE 754## 755 756OPTIONS=`getopt --alternative --unquoted \ 757 --longoptions help,serial:,colour,color,no-colour,no-color \ 758 --longoptions wait-adb:,wait-fastboot: \ 759 --longoptions wait-screen,wait-display \ 760 --longoptions no-wait-screen,no-wait-display \ 761 --longoptions gtest_print_time,print-time \ 762 -- "?hs:" ${*}` || 763 ( echo "${USAGE}" >&2 ; false ) || 764 die "getopt failure" 765set -- ${OPTIONS} 766 767color=false 768while [ ${#} -gt 0 ]; do 769 case ${1} in 770 -h | --help | -\?) 771 echo "${USAGE}" >&2 772 exit 0 773 ;; 774 -s | --serial) 775 export ANDROID_SERIAL=${2} 776 shift 777 ;; 778 --color | --colour) 779 color=true 780 ;; 781 --no-color | --no-colour) 782 color=false 783 ;; 784 --no-wait-display | --no-wait-screen) 785 screen_wait=false 786 ;; 787 --wait-display | --wait-screen) 788 screen_wait=true 789 ;; 790 --print-time | --gtest_print_time) 791 print_time=true 792 ;; 793 --wait-adb) 794 ADB_WAIT=${2} 795 shift 796 ;; 797 --wait-fastboot) 798 FASTBOOT_WAIT=${2} 799 shift 800 ;; 801 --) 802 shift 803 break 804 ;; 805 -*) 806 echo "${USAGE}" >&2 807 die "${0}: error unknown option ${1}" 808 ;; 809 *) 810 break 811 ;; 812 esac 813 shift 814done 815if ! ${color}; then 816 GREEN="" 817 RED="" 818 ORANGE="" 819 BLUE="" 820 NORMAL="" 821fi 822 823if ${print_time}; then 824 echo "${BLUE}[ INFO ]${NORMAL}" start `date` >&2 825fi 826 827inFastboot && die "device in fastboot mode" 828inRecovery && die "device in recovery mode" 829if ! inAdb; then 830 echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" >&2 831 adb_wait ${ADB_WAIT} 832fi 833inAdb || die "specified device not in adb mode" 834isDebuggable || die "device not a debug build" 835enforcing=true 836if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then 837 echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2 838 enforcing=false 839fi 840 841# Do something. 842 843# Collect characteristics of the device and report. 844 845D=`get_property ro.serialno` 846[ -n "${D}" ] || D=`get_property ro.boot.serialno` 847[ -z "${D}" -o -n "${ANDROID_SERIAL}" ] || ANDROID_SERIAL=${D} 848USB_SERIAL= 849[ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial | 850 grep usb | 851 xargs -r grep -l ${ANDROID_SERIAL}` 852USB_ADDRESS= 853if [ -n "${USB_SERIAL}" ]; then 854 USB_ADDRESS=${USB_SERIAL%/serial} 855 USB_ADDRESS=usb${USB_ADDRESS##*/} 856fi 857[ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] || 858 USB_DEVICE=`usb_devnum` 859 echo "${BLUE}[ INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} >&2 860BUILD_DESCRIPTION=`get_property ro.build.description` 861[ -z "${BUILD_DESCRIPTION}" ] || 862 echo "${BLUE}[ INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2 863ACTIVE_SLOT=`get_active_slot` 864[ -z "${ACTIVE_SLOT}" ] || 865 echo "${BLUE}[ INFO ]${NORMAL} active slot is ${ACTIVE_SLOT}" >&2 866 867# Acquire list of system partitions 868 869PARTITIONS=`adb_su cat /vendor/etc/fstab* | 870 skip_administrative_mounts | 871 sed -n "s@^\([^ ${TAB}/][^ ${TAB}/]*\)[ ${TAB}].*[, ${TAB}]ro[, ${TAB}].*@\1@p" | 872 sort -u | 873 tr '\n' ' '` 874PARTITIONS="${PARTITIONS:-system vendor}" 875# KISS (we do not support sub-mounts for system partitions currently) 876MOUNTS="`for i in ${PARTITIONS}; do 877 echo /${i} 878 done | 879 tr '\n' ' '`" 880echo "${BLUE}[ INFO ]${NORMAL} System Partitions list: ${PARTITIONS}" >&2 881 882# Report existing partition sizes 883adb_sh ls -l /dev/block/by-name/ /dev/block/mapper/ </dev/null 2>/dev/null | 884 sed -n 's@.* \([^ ]*\) -> /dev/block/\([^ ]*\)$@\1 \2@p' | 885 while read name device; do 886 [ super = ${name} -o cache = ${name} ] || 887 ( 888 for i in ${PARTITIONS}; do 889 [ ${i} = ${name} -o ${i} = ${name%_[ab]} ] && exit 890 done 891 exit 1 892 ) || 893 continue 894 895 case ${device} in 896 sd*) 897 device=${device%%[0-9]*}/${device} 898 ;; 899 esac 900 size=`adb_su cat /sys/block/${device}/size 2>/dev/null </dev/null` && 901 size=`expr ${size} / 2` && 902 echo "${BLUE}[ INFO ]${NORMAL} partition ${name} device ${device} size ${size}K" >&2 903 done 904 905# If reboot too soon after fresh flash, could trip device update failure logic 906if ! wait_for_screen && ${screen_wait}; then 907 screen_wait=false 908 echo "${ORANGE}[ WARNING ]${NORMAL} not healthy, no launcher, skipping wait for screen" >&2 909fi 910 911# Can we test remount -R command? 912OVERLAYFS_BACKING="cache mnt/scratch" 913overlayfs_supported=true 914if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ 915 "2" != "`get_property partition.system.verified`" ]; then 916 restore() { 917 ${overlayfs_supported} || return 0 918 inFastboot && 919 fastboot reboot && 920 adb_wait ${ADB_WAIT} || 921 true 922 if inAdb; then 923 reboot=false 924 for d in ${OVERLAYFS_BACKING}; do 925 if adb_su ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then 926 adb_su rm -rf /${d}/overlay </dev/null 927 reboot=true 928 fi 929 done 930 if ${reboot}; then 931 adb_reboot && 932 adb_wait ${ADB_WAIT} 933 fi 934 fi 935 } 936else 937 restore() { 938 ${overlayfs_supported} || return 0 939 inFastboot && 940 fastboot reboot && 941 adb_wait ${ADB_WAIT} || 942 true 943 inAdb && 944 adb_root && 945 adb enable-verity >/dev/null 2>/dev/null && 946 adb_reboot && 947 adb_wait ${ADB_WAIT} 948 } 949 950 echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2 951 952 avc_check 953 T=`adb_date` 954 adb_su remount -R system </dev/null 955 err=${?} 956 if [ "${err}" != 0 ]; then 957 echo "${ORANGE}[ WARNING ]${NORMAL} adb shell su root remount -R system = ${err}, likely did not reboot!" >&2 958 T="-t ${T}" 959 else 960 # Rebooted, logcat will be meaningless, and last logcat will likely be clear 961 T="" 962 fi 963 sleep 2 964 adb_wait ${ADB_WAIT} || 965 die "waiting for device after adb shell su root remount -R system `usb_status`" 966 if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ 967 "2" = "`get_property partition.system.verified`" ]; then 968 die ${T} "remount -R command failed 969${INDENT}ro.boot.verifiedbootstate=\"`get_property ro.boot.verifiedbootstate`\" 970${INDENT}partition.system.verified=\"`get_property partition.system.verified`\"" 971 fi 972 973 echo "${GREEN}[ OK ]${NORMAL} adb shell su root remount -R command" >&2 974fi 975 976echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2 977 978adb_wait || die "wait for device failed" 979adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null || 980 adb_sh grep "nodev${TAB}overlay" /proc/filesystems </dev/null >/dev/null 2>/dev/null && 981 echo "${GREEN}[ OK ]${NORMAL} overlay module present" >&2 || 982 ( 983 echo "${ORANGE}[ WARNING ]${NORMAL} overlay module not present" >&2 && 984 false 985 ) || 986 overlayfs_supported=false 987if ${overlayfs_supported}; then 988 adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null 2>/dev/null && 989 echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 || 990 case `adb_sh uname -r </dev/null` in 991 4.[456789].* | 4.[1-9][0-9]* | [56789].*) 992 echo "${ORANGE}[ WARNING ]${NORMAL} overlay module does not support override_creds" >&2 && 993 overlayfs_supported=false 994 ;; 995 *) 996 echo "${GREEN}[ OK ]${NORMAL} overlay module uses caller's creds" >&2 997 ;; 998 esac 999fi 1000 1001adb_root || 1002 die "initial setup" 1003 1004echo "${GREEN}[ RUN ]${NORMAL} Checking current overlayfs status" >&2 1005 1006# We can not universally use adb enable-verity to ensure device is 1007# in a overlayfs disabled state since it can prevent reboot on 1008# devices that remount the physical content rather than overlayfs. 1009# So lets do our best to surgically wipe the overlayfs state without 1010# having to go through enable-verity transition. 1011reboot=false 1012for d in ${OVERLAYFS_BACKING}; do 1013 if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then 1014 echo "${ORANGE}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2 1015 adb_sh rm -rf /${d}/overlay </dev/null || 1016 die "/${d}/overlay wipe" 1017 reboot=true 1018 fi 1019done 1020if ${reboot}; then 1021 echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2 1022 adb_reboot && 1023 adb_wait ${ADB_WAIT} || 1024 die "lost device after reboot after wipe `usb_status`" 1025 adb_root || 1026 die "lost device after elevation to root after wipe `usb_status`" 1027fi 1028D=`adb_sh df -k </dev/null` && 1029 H=`echo "${D}" | head -1` && 1030 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` && 1031 echo "${H}" && 1032 echo "${D}" && 1033 echo "${ORANGE}[ WARNING ]${NORMAL} overlays present before setup" >&2 || 1034 echo "${GREEN}[ OK ]${NORMAL} no overlay present before setup" >&2 1035overlayfs_needed=true 1036D=`adb_sh cat /proc/mounts </dev/null | 1037 skip_administrative_mounts data` 1038if echo "${D}" | grep /dev/root >/dev/null; then 1039 D=`echo / / 1040 echo "${D}" | grep -v /dev/root` 1041fi 1042D=`echo "${D}" | cut -s -d' ' -f1 | sort -u` 1043no_dedupe=true 1044for d in ${D}; do 1045 adb_sh tune2fs -l $d </dev/null 2>&1 | 1046 grep "Filesystem features:.*shared_blocks" >/dev/null && 1047 no_dedupe=false 1048done 1049D=`adb_sh df -k ${D} </dev/null | 1050 sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` 1051echo "${D}" 1052if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then 1053 overlayfs_needed=false 1054 # if device does not need overlays, then adb enable-verity will brick device 1055 restore() { 1056 ${overlayfs_supported} || return 0 1057 inFastboot && 1058 fastboot reboot && 1059 adb_wait ${ADB_WAIT} 1060 inAdb && 1061 adb_wait ${ADB_WAIT} 1062 } 1063elif ! ${overlayfs_supported}; then 1064 die "need overlayfs, but do not have it" 1065fi 1066 1067echo "${GREEN}[ RUN ]${NORMAL} disable verity" >&2 1068 1069T=`adb_date` 1070H=`adb disable-verity 2>&1` 1071err=${?} 1072L= 1073D="${H%?Now reboot your device for settings to take effect*}" 1074if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then 1075 echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 1076fi 1077if [ ${err} != 0 ]; then 1078 echo "${H}" 1079 ( [ -n "${L}" ] && echo "${L}" && false ) || 1080 die -t "${T}" "disable-verity" 1081fi 1082rebooted=false 1083if [ X"${D}" != X"${H}" ]; then 1084 echo "${H}" 1085 if [ X"${D}" != X"${D##*setup failed}" ]; then 1086 echo "${ORANGE}[ WARNING ]${NORMAL} overlayfs setup whined" >&2 1087 fi 1088 D=`adb_sh df -k </dev/null` && 1089 H=`echo "${D}" | head -1` && 1090 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` && 1091 [ -z "${D}" ] || 1092 ( echo "${H}" && echo "${D}" && false ) || 1093 die -t ${T} "overlay takeover unexpected at this phase" 1094 echo "${GREEN}[ INFO ]${NORMAL} rebooting as requested" >&2 1095 L=`adb_logcat -b all -v nsec -t ${T} 2>&1` 1096 adb_reboot && 1097 adb_wait ${ADB_WAIT} || 1098 die "lost device after reboot requested `usb_status`" 1099 adb_root || 1100 die "lost device after elevation to root `usb_status`" 1101 rebooted=true 1102 # re-disable verity to see the setup remarks expected 1103 T=`adb_date` 1104 H=`adb disable-verity 2>&1` 1105 err=${?} 1106 D="${H%?Now reboot your device for settings to take effect*}" 1107 if [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ]; then 1108 echo "${GREEN}[ OK ]${NORMAL} using overlayfs" >&2 1109 fi 1110 if [ ${err} != 0 ]; then 1111 T= 1112 fi 1113fi 1114if ${overlayfs_supported} && ${overlayfs_needed} && [ X"${D}" != X"${D##*setup failed}" ]; then 1115 echo "${D}" 1116 ( [ -n "${L}" ] && echo "${L}" && false ) || 1117 die -t "${T}" "setup for overlay" 1118fi 1119if [ X"${D}" != X"${D##*Successfully disabled verity}" ]; then 1120 echo "${H}" 1121 D=`adb_sh df -k </dev/null` && 1122 H=`echo "${D}" | head -1` && 1123 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay " || true` && 1124 [ -z "${D}" ] || 1125 ( echo "${H}" && echo "${D}" && false ) || 1126 ( [ -n "${L}" ] && echo "${L}" && false ) || 1127 die -t "${T}" "overlay takeover unexpected" 1128 [ -n "${L}" ] && echo "${L}" 1129 die -t "${T}" "unexpected report of verity being disabled a second time" 1130elif ${rebooted}; then 1131 echo "${GREEN}[ OK ]${NORMAL} verity already disabled" >&2 1132else 1133 echo "${ORANGE}[ WARNING ]${NORMAL} verity already disabled" >&2 1134fi 1135 1136echo "${GREEN}[ RUN ]${NORMAL} remount" >&2 1137 1138# Feed log with selinux denials as baseline before overlays 1139adb_unroot 1140adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null 1141adb_root 1142 1143D=`adb remount 2>&1` 1144ret=${?} 1145echo "${D}" 1146[ ${ret} != 0 ] || 1147 [ X"${D}" = X"${D##*remount failed}" ] || 1148 ( [ -n "${L}" ] && echo "${L}" && false ) || 1149 die -t "${T}" "adb remount failed" 1150D=`adb_sh df -k </dev/null` && 1151 H=`echo "${D}" | head -1` && 1152 D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` || 1153 ( [ -n "${L}" ] && echo "${L}" && false ) 1154ret=${?} 1155uses_dynamic_scratch=false 1156scratch_partition= 1157virtual_ab=`get_property ro.virtual_ab.enabled` 1158if ${overlayfs_needed}; then 1159 if [ ${ret} != 0 ]; then 1160 die -t ${T} "overlay takeover failed" 1161 fi 1162 echo "${D}" | grep "^overlay .* /system\$" >/dev/null || 1163 echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover not complete" >&2 1164 if [ -z "${virtual_ab}" ]; then 1165 scratch_partition=scratch 1166 fi 1167 if echo "${D}" | grep " /mnt/scratch" >/dev/null; then 1168 echo "${BLUE}[ INFO ]${NORMAL} using ${scratch_partition} dynamic partition for overrides" >&2 1169 fi 1170 M=`adb_sh cat /proc/mounts </dev/null | 1171 sed -n 's@\([^ ]*\) /mnt/scratch \([^ ]*\) .*@\2 on \1@p'` 1172 [ -n "${M}" ] && 1173 echo "${BLUE}[ INFO ]${NORMAL} scratch filesystem ${M}" 1174 uses_dynamic_scratch=true 1175 if [ "${M}" != "${M##*/dev/block/by-name/}" ]; then 1176 uses_dynamic_scratch=false 1177 scratch_partition="${M##*/dev/block/by-name/}" 1178 fi 1179 scratch_size=`adb_sh df -k /mnt/scratch </dev/null 2>/dev/null | 1180 while read device kblocks used available use mounted on; do 1181 if [ "/mnt/scratch" = "\${mounted}" ]; then 1182 echo \${kblocks} 1183 fi 1184 done` && 1185 [ -n "${scratch_size}" ] || 1186 die "scratch size" 1187 echo "${BLUE}[ INFO ]${NORMAL} scratch size ${scratch_size}KB" >&2 1188 for d in ${OVERLAYFS_BACKING}; do 1189 if adb_sh ls -d /${d}/overlay/system/upper </dev/null >/dev/null 2>/dev/null; then 1190 echo "${BLUE}[ INFO ]${NORMAL} /${d}/overlay is setup" >&2 1191 fi 1192 done 1193 1194 echo "${H}" && 1195 echo "${D}" && 1196 echo "${D}" | grep "^overlay .* /system\$" >/dev/null || 1197 die "overlay takeover after remount" 1198 !(adb_sh grep "^overlay " /proc/mounts </dev/null | 1199 skip_unrelated_mounts | 1200 grep " overlay ro,") || 1201 die "remount overlayfs missed a spot (ro)" 1202 !(adb_sh grep -v noatime /proc/mounts </dev/null | 1203 skip_administrative_mounts data | 1204 skip_unrelated_mounts | 1205 grep -v ' ro,') || 1206 die "mounts are not noatime" 1207 D=`adb_sh grep " rw," /proc/mounts </dev/null | 1208 skip_administrative_mounts data` 1209 if echo "${D}" | grep /dev/root >/dev/null; then 1210 D=`echo / / 1211 echo "${D}" | grep -v /dev/root` 1212 fi 1213 D=`echo "${D}" | cut -s -d' ' -f1 | sort -u` 1214 bad_rw=false 1215 for d in ${D}; do 1216 if adb_sh tune2fs -l $d </dev/null 2>&1 | 1217 grep "Filesystem features:.*shared_blocks" >/dev/null; then 1218 bad_rw=true 1219 else 1220 d=`adb_sh df -k ${D} </dev/null | 1221 sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'` 1222 [ X"${d}" = X"${d##* 100[%] }" ] || 1223 bad_rw=true 1224 fi 1225 done 1226 [ -z "${D}" ] || 1227 D=`adb_sh df -k ${D} </dev/null | 1228 sed -e 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@' \ 1229 -e 's/^Filesystem /Filesystem (rw) /'` 1230 [ -z "${D}" ] || echo "${D}" 1231 ${bad_rw} && die "remount overlayfs missed a spot (rw)" 1232else 1233 if [ ${ret} = 0 ]; then 1234 die -t ${T} "unexpected overlay takeover" 1235 fi 1236fi 1237 1238# Check something. 1239 1240echo "${GREEN}[ RUN ]${NORMAL} push content to ${MOUNTS}" >&2 1241 1242A="Hello World! $(date)" 1243for i in ${MOUNTS}; do 1244 echo "${A}" | adb_sh cat - ">${i}/hello" 1245 B="`adb_cat ${i}/hello`" || 1246 die "${i#/} hello" 1247 check_eq "${A}" "${B}" ${i} before reboot 1248done 1249echo "${A}" | adb_sh cat - ">/system/priv-app/hello" 1250B="`adb_cat /system/priv-app/hello`" || 1251 die "system priv-app hello" 1252check_eq "${A}" "${B}" /system/priv-app before reboot 1253SYSTEM_DEVT=`adb_sh stat --format=%D /system/hello </dev/null` 1254VENDOR_DEVT=`adb_sh stat --format=%D /vendor/hello </dev/null` 1255SYSTEM_INO=`adb_sh stat --format=%i /system/hello </dev/null` 1256VENDOR_INO=`adb_sh stat --format=%i /vendor/hello </dev/null` 1257BASE_SYSTEM_DEVT=`adb_sh stat --format=%D /system/bin/stat </dev/null` 1258BASE_VENDOR_DEVT=`adb_sh stat --format=%D /vendor/bin/stat </dev/null` 1259check_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 1260check_ne "${SYSTEM_INO}" "${VENDOR_INO}" vendor and system inode 1261if ${overlayfs_needed}; then 1262 check_ne "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt 1263 check_ne "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt 1264else 1265 check_eq "${SYSTEM_DEVT}" "${BASE_SYSTEM_DEVT}" system devt 1266 check_eq "${VENDOR_DEVT}" "${BASE_VENDOR_DEVT}" vendor devt 1267fi 1268check_ne "${BASE_SYSTEM_DEVT}" "${BASE_VENDOR_DEVT}" --warning system/vendor devt 1269[ -n "${SYSTEM_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] || 1270 die "system devt ${SYSTEM_DEVT} is major 0" 1271[ -n "${VENDOR_DEVT%[0-9a-fA-F][0-9a-fA-F]}" ] || 1272 die "vendor devt ${SYSTEM_DEVT} is major 0" 1273 1274# Download libc.so, append some gargage, push back, and check if the file 1275# is updated. 1276tempdir="`mktemp -d`" 1277cleanup() { 1278 rm -rf ${tempdir} 1279} 1280adb pull /system/lib/bootstrap/libc.so ${tempdir} >/dev/null || 1281 die "pull libc.so from device" 1282garbage="`hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random`" 1283echo ${garbage} >> ${tempdir}/libc.so 1284adb push ${tempdir}/libc.so /system/lib/bootstrap/libc.so >/dev/null || 1285 die "push libc.so to device" 1286adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || 1287 die "pull libc.so from device" 1288diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || 1289 die "libc.so differ" 1290 1291echo "${GREEN}[ RUN ]${NORMAL} reboot to confirm content persistent" >&2 1292 1293fixup_from_recovery() { 1294 inRecovery || return 1 1295 echo "${ORANGE}[ ERROR ]${NORMAL} Device in recovery" >&2 1296 adb reboot </dev/null 1297 adb_wait ${ADB_WAIT} 1298} 1299 1300adb_reboot && 1301 adb_wait ${ADB_WAIT} || 1302 fixup_from_recovery || 1303 die "reboot after override content added failed `usb_status`" 1304 1305if ${overlayfs_needed}; then 1306 D=`adb_su df -k </dev/null` && 1307 H=`echo "${D}" | head -1` && 1308 D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` || 1309 ( echo "${L}" && false ) || 1310 die -d "overlay takeover failed after reboot" 1311 1312 adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null | 1313 skip_administrative_mounts | 1314 grep -v ' \(erofs\|squashfs\|ext4\|f2fs\|vfat\) ' && 1315 echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 || 1316 echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2 1317fi 1318 1319if ${enforcing}; then 1320 adb_unroot || 1321 die "device not in unroot'd state" 1322 B="`adb_cat /vendor/hello 2>&1`" 1323 check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root 1324 echo "${GREEN}[ OK ]${NORMAL} /vendor content correct MAC after reboot" >&2 1325 # Feed unprivileged log with selinux denials as a result of overlays 1326 wait_for_screen 1327 adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null 1328fi 1329# If overlayfs has a nested security problem, this will fail. 1330B="`adb_ls /system/`" || 1331 die "adb ls /system" 1332[ X"${B}" != X"${B#*priv-app}" ] || 1333 die "adb ls /system/priv-app" 1334B="`adb_cat /system/priv-app/hello`" 1335check_eq "${A}" "${B}" /system/priv-app after reboot 1336# Only root can read vendor if sepolicy permissions are as expected. 1337adb_root || 1338 die "adb root" 1339for i in ${MOUNTS}; do 1340 B="`adb_cat ${i}/hello`" 1341 check_eq "${A}" "${B}" ${i#/} after reboot 1342 echo "${GREEN}[ OK ]${NORMAL} ${i} content remains after reboot" >&2 1343done 1344 1345check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot 1346check_eq "${VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/hello </dev/null`" vendor devt after reboot 1347check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot 1348check_eq "${VENDOR_INO}" "`adb_sh stat --format=%i /vendor/hello </dev/null`" vendor inode after reboot 1349check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" base system devt after reboot 1350check_eq "${BASE_VENDOR_DEVT}" "`adb_sh stat --format=%D /vendor/bin/stat </dev/null`" base system devt after reboot 1351check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" devt for su after reboot 1352 1353# Feed log with selinux denials as a result of overlays 1354adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null 1355 1356# Check if the updated libc.so is persistent after reboot. 1357adb_root && 1358 adb pull /system/lib/bootstrap/libc.so ${tempdir}/libc.so.fromdevice >/dev/null || 1359 die "pull libc.so from device" 1360diff ${tempdir}/libc.so ${tempdir}/libc.so.fromdevice > /dev/null || die "libc.so differ" 1361rm -rf ${tempdir} 1362cleanup() { 1363 true 1364} 1365echo "${GREEN}[ OK ]${NORMAL} /system/lib/bootstrap/libc.so content remains after reboot" >&2 1366 1367echo "${GREEN}[ RUN ]${NORMAL} flash vendor, confirm its content disappears" >&2 1368 1369H=`adb_sh echo '${HOSTNAME}' </dev/null 2>/dev/null` 1370is_bootloader_fastboot=false 1371# cuttlefish? 1372[ X"${H}" != X"${H#vsoc}" ] || is_bootloader_fastboot=true 1373is_userspace_fastboot=false 1374 1375if ! ${is_bootloader_fastboot}; then 1376 echo "${ORANGE}[ WARNING ]${NORMAL} does not support fastboot, skipping" 1377elif [ -z "${ANDROID_PRODUCT_OUT}" ]; then 1378 echo "${ORANGE}[ WARNING ]${NORMAL} build tree not setup, skipping" 1379elif [ ! -s "${ANDROID_PRODUCT_OUT}/vendor.img" ]; then 1380 echo "${ORANGE}[ WARNING ]${NORMAL} vendor image missing, skipping" 1381elif [ "${ANDROID_PRODUCT_OUT}" = "${ANDROID_PRODUCT_OUT%*/${H}}" ]; then 1382 echo "${ORANGE}[ WARNING ]${NORMAL} wrong vendor image, skipping" 1383elif [ -z "${ANDROID_HOST_OUT}" ]; then 1384 echo "${ORANGE}[ WARNING ]${NORMAL} please run lunch, skipping" 1385elif ! ( 1386 adb_cat /vendor/build.prop | 1387 cmp -s ${ANDROID_PRODUCT_OUT}/vendor/build.prop 1388 ) >/dev/null 2>/dev/null; then 1389 echo "${ORANGE}[ WARNING ]${NORMAL} vendor image signature mismatch, skipping" 1390else 1391 wait_for_screen 1392 avc_check 1393 adb reboot fastboot </dev/null || 1394 die "fastbootd not supported (wrong adb in path?)" 1395 any_wait ${ADB_WAIT} && 1396 inFastboot || 1397 die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)" 1398 fastboot flash vendor || 1399 ( fastboot reboot && false) || 1400 die "fastboot flash vendor" 1401 fastboot_getvar is-userspace yes && 1402 is_userspace_fastboot=true 1403 if [ -n "${scratch_paritition}" ]; then 1404 fastboot_getvar partition-type:${scratch_partition} raw || 1405 ( fastboot reboot && false) || 1406 die "fastboot can not see ${scratch_partition} parameters" 1407 if ${uses_dynamic_scratch}; then 1408 # check ${scratch_partition} via fastboot 1409 fastboot_getvar has-slot:${scratch_partition} no && 1410 fastboot_getvar is-logical:${scratch_partition} yes || 1411 ( fastboot reboot && false) || 1412 die "fastboot can not see ${scratch_partition} parameters" 1413 else 1414 fastboot_getvar is-logical:${scratch_partition} no || 1415 ( fastboot reboot && false) || 1416 die "fastboot can not see ${scratch_partition} parameters" 1417 fi 1418 if ! ${uses_dynamic_scratch}; then 1419 fastboot reboot-bootloader || 1420 die "Reboot into fastboot" 1421 fi 1422 if ${uses_dynamic_scratch}; then 1423 echo "${BLUE}[ INFO ]${NORMAL} expect fastboot erase ${scratch_partition} to fail" >&2 1424 fastboot erase ${scratch_partition} && 1425 ( fastboot reboot || true) && 1426 die "fastboot can erase ${scratch_partition}" 1427 fi 1428 echo "${BLUE}[ INFO ]${NORMAL} expect fastboot format ${scratch_partition} to fail" >&2 1429 fastboot format ${scratch_partition} && 1430 ( fastboot reboot || true) && 1431 die "fastboot can format ${scratch_partition}" 1432 fi 1433 fastboot reboot || 1434 die "can not reboot out of fastboot" 1435 echo "${ORANGE}[ WARNING ]${NORMAL} adb after fastboot" 1436 adb_wait ${ADB_WAIT} || 1437 fixup_from_recovery || 1438 die "did not reboot after formatting ${scratch_partition} `usb_status`" 1439 if ${overlayfs_needed}; then 1440 adb_root && 1441 D=`adb_sh df -k </dev/null` && 1442 H=`echo "${D}" | head -1` && 1443 D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` && 1444 echo "${H}" && 1445 echo "${D}" && 1446 echo "${D}" | grep "^overlay .* /system\$" >/dev/null || 1447 die "overlay /system takeover after flash vendor" 1448 echo "${D}" | grep "^overlay .* /vendor\$" >/dev/null && 1449 if ${is_userspace_fastboot}; then 1450 die "overlay supposed to be minus /vendor takeover after flash vendor" 1451 else 1452 echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 1453 echo "${ORANGE}[ WARNING ]${NORMAL} overlay supposed to be minus /vendor takeover after flash vendor" >&2 1454 fi 1455 fi 1456 B="`adb_cat /system/hello`" 1457 check_eq "${A}" "${B}" system after flash vendor 1458 B="`adb_ls /system/`" || 1459 die "adb ls /system" 1460 [ X"${B}" != X"${B#*priv-app}" ] || 1461 die "adb ls /system/priv-app" 1462 B="`adb_cat /system/priv-app/hello`" 1463 check_eq "${A}" "${B}" system/priv-app after flash vendor 1464 adb_root || 1465 die "adb root" 1466 B="`adb_cat /vendor/hello`" 1467 if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then 1468 check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ 1469 vendor content after flash vendor 1470 else 1471 echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2 1472 check_eq "cat: /vendor/hello: No such file or directory" "${B}" \ 1473 --warning vendor content after flash vendor 1474 fi 1475 1476 check_eq "${SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/hello </dev/null`" system devt after reboot 1477 check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot 1478 check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/bin/stat </dev/null`" base system devt after reboot 1479 check_eq "${BASE_SYSTEM_DEVT}" "`adb_sh stat --format=%D /system/xbin/su </dev/null`" devt for su after reboot 1480 1481fi 1482 1483wait_for_screen 1484echo "${GREEN}[ RUN ]${NORMAL} remove test content (cleanup)" >&2 1485 1486T=`adb_date` 1487H=`adb remount 2>&1` 1488err=${?} 1489L= 1490D="${H%?Now reboot your device for settings to take effect*}" 1491if [ X"${H}" != X"${D}" ]; then 1492 echo "${ORANGE}[ WARNING ]${NORMAL} adb remount requires a reboot after partial flash (legacy avb)" 1493 L=`adb_logcat -b all -v nsec -t ${T} 2>&1` 1494 adb_reboot && 1495 adb_wait ${ADB_WAIT} && 1496 adb_root || 1497 die "failed to reboot" 1498 T=`adb_date` 1499 H=`adb remount 2>&1` 1500 err=${?} 1501fi 1502echo "${H}" 1503[ ${err} = 0 ] && 1504 ( adb_sh rm /vendor/hello </dev/null 2>/dev/null || true ) && 1505 adb_sh rm /system/hello /system/priv-app/hello </dev/null || 1506 ( [ -n "${L}" ] && echo "${L}" && false ) || 1507 die -t ${T} "cleanup hello" 1508B="`adb_cat /system/hello`" 1509check_eq "cat: /system/hello: No such file or directory" "${B}" after rm 1510B="`adb_cat /system/priv-app/hello`" 1511check_eq "cat: /system/priv-app/hello: No such file or directory" "${B}" after rm 1512B="`adb_cat /vendor/hello`" 1513check_eq "cat: /vendor/hello: No such file or directory" "${B}" after rm 1514for i in ${MOUNTS}; do 1515 adb_sh rm ${i}/hello </dev/null 2>/dev/null || true 1516done 1517 1518if ${is_bootloader_fastboot} && [ -n "${scratch_partition}" ]; then 1519 1520 echo "${GREEN}[ RUN ]${NORMAL} test fastboot flash to ${scratch_partition} recovery" >&2 1521 1522 avc_check 1523 adb reboot fastboot </dev/null || 1524 die "Reboot into fastbootd" 1525 img=${TMPDIR}/adb-remount-test-${$}.img 1526 cleanup() { 1527 rm ${img} 1528 } 1529 dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null && 1530 fastboot_wait ${FASTBOOT_WAIT} || 1531 die "reboot into fastboot to flash scratch `usb_status`" 1532 fastboot flash --force ${scratch_partition} ${img} 1533 err=${?} 1534 cleanup 1535 cleanup() { 1536 true 1537 } 1538 fastboot reboot || 1539 die "can not reboot out of fastboot" 1540 [ 0 -eq ${err} ] || 1541 die "fastboot flash ${scratch_partition}" 1542 adb_wait ${ADB_WAIT} && 1543 adb_root || 1544 die "did not reboot after flashing empty ${scratch_partition} `usb_status`" 1545 T=`adb_date` 1546 D=`adb disable-verity 2>&1` 1547 err=${?} 1548 if [ X"${D}" != "${D%?Now reboot your device for settings to take effect*}" ] 1549 then 1550 echo "${ORANGE}[ WARNING ]${NORMAL} adb disable-verity requires a reboot after partial flash" 1551 adb_reboot && 1552 adb_wait ${ADB_WAIT} && 1553 adb_root || 1554 die "failed to reboot" 1555 T=`adb_date` 1556 D="${D} 1557`adb disable-verity 2>&1`" 1558 err=${?} 1559 fi 1560 1561 echo "${D}" 1562 [ ${err} = 0 ] && 1563 [ X"${D}" = X"${D##*setup failed}" ] && 1564 [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] && 1565 echo "${GREEN}[ OK ]${NORMAL} ${scratch_partition} recreated" >&2 || 1566 die -t ${T} "setup for overlayfs" 1567 D=`adb remount 2>&1` 1568 err=${?} 1569 echo "${D}" 1570 [ ${err} != 0 ] || 1571 [ X"${D}" = X"${D##*remount failed}" ] || 1572 ( echo "${D}" && false ) || 1573 die -t ${T} "remount failed" 1574fi 1575 1576echo "${GREEN}[ RUN ]${NORMAL} test raw remount commands" >&2 1577 1578fixup_from_fastboot() { 1579 inFastboot || return 1 1580 if [ -n "${ACTIVE_SLOT}" ]; then 1581 local active_slot=`get_active_slot` 1582 if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then 1583 echo "${ORANGE}[ ERROR ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" 1584 else 1585 echo "${ORANGE}[ ERROR ]${NORMAL} Active slot to be set to ${ACTIVE_SLOT}" 1586 fi >&2 1587 fastboot --set-active=${ACTIVE_SLOT} 1588 fi 1589 fastboot reboot 1590 adb_wait ${ADB_WAIT} 1591} 1592 1593# Prerequisite is a prepped device from above. 1594adb_reboot && 1595 adb_wait ${ADB_WAIT} || 1596 fixup_from_fastboot || 1597 die "lost device after reboot to ro state `usb_status`" 1598adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && 1599 die "/vendor is not read-only" 1600adb_su mount -o rw,remount /vendor </dev/null || 1601 die "remount command" 1602adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || 1603 die "/vendor is not read-write" 1604echo "${GREEN}[ OK ]${NORMAL} mount -o rw,remount command works" >&2 1605 1606# Prerequisite is a prepped device from above. 1607adb_reboot && 1608 adb_wait ${ADB_WAIT} || 1609 fixup_from_fastboot || 1610 die "lost device after reboot to ro state `usb_status`" 1611adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && 1612 die "/vendor is not read-only" 1613adb_su remount vendor </dev/null || 1614 die "remount command" 1615adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || 1616 die "/vendor is not read-write" 1617adb_sh grep " /system .* rw," /proc/mounts >/dev/null </dev/null && 1618 die "/vendor is not read-only" 1619echo "${GREEN}[ OK ]${NORMAL} remount command works from setup" >&2 1620 1621# Prerequisite is an overlayfs deconstructed device but with verity disabled. 1622# This also saves a lot of 'noise' from the command doing a mkfs on backing 1623# storage and all the related tuning and adjustment. 1624for d in ${OVERLAYFS_BACKING}; do 1625 adb_su rm -rf /${d}/overlay </dev/null || 1626 die "/${d}/overlay wipe" 1627done 1628adb_reboot && 1629 adb_wait ${ADB_WAIT} || 1630 fixup_from_fastboot || 1631 die "lost device after reboot after wipe `usb_status`" 1632adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null && 1633 die "/vendor is not read-only" 1634adb_su remount vendor </dev/null || 1635 die "remount command" 1636adb_su df -k </dev/null | skip_unrelated_mounts 1637adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null || 1638 die "/vendor is not read-write" 1639adb_sh grep " \(/system\|/\) .* rw," /proc/mounts >/dev/null </dev/null && 1640 die "/system is not read-only" 1641echo "${GREEN}[ OK ]${NORMAL} remount command works from scratch" >&2 1642 1643if ! restore; then 1644 restore() { 1645 true 1646 } 1647 die "failed to restore verity after remount from scratch test" 1648fi 1649 1650err=0 1651 1652if ${overlayfs_supported}; then 1653 echo "${GREEN}[ RUN ]${NORMAL} test 'adb remount -R'" >&2 1654 avc_check 1655 adb_root || 1656 die "adb root in preparation for adb remount -R" 1657 T=`adb_date` 1658 adb remount -R 1659 err=${?} 1660 if [ "${err}" != 0 ]; then 1661 die -t ${T} "adb remount -R = ${err}" 1662 fi 1663 sleep 2 1664 adb_wait ${ADB_WAIT} || 1665 die "waiting for device after adb remount -R `usb_status`" 1666 if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \ 1667 "2" = "`get_property partition.system.verified`" ] && 1668 [ -n "`get_property ro.boot.verifiedbootstate`" -o \ 1669 -n "`get_property partition.system.verified`" ]; then 1670 die "remount -R command failed to disable verity 1671${INDENT}ro.boot.verifiedbootstate=\"`get_property ro.boot.verifiedbootstate`\" 1672${INDENT}partition.system.verified=\"`get_property partition.system.verified`\"" 1673 fi 1674 1675 echo "${GREEN}[ OK ]${NORMAL} 'adb remount -R' command" >&2 1676 1677 restore 1678 err=${?} 1679fi 1680 1681restore() { 1682 true 1683} 1684 1685[ ${err} = 0 ] || 1686 die "failed to restore verity" 1687 1688echo "${GREEN}[ PASSED ]${NORMAL} adb remount" >&2 1689 1690test_duration 1691