• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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