Merge changes I7a2dd830,I6ce43725,I5fc2f370,Ibc2e14bd,Idf213800, ...
* changes: fs_mgr_remount: support legacy devices (marlin) fs_mgr: remount: add -R argument fs_mgr: remount: add -T fstab argument fs_mgr: remount: log to stderr and logd fs_mgr: add remount command fs_mgr: overlayfs: test: add inRecovery check
This commit is contained in:
commit
c620f4a1b8
|
@ -111,3 +111,35 @@ cc_library_static {
|
|||
"libgsi_headers",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "remount",
|
||||
defaults: ["fs_mgr_defaults"],
|
||||
static_libs: [
|
||||
"libavb_user",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbootloader_message",
|
||||
"libbase",
|
||||
"libcrypto",
|
||||
"libfec",
|
||||
"libfs_mgr",
|
||||
],
|
||||
header_libs: [
|
||||
"libcutils_headers",
|
||||
],
|
||||
srcs: [
|
||||
"fs_mgr_remount.cpp",
|
||||
],
|
||||
cppflags: [
|
||||
"-DALLOW_ADBD_DISABLE_VERITY=0",
|
||||
],
|
||||
product_variables: {
|
||||
debuggable: {
|
||||
cppflags: [
|
||||
"-UALLOW_ADBD_DISABLE_VERITY",
|
||||
"-DALLOW_ADBD_DISABLE_VERITY=1",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <libavb_user/libavb_user.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <bootloader_message/bootloader_message.h>
|
||||
#include <cutils/android_reboot.h>
|
||||
#include <fec/io.h>
|
||||
#include <fs_mgr_overlayfs.h>
|
||||
#include <fs_mgr_priv.h>
|
||||
#include <fstab/fstab.h>
|
||||
|
||||
namespace {
|
||||
|
||||
[[noreturn]] void usage(int exit_status) {
|
||||
LOG(INFO) << getprogname()
|
||||
<< " [-h] [-R] [-T fstab_file]\n"
|
||||
"\t-h --help\tthis help\n"
|
||||
"\t-R --reboot\tdisable verity & reboot to facilitate remount\n"
|
||||
"\t-T --fstab\tcustom fstab file location\n"
|
||||
"\n"
|
||||
"Remount all partitions read-write.\n"
|
||||
"-R notwithstanding, verity must be disabled.";
|
||||
|
||||
::exit(exit_status);
|
||||
}
|
||||
|
||||
bool remountable_partition(const android::fs_mgr::FstabEntry& entry) {
|
||||
if (entry.fs_mgr_flags.vold_managed) return false;
|
||||
if (entry.fs_mgr_flags.recovery_only) return false;
|
||||
if (entry.fs_mgr_flags.slot_select_other) return false;
|
||||
if (!(entry.flags & MS_RDONLY)) return false;
|
||||
if (entry.fs_type == "vfat") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
|
||||
if (entry.mount_point == "/") return "/system";
|
||||
return entry.mount_point;
|
||||
}
|
||||
|
||||
const android::fs_mgr::FstabEntry* is_wrapped(const android::fs_mgr::Fstab& overlayfs_candidates,
|
||||
const android::fs_mgr::FstabEntry& entry) {
|
||||
auto mount_point = system_mount_point(entry);
|
||||
auto it = std::find_if(overlayfs_candidates.begin(), overlayfs_candidates.end(),
|
||||
[&mount_point](const auto& entry) {
|
||||
return android::base::StartsWith(mount_point,
|
||||
system_mount_point(entry) + "/");
|
||||
});
|
||||
if (it == overlayfs_candidates.end()) return nullptr;
|
||||
return &(*it);
|
||||
}
|
||||
|
||||
void try_unmount_bionic(android::fs_mgr::Fstab* mounts) {
|
||||
static constexpr const char* kBionic = "/bionic";
|
||||
|
||||
auto entry = GetEntryForMountPoint(mounts, kBionic);
|
||||
if (!entry) return;
|
||||
|
||||
struct statfs buf;
|
||||
if (::statfs(kBionic, &buf) == -1) {
|
||||
PLOG(ERROR) << "statfs of " << kBionic;
|
||||
return;
|
||||
}
|
||||
if (buf.f_flags & MS_RDONLY) {
|
||||
// /bionic is on a read-only partition; can happen for
|
||||
// non-system-as-root-devices. Don' try to unmount.
|
||||
return;
|
||||
}
|
||||
fs_mgr_set_blk_ro(entry->blk_device, false);
|
||||
if (::mount(entry->blk_device.c_str(), entry->mount_point.c_str(), entry->fs_type.c_str(),
|
||||
MS_REMOUNT, nullptr) == -1) {
|
||||
PLOG(ERROR) << "remount of " << kBionic;
|
||||
}
|
||||
}
|
||||
|
||||
void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
|
||||
const char* file, unsigned int line, const char* message) {
|
||||
static const char log_characters[] = "VD\0WEFF";
|
||||
if (severity < sizeof(log_characters)) {
|
||||
auto severity_char = log_characters[severity];
|
||||
if (severity_char) fprintf(stderr, "%c ", severity_char);
|
||||
}
|
||||
fprintf(stderr, "%s\n", message);
|
||||
|
||||
static auto logd = android::base::LogdLogger();
|
||||
logd(id, severity, tag, file, line, message);
|
||||
}
|
||||
|
||||
[[noreturn]] void reboot(bool dedupe) {
|
||||
if (dedupe) {
|
||||
LOG(INFO) << "The device will now reboot to recovery and attempt un-deduplication.";
|
||||
} else {
|
||||
LOG(INFO) << "Successfully disabled verity\nrebooting device";
|
||||
}
|
||||
::sync();
|
||||
android::base::SetProperty(ANDROID_RB_PROPERTY, dedupe ? "reboot,recovery" : "reboot,remount");
|
||||
::sleep(60);
|
||||
::exit(0); // SUCCESS
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
android::base::InitLogging(argv, MyLogger);
|
||||
|
||||
enum {
|
||||
SUCCESS,
|
||||
NOT_USERDEBUG,
|
||||
BADARG,
|
||||
NOT_ROOT,
|
||||
NO_FSTAB,
|
||||
VERITY_PARTITION,
|
||||
BAD_OVERLAY,
|
||||
NO_MOUNTS,
|
||||
REMOUNT_FAILED,
|
||||
} retval = SUCCESS;
|
||||
|
||||
// If somehow this executable is delivered on a "user" build, it can
|
||||
// not function, so providing a clear message to the caller rather than
|
||||
// letting if fall through and provide a lot of confusing failure messages.
|
||||
if (!ALLOW_ADBD_DISABLE_VERITY || (android::base::GetProperty("ro.debuggable", "0") != "1")) {
|
||||
LOG(ERROR) << "only functions on userdebug or eng builds";
|
||||
return NOT_USERDEBUG;
|
||||
}
|
||||
|
||||
const char* fstab_file = nullptr;
|
||||
auto can_reboot = false;
|
||||
|
||||
struct option longopts[] = {
|
||||
{"fstab", required_argument, nullptr, 'T'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"reboot", no_argument, nullptr, 'R'},
|
||||
{0, 0, nullptr, 0},
|
||||
};
|
||||
for (int opt; (opt = ::getopt_long(argc, argv, "hRT:", longopts, nullptr)) != -1;) {
|
||||
switch (opt) {
|
||||
case 'R':
|
||||
can_reboot = true;
|
||||
break;
|
||||
case 'T':
|
||||
if (fstab_file) {
|
||||
LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg;
|
||||
usage(BADARG);
|
||||
}
|
||||
fstab_file = optarg;
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Bad Argument -" << char(opt);
|
||||
usage(BADARG);
|
||||
break;
|
||||
case 'h':
|
||||
usage(SUCCESS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > optind) {
|
||||
LOG(ERROR) << "Bad Argument " << argv[optind];
|
||||
usage(BADARG);
|
||||
}
|
||||
|
||||
// Make sure we are root.
|
||||
if (::getuid() != 0) {
|
||||
LOG(ERROR) << "must be run as root";
|
||||
return NOT_ROOT;
|
||||
}
|
||||
|
||||
// Read the selected fstab.
|
||||
android::fs_mgr::Fstab fstab;
|
||||
auto fstab_read = false;
|
||||
if (fstab_file) {
|
||||
fstab_read = android::fs_mgr::ReadFstabFromFile(fstab_file, &fstab);
|
||||
} else {
|
||||
fstab_read = android::fs_mgr::ReadDefaultFstab(&fstab);
|
||||
}
|
||||
if (!fstab_read || fstab.empty()) {
|
||||
PLOG(ERROR) << "Failed to read fstab";
|
||||
return NO_FSTAB;
|
||||
}
|
||||
|
||||
// Generate the list of supported overlayfs mount points.
|
||||
auto overlayfs_candidates = fs_mgr_overlayfs_candidate_list(fstab);
|
||||
|
||||
// Generate the all remountable partitions sub-list
|
||||
android::fs_mgr::Fstab partitions;
|
||||
for (auto const& entry : fstab) {
|
||||
if (!remountable_partition(entry)) continue;
|
||||
if (overlayfs_candidates.empty() ||
|
||||
GetEntryForMountPoint(&overlayfs_candidates, entry.mount_point) ||
|
||||
(is_wrapped(overlayfs_candidates, entry) == nullptr)) {
|
||||
partitions.emplace_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Check verity and optionally setup overlayfs backing.
|
||||
auto reboot_later = false;
|
||||
for (auto it = partitions.begin(); it != partitions.end();) {
|
||||
auto& entry = *it;
|
||||
auto& mount_point = entry.mount_point;
|
||||
if (fs_mgr_is_verity_enabled(entry)) {
|
||||
LOG(WARNING) << "Verity enabled on " << mount_point;
|
||||
if (can_reboot &&
|
||||
(android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked")) {
|
||||
if (AvbOps* ops = avb_ops_user_new()) {
|
||||
auto ret = avb_user_verity_set(
|
||||
ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
|
||||
false);
|
||||
avb_ops_user_free(ops);
|
||||
if (ret) {
|
||||
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
|
||||
retval = VERITY_PARTITION;
|
||||
// w/o overlayfs available, also check for dedupe
|
||||
reboot_later = true;
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
reboot(false);
|
||||
} else if (fs_mgr_set_blk_ro(entry.blk_device, false)) {
|
||||
fec::io fh(entry.blk_device.c_str(), O_RDWR);
|
||||
if (fh && fh.set_verity_status(false)) reboot_later = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG(ERROR) << "Skipping " << mount_point;
|
||||
retval = VERITY_PARTITION;
|
||||
it = partitions.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto change = false;
|
||||
errno = 0;
|
||||
if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change)) {
|
||||
if (change) {
|
||||
LOG(INFO) << "Using overlayfs for " << mount_point;
|
||||
}
|
||||
} else if (errno) {
|
||||
PLOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
|
||||
retval = BAD_OVERLAY;
|
||||
it = partitions.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
if (partitions.empty()) {
|
||||
if (reboot_later) reboot(false);
|
||||
LOG(WARNING) << "No partitions to remount";
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Mount overlayfs.
|
||||
if (!fs_mgr_overlayfs_mount_all(&partitions)) {
|
||||
retval = BAD_OVERLAY;
|
||||
PLOG(ERROR) << "Can not mount overlayfs for partitions";
|
||||
}
|
||||
|
||||
// Get actual mounts _after_ overlayfs has been added.
|
||||
android::fs_mgr::Fstab mounts;
|
||||
if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
|
||||
PLOG(ERROR) << "Failed to read /proc/mounts";
|
||||
retval = NO_MOUNTS;
|
||||
}
|
||||
|
||||
// Remount selected partitions.
|
||||
for (auto& entry : partitions) {
|
||||
// unlock the r/o key for the mount point device
|
||||
if (entry.fs_mgr_flags.logical) {
|
||||
fs_mgr_update_logical_partition(&entry);
|
||||
}
|
||||
auto blk_device = entry.blk_device;
|
||||
auto mount_point = entry.mount_point;
|
||||
|
||||
for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
|
||||
auto& rentry = *it;
|
||||
if (mount_point == rentry.mount_point) {
|
||||
blk_device = rentry.blk_device;
|
||||
break;
|
||||
}
|
||||
if ((mount_point == "/") && (rentry.mount_point == "/system")) {
|
||||
if (blk_device != "/dev/root") blk_device = rentry.blk_device;
|
||||
mount_point = "/system";
|
||||
break;
|
||||
}
|
||||
}
|
||||
fs_mgr_set_blk_ro(blk_device, false);
|
||||
|
||||
// Now remount!
|
||||
if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
|
||||
nullptr) == 0) {
|
||||
continue;
|
||||
}
|
||||
if ((errno == EINVAL) && (mount_point != entry.mount_point)) {
|
||||
mount_point = entry.mount_point;
|
||||
if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
|
||||
nullptr) == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PLOG(WARNING) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
|
||||
// If errno = EROFS at this point, we are dealing with r/o
|
||||
// filesystem types like squashfs, erofs or ext4 dedupe. We will
|
||||
// consider such a device that does not have CONFIG_OVERLAY_FS
|
||||
// in the kernel as a misconfigured; except for ext4 dedupe.
|
||||
if ((errno == EROFS) && can_reboot) {
|
||||
const std::vector<std::string> msg = {"--fsck_unshare_blocks"};
|
||||
std::string err;
|
||||
if (write_bootloader_message(msg, &err)) reboot(true);
|
||||
LOG(ERROR) << "Failed to set bootloader message: " << err;
|
||||
errno = EROFS;
|
||||
}
|
||||
retval = REMOUNT_FAILED;
|
||||
}
|
||||
|
||||
if (reboot_later) reboot(false);
|
||||
|
||||
try_unmount_bionic(&mounts);
|
||||
|
||||
return retval;
|
||||
}
|
|
@ -70,19 +70,37 @@ inFastboot() {
|
|||
Returns: true if device is in adb mode" ]
|
||||
inAdb() {
|
||||
adb devices |
|
||||
grep -v -e 'List of devices attached' -e '^$' |
|
||||
grep -v -e 'List of devices attached' -e '^$' -e "[${SPACE}${TAB}]recovery\$" |
|
||||
if [ -n "${ANDROID_SERIAL}" ]; then
|
||||
grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null
|
||||
else
|
||||
wc -l | grep '^1$' >/dev/null
|
||||
fi
|
||||
}
|
||||
[ "USAGE: inRecovery
|
||||
|
||||
Returns: true if device is in recovery mode" ]
|
||||
inRecovery() {
|
||||
local list="`adb devices |
|
||||
grep -v -e 'List of devices attached' -e '^$'`"
|
||||
if [ -n "${ANDROID_SERIAL}" ]; then
|
||||
echo "${list}" |
|
||||
grep "^${ANDROID_SERIAL}[${SPACE}${TAB}][${SPACE}${TAB}]*recovery\$" >/dev/null
|
||||
return ${?}
|
||||
fi
|
||||
if echo "${list}" | wc -l | grep '^1$' >/dev/null; then
|
||||
echo "${list}" |
|
||||
grep "[${SPACE}${TAB}]recovery\$" >/dev/null
|
||||
return ${?}
|
||||
fi
|
||||
false
|
||||
}
|
||||
|
||||
[ "USAGE: adb_sh <commands> </dev/stdin >/dev/stdout 2>/dev/stderr
|
||||
|
||||
Returns: true if the command succeeded" ]
|
||||
adb_sh() {
|
||||
args=
|
||||
local args=
|
||||
for i in "${@}"; do
|
||||
[ -z "${args}" ] || args="${args} "
|
||||
if [ X"${i}" != X"${i#\'}" ]; then
|
||||
|
@ -143,10 +161,10 @@ adb_su() {
|
|||
Returns: content of file to stdout with carriage returns skipped,
|
||||
true of the file exists" ]
|
||||
adb_cat() {
|
||||
OUTPUT="`adb_sh cat ${1} </dev/null 2>&1`"
|
||||
retval=${?}
|
||||
local OUTPUT="`adb_sh cat ${1} </dev/null 2>&1`"
|
||||
local ret=${?}
|
||||
echo "${OUTPUT}" | tr -d '\r'
|
||||
return ${retval}
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
[ "USAGE: adb_reboot
|
||||
|
@ -165,7 +183,7 @@ format_duration() {
|
|||
echo unknown
|
||||
return
|
||||
fi
|
||||
duration="${1}"
|
||||
local duration="${1}"
|
||||
if [ X"${duration}" != X"${duration%s}" ]; then
|
||||
duration=${duration%s}
|
||||
elif [ X"${duration}" != X"${duration%m}" ]; then
|
||||
|
@ -175,9 +193,9 @@ format_duration() {
|
|||
elif [ X"${duration}" != X"${duration%d}" ]; then
|
||||
duration=`expr ${duration%d} \* 86400`
|
||||
fi
|
||||
seconds=`expr ${duration} % 60`
|
||||
minutes=`expr \( ${duration} / 60 \) % 60`
|
||||
hours=`expr ${duration} / 3600`
|
||||
local seconds=`expr ${duration} % 60`
|
||||
local minutes=`expr \( ${duration} / 60 \) % 60`
|
||||
local hours=`expr ${duration} / 3600`
|
||||
if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then
|
||||
if [ 1 -eq ${duration} ]; then
|
||||
echo 1 second
|
||||
|
@ -205,10 +223,10 @@ Returns: waits until the device has returned for adb or optional timeout" ]
|
|||
adb_wait() {
|
||||
if [ -n "${1}" ]; then
|
||||
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
|
||||
timeout --preserve-status --signal=KILL ${1} adb wait-for-device
|
||||
retval=${?}
|
||||
timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null
|
||||
local ret=${?}
|
||||
echo -n " ${CR}"
|
||||
return ${retval}
|
||||
return ${ret}
|
||||
else
|
||||
adb wait-for-device
|
||||
fi
|
||||
|
@ -216,12 +234,15 @@ adb_wait() {
|
|||
|
||||
[ "USAGE: usb_status > stdout
|
||||
|
||||
If adb_wait failed, check if device is in fastboot mode and report status
|
||||
If adb_wait failed, check if device is in adb, recovery or fastboot mode
|
||||
and report status string.
|
||||
|
||||
Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ]
|
||||
usb_status() {
|
||||
if inFastboot; then
|
||||
echo "(In fastboot mode)"
|
||||
elif inRecovery; then
|
||||
echo "(In recovery mode)"
|
||||
elif inAdb; then
|
||||
echo "(In adb mode)"
|
||||
else
|
||||
|
@ -238,15 +259,47 @@ fastboot_wait() {
|
|||
if [ -n "${1}" ]; then
|
||||
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
|
||||
timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
|
||||
retval=${?}
|
||||
local ret=${?}
|
||||
echo -n " ${CR}"
|
||||
( exit ${retval} )
|
||||
( exit ${ret} )
|
||||
else
|
||||
fastboot wait-for-device >/dev/null 2>/dev/null
|
||||
fi ||
|
||||
inFastboot
|
||||
}
|
||||
|
||||
[ "USAGE: recovery_wait [timeout]
|
||||
|
||||
Returns: waits until the device has returned for recovery or optional timeout" ]
|
||||
recovery_wait() {
|
||||
if [ -n "${1}" ]; then
|
||||
echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
|
||||
timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null
|
||||
local ret=${?}
|
||||
echo -n " ${CR}"
|
||||
return ${ret}
|
||||
else
|
||||
adb wait-for-recovery
|
||||
fi
|
||||
}
|
||||
|
||||
[ "any_wait [timeout]
|
||||
|
||||
Returns: waits until a device has returned or optional timeout" ]
|
||||
any_wait() {
|
||||
(
|
||||
adb_wait ${1} &
|
||||
adb_pid=${!}
|
||||
fastboot_wait ${1} &
|
||||
fastboot_pid=${!}
|
||||
recovery_wait ${1} &
|
||||
recovery_pid=${!}
|
||||
wait -n
|
||||
kill "${adb_pid}" "${fastboot_pid}" "${recovery_pid}"
|
||||
) >/dev/null 2>/dev/null
|
||||
inFastboot || inAdb || inRecovery
|
||||
}
|
||||
|
||||
[ "USAGE: adb_root
|
||||
|
||||
NB: This can be flakey on devices due to USB state
|
||||
|
@ -277,11 +330,11 @@ adb_unroot() {
|
|||
|
||||
Returns: true if var output matches expected" ]
|
||||
fastboot_getvar() {
|
||||
O=`fastboot getvar ${1} 2>&1`
|
||||
err=${?}
|
||||
local O=`fastboot getvar ${1} 2>&1`
|
||||
local ret=${?}
|
||||
O="${O#< waiting for * >?}"
|
||||
O="${O%%?Finished. Total time: *}"
|
||||
if [ 0 -ne ${err} ]; then
|
||||
if [ 0 -ne ${ret} ]; then
|
||||
echo ${O} >&2
|
||||
false
|
||||
return
|
||||
|
@ -325,7 +378,7 @@ test_duration() {
|
|||
echo "${BLUE}[ INFO ]${NORMAL} end `date`"
|
||||
[ -n "${start_time}" ] || return
|
||||
end_time=`date +%s`
|
||||
diff_time=`expr ${end_time} - ${start_time}`
|
||||
local diff_time=`expr ${end_time} - ${start_time}`
|
||||
echo "${BLUE}[ INFO ]${NORMAL} duration `format_duration ${diff_time}`"
|
||||
fi >&2
|
||||
}
|
||||
|
@ -358,8 +411,8 @@ die() {
|
|||
|
||||
Returns true if (regex) lval matches rval" ]
|
||||
EXPECT_EQ() {
|
||||
lval="${1}"
|
||||
rval="${2}"
|
||||
local lval="${1}"
|
||||
local rval="${2}"
|
||||
shift 2
|
||||
if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then
|
||||
if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval%
|
||||
|
@ -404,10 +457,10 @@ EXPECT_EQ() {
|
|||
|
||||
Exits if (regex) lval mismatches rval" ]
|
||||
check_eq() {
|
||||
left="${1}"
|
||||
right="${2}"
|
||||
local lval="${1}"
|
||||
local rval="${2}"
|
||||
shift 2
|
||||
EXPECT_EQ "${left}" "${right}" ||
|
||||
EXPECT_EQ "${lval}" "${rval}" ||
|
||||
die "${@}"
|
||||
}
|
||||
|
||||
|
@ -498,15 +551,16 @@ if ${print_time}; then
|
|||
fi
|
||||
|
||||
inFastboot && die "device in fastboot mode"
|
||||
inRecovery && die "device in recovery mode"
|
||||
if ! inAdb; then
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode"
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} device not in adb mode" >&2
|
||||
adb_wait 2m
|
||||
fi
|
||||
inAdb || die "specified device not in adb mode"
|
||||
isDebuggable || die "device not a debug build"
|
||||
enforcing=true
|
||||
if ! adb_su getenforce </dev/null | grep 'Enforcing' >/dev/null; then
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode"
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} device does not have sepolicy in enforcing mode" >&2
|
||||
enforcing=false
|
||||
fi
|
||||
|
||||
|
@ -563,6 +617,19 @@ if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
|
|||
adb_reboot &&
|
||||
adb_wait 2m
|
||||
}
|
||||
|
||||
echo "${GREEN}[ RUN ]${NORMAL} Testing adb shell su root remount -R command" >&2
|
||||
|
||||
adb_su remount -R </dev/null || true
|
||||
sleep 2
|
||||
adb_wait 2m ||
|
||||
die "waiting for device after remount -R `usb_status`"
|
||||
if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
|
||||
"2" = "`get_property partition.system.verified`" ]; then
|
||||
die "remount -R command failed"
|
||||
fi
|
||||
|
||||
echo "${GREEN}[ OK ]${NORMAL} adb shell su root remount -R command" >&2
|
||||
fi
|
||||
|
||||
echo "${GREEN}[ RUN ]${NORMAL} Testing kernel support for overlayfs" >&2
|
||||
|
@ -577,7 +644,7 @@ adb_sh ls -d /sys/module/overlay </dev/null >/dev/null 2>/dev/null ||
|
|||
) ||
|
||||
overlayfs_supported=false
|
||||
if ${overlayfs_supported}; then
|
||||
adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null &&
|
||||
adb_su ls /sys/module/overlay/parameters/override_creds </dev/null >/dev/null 2>/dev/null &&
|
||||
echo "${GREEN}[ OK ]${NORMAL} overlay module supports override_creds" >&2 ||
|
||||
case `adb_sh uname -r </dev/null` in
|
||||
4.[456789].* | 4.[1-9][0-9]* | [56789].*)
|
||||
|
@ -857,21 +924,20 @@ if ${overlayfs_needed}; then
|
|||
echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2
|
||||
fi
|
||||
|
||||
B="`adb_cat /system/hello`" ||
|
||||
die "re-read /system/hello after reboot"
|
||||
check_eq "${A}" "${B}" /system after reboot
|
||||
echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2
|
||||
# Only root can read vendor if sepolicy permissions are as expected.
|
||||
if ${enforcing}; then
|
||||
adb_unroot
|
||||
B="`adb_cat /vendor/hello`" &&
|
||||
die "re-read /vendor/hello after reboot w/o root"
|
||||
adb_unroot ||
|
||||
die "device not in unroot'd state"
|
||||
B="`adb_cat /vendor/hello 2>&1`"
|
||||
check_eq "cat: /vendor/hello: Permission denied" "${B}" vendor after reboot w/o root
|
||||
echo "${GREEN}[ OK ]${NORMAL} /vendor content correct MAC after reboot" >&2
|
||||
fi
|
||||
adb_root &&
|
||||
B="`adb_cat /vendor/hello`" ||
|
||||
die "re-read /vendor/hello after reboot"
|
||||
B="`adb_cat /system/hello`"
|
||||
check_eq "${A}" "${B}" /system after reboot
|
||||
echo "${GREEN}[ OK ]${NORMAL} /system content remains after reboot" >&2
|
||||
# Only root can read vendor if sepolicy permissions are as expected.
|
||||
adb_root ||
|
||||
die "adb root"
|
||||
B="`adb_cat /vendor/hello`"
|
||||
check_eq "${A}" "${B}" vendor after reboot
|
||||
echo "${GREEN}[ OK ]${NORMAL} /vendor content remains after reboot" >&2
|
||||
|
||||
|
@ -901,8 +967,9 @@ elif [ -z "${ANDROID_HOST_OUT}" ]; then
|
|||
else
|
||||
adb reboot-fastboot ||
|
||||
die "fastbootd not supported (wrong adb in path?)"
|
||||
fastboot_wait 2m ||
|
||||
die "reboot into fastboot to flash vendor `usb_status`"
|
||||
any_wait 2m &&
|
||||
inFastboot ||
|
||||
die "reboot into fastboot to flash vendor `usb_status` (bad bootloader?)"
|
||||
fastboot flash vendor ||
|
||||
( fastboot reboot && false) ||
|
||||
die "fastboot flash vendor"
|
||||
|
@ -956,12 +1023,11 @@ else
|
|||
if ${is_userspace_fastboot}; then
|
||||
die "overlay supposed to be minus /vendor takeover after flash vendor"
|
||||
else
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing, ignoring a failure"
|
||||
( die "overlay supposed to be minus /vendor takeover after flash vendor" )
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} overlay supposed to be minus /vendor takeover after flash vendor" >&2
|
||||
fi
|
||||
fi
|
||||
B="`adb_cat /system/hello`" ||
|
||||
die "re-read /system/hello after flash vendor"
|
||||
B="`adb_cat /system/hello`"
|
||||
check_eq "${A}" "${B}" system after flash vendor
|
||||
adb_root ||
|
||||
die "adb root"
|
||||
|
@ -969,13 +1035,21 @@ else
|
|||
if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then
|
||||
die "re-read /vendor/hello after flash vendor"
|
||||
else
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing, ignoring a failure"
|
||||
( die "re-read /vendor/hello after flash vendor" )
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} re-read /vendor/hello after flash vendor" >&2
|
||||
fi
|
||||
if ${is_userspace_fastboot} || ! ${overlayfs_needed}; then
|
||||
check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor
|
||||
check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
|
||||
vendor content after flash vendor
|
||||
else
|
||||
( check_eq "cat: /vendor/hello: No such file or directory" "${B}" vendor after flash vendor )
|
||||
(
|
||||
echo "${ORANGE}[ WARNING ]${NORMAL} user fastboot missing required to invalidate, ignoring a failure" >&2
|
||||
restore() {
|
||||
true
|
||||
}
|
||||
check_eq "cat: /vendor/hello: No such file or directory" "${B}" \
|
||||
vendor content after flash vendor
|
||||
)
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -1003,12 +1077,10 @@ echo "${H}"
|
|||
adb_sh rm /system/hello </dev/null ||
|
||||
( [ -n "${L}" ] && echo "${L}" && false ) ||
|
||||
die -t ${T} "cleanup hello"
|
||||
B="`adb_cat /system/hello`" &&
|
||||
die "re-read /system/hello after rm"
|
||||
check_eq "cat: /system/hello: No such file or directory" "${B}" after flash rm
|
||||
B="`adb_cat /vendor/hello`" &&
|
||||
die "re-read /vendor/hello after rm"
|
||||
check_eq "cat: /vendor/hello: No such file or directory" "${B}" after flash rm
|
||||
B="`adb_cat /system/hello`"
|
||||
check_eq "cat: /system/hello: No such file or directory" "${B}" after rm
|
||||
B="`adb_cat /vendor/hello`"
|
||||
check_eq "cat: /vendor/hello: No such file or directory" "${B}" after rm
|
||||
|
||||
if [ -n "${scratch_partition}" ]; then
|
||||
|
||||
|
@ -1081,9 +1153,56 @@ adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null ||
|
|||
die "/vendor is not read-write"
|
||||
echo "${GREEN}[ OK ]${NORMAL} mount -o rw,remount command works" >&2
|
||||
|
||||
# Prerequisite is a prepped device from above.
|
||||
adb_reboot &&
|
||||
adb_wait 2m ||
|
||||
die "lost device after reboot to ro state (USB stack broken?)"
|
||||
adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
|
||||
die "/vendor is not read-only"
|
||||
adb_su remount </dev/null ||
|
||||
die "remount command"
|
||||
adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null ||
|
||||
die "/vendor is not read-write"
|
||||
echo "${GREEN}[ OK ]${NORMAL} remount command works from setup" >&2
|
||||
|
||||
# Prerequisite is an overlayfs deconstructed device but with verity disabled.
|
||||
# This also saves a lot of 'noise' from the command doing a mkfs on backing
|
||||
# storage and all the related tuning and adjustment.
|
||||
for d in ${OVERLAYFS_BACKING}; do
|
||||
adb_su rm -rf /${d}/overlay </dev/null ||
|
||||
die "/${d}/overlay wipe"
|
||||
done
|
||||
adb_reboot &&
|
||||
adb_wait 2m ||
|
||||
die "lost device after reboot after wipe (USB stack broken?)"
|
||||
adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
|
||||
die "/vendor is not read-only"
|
||||
adb_su remount </dev/null ||
|
||||
die "remount command"
|
||||
adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null ||
|
||||
die "/vendor is not read-write"
|
||||
echo "${GREEN}[ OK ]${NORMAL} remount command works from scratch" >&2
|
||||
|
||||
restore
|
||||
err=${?}
|
||||
|
||||
if [ ${err} = 0 ] && ${overlayfs_supported}; then
|
||||
echo "${GREEN}[ RUN ]${NORMAL} test 'adb remount -R'" >&2
|
||||
adb_root &&
|
||||
adb remount -R &&
|
||||
adb_wait 2m ||
|
||||
die "adb remount -R"
|
||||
if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
|
||||
"2" = "`get_property partition.system.verified`" ]; then
|
||||
die "remount -R command failed to disable verity"
|
||||
fi
|
||||
|
||||
echo "${GREEN}[ OK ]${NORMAL} 'adb remount -R' command" >&2
|
||||
|
||||
restore
|
||||
err=${?}
|
||||
fi
|
||||
|
||||
restore() {
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue