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