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 1085err=${?} 1086[[ ${err} -eq 0 || ${err} -eq 255 ]] || 1087 die -t "${T}" "disable-verity -R failed" 1088sleep 2 1089adb_wait "${ADB_WAIT}" || 1090 die "lost device after adb disable-verity -R $(usb_status)" 1091 1092if [ "2" = "$(get_property partition.system.verified)" ]; then 1093 LOG ERROR "partition.system.verified=$(get_property partition.system.verified)" 1094 die "verity not disabled after adb disable-verity -R" 1095fi 1096if ${overlayfs_needed}; then 1097 is_overlayfs_mounted || 1098 die -d "no overlay takeover after adb disable-verity -R" 1099 LOG OK "overlay takeover after adb disable-verity -R" 1100fi 1101LOG OK "adb disable-verity -R" 1102 1103################################################################################ 1104LOG RUN "Checking kernel has overlayfs required patches" 1105 1106adb_root || die "adb root" 1107if adb_test -d /sys/module/overlay || 1108 adb_sh grep -q "nodev${TAB}overlay" /proc/filesystems; then 1109 LOG OK "overlay module present" 1110else 1111 LOG INFO "overlay module not present" 1112fi 1113if is_overlayfs_mounted 2>/dev/null; then 1114 if adb_test -f /sys/module/overlay/parameters/override_creds; then 1115 LOG OK "overlay module supports override_creds" 1116 else 1117 case "$(adb_sh uname -r </dev/null)" in 1118 4.[456789].* | 4.[1-9][0-9]* | [56789].*) 1119 die "overlay module does not support override_creds" 1120 ;; 1121 *) 1122 LOG OK "overlay module uses caller's creds" 1123 ;; 1124 esac 1125 fi 1126fi 1127 1128################################################################################ 1129# Precondition is a verity-disabled device with overlayfs already setup. 1130LOG RUN "Testing raw remount commands" 1131 1132adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null && 1133 die "/system is not RO" 1134adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null && 1135 die "/vendor is not RO" 1136 1137T=$(adb_date) 1138adb_su mount -o remount,rw /vendor || 1139 die -t "${T}" "mount -o remount,rw /vendor" 1140adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null || 1141 die "/vendor is not RW after mount -o remount,rw" 1142LOG OK "mount -o remount,rw" 1143 1144T=$(adb_date) 1145adb_su mount -o remount,ro /vendor || 1146 die -t "${T}" "mount -o remount,ro /vendor" 1147adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null && 1148 die "/vendor is not RO after mount -o remount,ro" 1149LOG OK "mount -o remount,ro" 1150 1151T=$(adb_date) 1152adb_su remount vendor >&2 || 1153 die -t "${T}" "adb remount vendor" 1154adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null || 1155 die -t "${T}" "/vendor is not RW after adb remount vendor" 1156adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null && 1157 die -t "${T}" "/system is not RO after adb remount vendor" 1158LOG OK "adb remount vendor" 1159 1160LOG INFO "Restoring device RO state and destroying overlayfs" 1161T=$(adb_date) 1162adb_su mount -o remount,ro /vendor || 1163 die -t "${T}" "mount -o remount,ro /vendor" 1164if surgically_wipe_overlayfs; then 1165 adb_reboot || 1166 die "lost device after reboot after overlay wipe $(usb_status)" 1167fi 1168is_overlayfs_mounted && 1169 die "overlay takeover unexpected at this phase" 1170 1171################################################################################ 1172# Precondition is a verity-disabled device with overlayfs *not* setup. 1173LOG RUN "Testing adb remount performs overlayfs setup from scratch" 1174 1175adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null && 1176 die "/vendor is not RO" 1177T=$(adb_date) 1178adb_su remount vendor >&2 || 1179 die -t "${T}" "adb remount vendor from scratch" 1180if ${overlayfs_needed}; then 1181 is_overlayfs_mounted /vendor || 1182 die -t "${T}" "expected overlay takeover /vendor" 1183 is_overlayfs_mounted /system 2>/dev/null && 1184 die -t "${T}" "unexpected overlay takeover /system" 1185fi 1186adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null || 1187 die -t "${T}" "/vendor is not RW after adb remount vendor" 1188adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null && 1189 die -t "${T}" "/system is not RO after adb remount vendor" 1190LOG OK "adb remount from scratch" 1191 1192################################################################################ 1193# Precondition is overlayfs partially setup by previous test. 1194LOG RUN "Testing adb remount -R" 1195 1196T=$(adb_date) 1197adb_su remount -R </dev/null >&2 1198err=${?} 1199[[ ${err} -eq 0 || ${err} -eq 255 ]] || 1200 die -t "${T}" "adb remount -R failed" 1201sleep 2 1202adb_wait "${ADB_WAIT}" || 1203 die "lost device after adb remount -R $(usb_status)" 1204 1205if [ "2" = "$(get_property partition.system.verified)" ]; then 1206 LOG ERROR "partition.system.verified=$(get_property partition.system.verified)" 1207 die "verity not disabled after adb remount -R" 1208fi 1209if ${overlayfs_needed}; then 1210 is_overlayfs_mounted /system || 1211 die -d "expected overlay takeover /system" 1212 is_overlayfs_mounted /vendor 2>/dev/null || 1213 die -d "expected overlay takeover /vendor" 1214 LOG OK "overlay takeover after adb remount -R" 1215fi 1216LOG OK "adb remount -R" 1217 1218# For devices using overlayfs, remount -R should reboot after overlayfs setup. 1219# For legacy device, manual reboot to ensure device clean state. 1220if ! ${overlayfs_needed}; then 1221 LOG WARNING "Reboot to RO (device doesn't use overlayfs)" 1222 adb_reboot || 1223 die "lost device after reboot to RO $(usb_status)" 1224fi 1225 1226################################################################################ 1227# Precondition is a verity-disabled device with overlayfs already setup. 1228LOG RUN "Testing adb remount RW" 1229 1230# Feed log with selinux denials as baseline before overlays 1231adb_unroot 1232adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null || true 1233adb_root 1234 1235adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null && 1236 die "/system is not RO" 1237adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null && 1238 die "/vendor is not RO" 1239 1240data_device=$(adb_sh awk '$2 == "/data" { print $1; exit }' /proc/mounts) 1241RO=$(adb_sh grep " ro," /proc/mounts </dev/null | 1242 grep -v "^${data_device}" | 1243 skip_administrative_mounts | 1244 awk '{ print $1 }') 1245 1246T=$(adb_date) 1247adb remount >&2 || 1248 die -t "${T}" "adb remount" 1249adb_sh grep -qE " (/system|/) [^ ]* rw," /proc/mounts </dev/null || 1250 die -t "${T}" "/system is not RW" 1251adb_sh grep -q " /vendor [^ ]* rw," /proc/mounts </dev/null || 1252 die -t "${T}" "/vendor is not RW" 1253 1254# Only find mounts that are remounted RO -> RW 1255RW=$(adb_sh grep " rw," /proc/mounts </dev/null | 1256 grep -v "^${data_device}" | 1257 skip_administrative_mounts | 1258 grep -E "^($(join_with '|' ${RO})) ") 1259 1260scratch_on_super=false 1261if ${overlayfs_needed}; then 1262 is_overlayfs_mounted /system || 1263 die -t "${T}" "expected overlay to takeover /system after remount" 1264 1265 # Collect information about the scratch device if we have one 1266 M=$(adb_sh cat /proc/mounts </dev/null | 1267 awk '$2 == "/mnt/scratch" { print $1, $3; exit }') 1268 if [ -n "${M}" ]; then 1269 scratch_device=$(echo "${M}" | awk '{ print $1 }') 1270 scratch_filesystem=$(echo "${M}" | awk '{ print $2 }') 1271 scratch_size=$(adb_sh df -k "${scratch_device}" </dev/null | 1272 tail +2 | head -1 | awk '{ print $2 }') 1273 [ -z "${scratch_size}" ] && die "cannot get size of scratch device (${scratch_device})" 1274 1275 # Detect scratch partition backed by super? 1276 for b in "/dev/block/by-name/super"{,_${ACTIVE_SLOT}}; do 1277 if adb_test -e "${b}"; then 1278 device=$(adb_su realpath "${b}") 1279 D=$(adb_su stat -c '0x%t 0x%T' "${device}") 1280 major=$(echo "${D}" | awk '{ print $1 }') 1281 minor=$(echo "${D}" | awk '{ print $2 }') 1282 super_devt=$(( major )):$(( minor )) 1283 if adb_su dmctl table scratch | tail +2 | grep -q -w "${super_devt}"; then 1284 scratch_on_super=true 1285 fi 1286 break 1287 fi 1288 done 1289 1290 if ${scratch_on_super}; then 1291 LOG INFO "using dynamic scratch partition on super" 1292 else 1293 LOG INFO "using dynamic scratch partition on /data (VAB device)" 1294 fi 1295 LOG INFO "scratch device ${scratch_device} filesystem ${scratch_filesystem} size ${scratch_size}KiB" 1296 else 1297 LOG INFO "cannot find any scratch device mounted on /mnt/scratch, using scratch on /cache" 1298 fi 1299 1300 for d in ${OVERLAYFS_BACKING}; do 1301 if adb_test -d /${d}/overlay/system/upper; then 1302 LOG INFO "/${d}/overlay is setup" 1303 fi 1304 done 1305 1306 # KISS (we do not support sub-mounts for system partitions currently) 1307 adb_sh grep "^overlay " /proc/mounts </dev/null | 1308 grep -vE "^overlay.* /(apex|system|vendor)/[^ ]" | 1309 grep " overlay ro," && 1310 die "expected overlay to be RW after remount" 1311 1312 D=$(echo "${RW}" | 1313 awk '{ print $1 }' | 1314 sed 's|/dev/root|/|' | 1315 sort -u) 1316 if [ -n "${D}" ]; then 1317 adb_sh df -k ${D} </dev/null | 1318 sed -e 's/^Filesystem /Filesystem (rw)/' 1319 fi >&2 1320 for d in ${D}; do 1321 if adb_sh tune2fs -l "${d}" </dev/null 2>&1 | grep -q "Filesystem features:.*shared_blocks" || 1322 adb_sh df -k "${d}" | grep -q " 100% "; then 1323 die "remount overlayfs missed a spot (rw)" 1324 fi 1325 done 1326else 1327 is_overlayfs_mounted && die -t "${T}" "unexpected overlay takeover" 1328fi 1329 1330echo -n "${RW}" | 1331 grep -v noatime && 1332 die "mounts (rw) are not noatime" 1333 1334LOG OK "adb remount RW" 1335 1336################################################################################ 1337LOG RUN "push content to ${MOUNTS}" 1338 1339adb_root || die "adb root" 1340A="Hello World! $(date)" 1341for i in ${MOUNTS} /system/priv-app; do 1342 echo "${A}" | adb_sh cat - ">${i}/hello" 1343 B="`adb_cat ${i}/hello`" || 1344 die "${i#/} hello" 1345 check_eq "${A}" "${B}" ${i} before reboot 1346done 1347SYSTEM_INO=`adb_sh stat --format=%i /system/hello </dev/null` 1348VENDOR_INO=`adb_sh stat --format=%i /vendor/hello </dev/null` 1349check_ne "${SYSTEM_INO}" "${VENDOR_INO}" vendor and system inode 1350 1351# Edit build.prop and check if properties are updated. 1352system_build_prop_original="${TMPDIR}/system_build.prop.original" 1353system_build_prop_modified="${TMPDIR}/system_build.prop.modified" 1354system_build_prop_fromdevice="${TMPDIR}/system_build.prop.fromdevice" 1355adb pull /system/build.prop "${system_build_prop_original}" >/dev/null || 1356 die "adb pull /system/build.prop" 1357# Prepend with extra newline in case the original file doesn't end with a newline. 1358cat "${system_build_prop_original}" - <<EOF >"${system_build_prop_modified}" 1359 1360# Properties added by adb remount test 1361test.adb.remount.system.build.prop=true 1362EOF 1363adb push "${system_build_prop_modified}" /system/build.prop >/dev/null || 1364 die "adb push /system/build.prop" 1365adb pull /system/build.prop "${system_build_prop_fromdevice}" >/dev/null || 1366 die "adb pull /system/build.prop" 1367diff "${system_build_prop_modified}" "${system_build_prop_fromdevice}" >/dev/null || 1368 die "/system/build.prop differs from pushed content" 1369 1370################################################################################ 1371LOG RUN "reboot to confirm content persistent" 1372 1373fixup_from_recovery() { 1374 inRecovery || return 1 1375 LOG ERROR "Device in recovery" 1376 adb reboot </dev/null 1377 adb_wait ${ADB_WAIT} 1378} 1379 1380adb_reboot || 1381 fixup_from_recovery || 1382 die "reboot after override content added failed `usb_status`" 1383 1384if ${overlayfs_needed}; then 1385 is_overlayfs_mounted || 1386 die -d "overlay takeover failed after reboot" 1387 1388 adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null | 1389 skip_administrative_mounts | 1390 grep -v ' \(erofs\|squashfs\|ext4\|f2fs\|vfat\) ' && 1391 LOG WARNING "overlay takeover after first stage init" || 1392 LOG OK "overlay takeover in first stage init" 1393fi 1394 1395if ${enforcing}; then 1396 adb_unroot || 1397 die "device not in unroot'd state" 1398 B="`adb_cat /vendor/hello 2>&1`" 1399 check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root 1400 LOG OK "/vendor content correct MAC after reboot" 1401 # Feed unprivileged log with selinux denials as a result of overlays 1402 wait_for_screen 1403 adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null || true 1404fi 1405# If overlayfs has a nested security problem, this will fail. 1406adb_sh ls /system >/dev/null || die "ls /system" 1407adb_test -d /system/priv-app || die "[ -d /system/priv-app ]" 1408B="`adb_cat /system/priv-app/hello`" 1409check_eq "${A}" "${B}" /system/priv-app after reboot 1410 1411# Only root can read vendor if sepolicy permissions are as expected. 1412adb_root || die "adb root" 1413for i in ${MOUNTS}; do 1414 B="`adb_cat ${i}/hello`" 1415 check_eq "${A}" "${B}" ${i#/} after reboot 1416 LOG OK "${i} content remains after reboot" 1417done 1418 1419check_eq "${SYSTEM_INO}" "`adb_sh stat --format=%i /system/hello </dev/null`" system inode after reboot 1420check_eq "${VENDOR_INO}" "`adb_sh stat --format=%i /vendor/hello </dev/null`" vendor inode after reboot 1421 1422# Feed log with selinux denials as a result of overlays 1423adb_sh find ${MOUNTS} </dev/null >/dev/null 2>/dev/null || true 1424 1425# Check if the updated build.prop is persistent after reboot. 1426check_eq "true" "$(get_property 'test.adb.remount.system.build.prop')" "load modified build.prop" 1427adb pull /system/build.prop "${system_build_prop_fromdevice}" >/dev/null || 1428 die "adb pull /system/build.prop" 1429diff "${system_build_prop_modified}" "${system_build_prop_fromdevice}" >/dev/null || 1430 die "/system/build.prop differs from pushed content" 1431LOG OK "/system/build.prop content remains after reboot" 1432 1433################################################################################ 1434LOG RUN "flash vendor, and confirm vendor override disappears" 1435 1436is_bootloader_fastboot=true 1437# virtual device? 1438case "$(get_property ro.product.vendor.device)" in 1439 vsoc_* | emulator_* | emulator64_*) 1440 is_bootloader_fastboot=false 1441 ;; 1442esac 1443is_userspace_fastboot=false 1444 1445if ! ${is_bootloader_fastboot}; then 1446 LOG WARNING "does not support fastboot flash, skipping" 1447else 1448 wait_for_screen 1449 adb_root || die "adb root" 1450 1451 VENDOR_DEVICE_CANDIDATES=( 1452 "/dev/block/mapper/vendor"{_${ACTIVE_SLOT},} 1453 "/dev/block/by-name/vendor"{_${ACTIVE_SLOT},} 1454 ) 1455 for b in "${VENDOR_DEVICE_CANDIDATES[@]}"; do 1456 if adb_test -e "${b}"; then 1457 adb pull "${b}" "${TMPDIR}/vendor.img" || die "adb pull ${b}" 1458 LOG INFO "pulled ${b} from device as vendor.img" 1459 break 1460 fi 1461 done 1462 [ -f "${TMPDIR}/vendor.img" ] || 1463 die "cannot find block device of vendor partition" 1464 1465 avc_check 1466 adb reboot fastboot </dev/null || 1467 die "fastbootd not supported (wrong adb in path?)" 1468 any_wait ${ADB_WAIT} && 1469 inFastboot || 1470 die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)" 1471 fastboot flash vendor "${TMPDIR}/vendor.img" || 1472 ( fastboot reboot && false) || 1473 die "fastboot flash vendor" 1474 LOG OK "flashed vendor" 1475 1476 fastboot_getvar is-userspace yes && 1477 is_userspace_fastboot=true 1478 1479 if ${scratch_on_super}; then 1480 fastboot_getvar partition-type:scratch raw || 1481 die "fastboot cannot see parameter partition-type:scratch" 1482 fastboot_getvar has-slot:scratch no || 1483 die "fastboot cannot see parameter has-slot:scratch" 1484 fastboot_getvar is-logical:scratch yes || 1485 die "fastboot cannot see parameter is-logical:scratch" 1486 LOG INFO "expect fastboot erase scratch to fail" 1487 fastboot erase scratch && die "fastboot can erase scratch" 1488 LOG INFO "expect fastboot format scratch to fail" 1489 fastboot format scratch && die "fastboot can format scratch" 1490 fi 1491 1492 fastboot reboot || die "cannot reboot out of fastboot" 1493 LOG INFO "reboot from fastboot" 1494 adb_wait ${ADB_WAIT} || 1495 fixup_from_recovery || 1496 die "cannot reboot after flash vendor $(usb_status)" 1497 if ${overlayfs_needed}; then 1498 is_overlayfs_mounted /system || 1499 die "overlay /system takeover after flash vendor" 1500 if is_overlayfs_mounted /vendor 2>/dev/null; then 1501 if ${is_userspace_fastboot}; then 1502 die "overlay supposed to be minus /vendor takeover after flash vendor" 1503 else 1504 LOG WARNING "fastbootd missing required to invalidate, ignoring a failure" 1505 LOG WARNING "overlay supposed to be minus /vendor takeover after flash vendor" 1506 fi 1507 fi 1508 fi 1509 check_eq "${A}" "$(adb_cat /system/hello)" "/system content after flash vendor" 1510 check_eq "${SYSTEM_INO}" "$(adb_sh stat --format=%i /system/hello </dev/null)" "system inode after flash vendor" 1511 adb_sh ls /system >/dev/null || die "ls /system" 1512 adb_test -d /system/priv-app || die "[ -d /system/priv-app ]" 1513 check_eq "${A}" "$(adb_cat /system/priv-app/hello)" "/system/priv-app content after flash vendor" 1514 adb_root || die "adb root" 1515 if adb_test -e /vendor/hello; then 1516 if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then 1517 die "vendor content after flash vendor" 1518 else 1519 LOG WARNING "fastbootd missing required to invalidate, ignoring a failure" 1520 LOG WARNING "vendor content after flash vendor" 1521 fi 1522 fi 1523 LOG OK "vendor override destroyed after flash verdor" 1524fi >&2 1525 1526wait_for_screen 1527 1528################################################################################ 1529LOG RUN "Clean up test content" 1530 1531adb_root || die "adb root" 1532T=$(adb_date) 1533D=$(adb remount 2>&1) || 1534 die -t "${T}" "adb remount" 1535echo "${D}" >&2 1536if [[ "${D}" =~ [Rr]eboot ]]; then 1537 LOG OK "adb remount calls for a reboot after partial flash" 1538 # but we don't really want to, since rebooting just recreates the already tore 1539 # down vendor overlay. 1540fi 1541 1542for i in ${MOUNTS} /system/priv-app; do 1543 adb_sh rm "${i}/hello" 2>/dev/null || true 1544 adb_test -e "${i}/hello" && 1545 die -t "${T}" "/${i}/hello lingers after rm" 1546done 1547 1548################################################################################ 1549if ${is_bootloader_fastboot} && ${scratch_on_super}; then 1550 1551 LOG RUN "test fastboot flash to scratch recovery" 1552 1553 avc_check 1554 adb reboot fastboot </dev/null || 1555 die "Reboot into fastbootd" 1556 img="${TMPDIR}/adb-remount-test-${$}.img" 1557 dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null && 1558 fastboot_wait ${FASTBOOT_WAIT} || 1559 die "reboot into fastboot to flash scratch `usb_status`" 1560 fastboot flash --force scratch ${img} 1561 err=${?} 1562 fastboot reboot || 1563 die "can not reboot out of fastboot" 1564 [ 0 -eq ${err} ] || 1565 die "fastboot flash scratch" 1566 adb_wait ${ADB_WAIT} && 1567 adb_root || 1568 die "did not reboot after flashing empty scratch $(usb_status)" 1569 T=`adb_date` 1570 D=`adb disable-verity 2>&1` 1571 err=${?} 1572 if [ X"${D}" != "${D%?Now reboot your device for settings to take effect*}" ] 1573 then 1574 LOG WARNING "adb disable-verity requires a reboot after partial flash" 1575 adb_reboot && 1576 adb_root || 1577 die "failed to reboot" 1578 T=`adb_date` 1579 D="${D} 1580`adb disable-verity 2>&1`" 1581 err=${?} 1582 fi 1583 1584 echo "${D}" >&2 1585 [ ${err} = 0 ] && 1586 [ X"${D}" = X"${D##*setup failed}" ] && 1587 [ X"${D}" != X"${D##*[Uu]sing overlayfs}" ] && 1588 LOG OK "recreated scratch" || 1589 die -t ${T} "setup for overlayfs" 1590 adb remount >&2 || 1591 die -t ${T} "remount failed" 1592fi 1593 1594 1595LOG PASSED "adb remount test" 1596