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