fs_mgr: overlayfs: export fs_mgr_overlayfs_candidate_list

Refactor fs_mgr_candidate_list into fs_mgr_overlayfs_candidate_list
that reports all the possible candidates.  The caller is responsible
for filtering out any that have verity enabled.

Sundry improvements to the adb-remount-test.sh script to improve
stability and feedback.

Test: adb-remount-test.sh
Bug: 122602260
Change-Id: I2399f83d8ed77d8f3d2ad1405d0c187ccbace764
This commit is contained in:
Mark Salyzyn 2019-01-24 11:08:10 -08:00
parent 111e38e5bc
commit dffdb4374b
3 changed files with 103 additions and 57 deletions

View File

@ -78,6 +78,10 @@ bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
return {};
}
bool fs_mgr_overlayfs_mount_all(Fstab*) {
return false;
}
@ -238,8 +242,7 @@ std::string fs_mgr_get_overlayfs_options(const std::string& mount_point) {
return ret;
}
const char* fs_mgr_mount_point(const char* mount_point) {
if (!mount_point) return mount_point;
const std::string fs_mgr_mount_point(const std::string& mount_point) {
if ("/"s != mount_point) return mount_point;
return "/system";
}
@ -526,40 +529,6 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
}
}
std::vector<std::string> fs_mgr_candidate_list(Fstab* fstab, const char* mount_point = nullptr) {
std::vector<std::string> mounts;
for (auto& entry : *fstab) {
if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
!fs_mgr_wants_overlayfs(&entry)) {
continue;
}
std::string new_mount_point(fs_mgr_mount_point(entry.mount_point.c_str()));
if (mount_point && (new_mount_point != mount_point)) continue;
auto saved_errno = errno;
auto verity_enabled = fs_mgr_is_verity_enabled(entry);
if (errno == ENOENT || errno == ENXIO) errno = saved_errno;
if (verity_enabled) continue;
auto duplicate_or_more_specific = false;
for (auto it = mounts.begin(); it != mounts.end();) {
if ((*it == new_mount_point) ||
(android::base::StartsWith(new_mount_point, *it + "/"))) {
duplicate_or_more_specific = true;
break;
}
if (android::base::StartsWith(*it, new_mount_point + "/")) {
it = mounts.erase(it);
} else {
++it;
}
}
if (!duplicate_or_more_specific) mounts.emplace_back(new_mount_point);
}
return mounts;
}
// Mount kScratchMountPoint
bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type,
bool readonly = false) {
@ -802,12 +771,42 @@ bool fs_mgr_overlayfs_invalid() {
} // namespace
Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
Fstab candidates;
for (const auto& entry : fstab) {
FstabEntry new_entry = entry;
if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
!fs_mgr_wants_overlayfs(&new_entry)) {
continue;
}
auto new_mount_point = fs_mgr_mount_point(entry.mount_point);
auto duplicate_or_more_specific = false;
for (auto it = candidates.begin(); it != candidates.end();) {
auto it_mount_point = fs_mgr_mount_point(it->mount_point);
if ((it_mount_point == new_mount_point) ||
(android::base::StartsWith(new_mount_point, it_mount_point + "/"))) {
duplicate_or_more_specific = true;
break;
}
if (android::base::StartsWith(it_mount_point, new_mount_point + "/")) {
it = candidates.erase(it);
} else {
++it;
}
}
if (!duplicate_or_more_specific) candidates.emplace_back(std::move(new_entry));
}
return candidates;
}
bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
auto ret = false;
if (fs_mgr_overlayfs_invalid()) return ret;
auto scratch_can_be_mounted = true;
for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
if (fs_mgr_is_verity_enabled(entry)) continue;
auto mount_point = fs_mgr_mount_point(entry.mount_point);
if (fs_mgr_overlayfs_already_mounted(mount_point)) {
ret = true;
continue;
@ -840,8 +839,9 @@ std::vector<std::string> fs_mgr_overlayfs_required_devices(Fstab* fstab) {
return {};
}
for (const auto& mount_point : fs_mgr_candidate_list(fstab)) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) continue;
for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
if (fs_mgr_is_verity_enabled(entry)) continue;
if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) continue;
auto device = fs_mgr_overlayfs_scratch_device();
if (!fs_mgr_overlayfs_scratch_can_be_mounted(device)) break;
return {device};
@ -867,8 +867,24 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool*
return false;
}
errno = save_errno;
auto mounts = fs_mgr_candidate_list(&fstab, fs_mgr_mount_point(mount_point));
if (mounts.empty()) return ret;
auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
for (auto it = candidates.begin(); it != candidates.end();) {
if (mount_point &&
(fs_mgr_mount_point(it->mount_point) != fs_mgr_mount_point(mount_point))) {
it = candidates.erase(it);
continue;
}
save_errno = errno;
auto verity_enabled = fs_mgr_is_verity_enabled(*it);
if (errno == ENOENT || errno == ENXIO) errno = save_errno;
if (verity_enabled) {
it = candidates.erase(it);
continue;
}
++it;
}
if (candidates.empty()) return ret;
std::string dir;
for (const auto& overlay_mount_point : kOverlayMountPoints) {
@ -891,8 +907,8 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool*
std::string overlay;
ret |= fs_mgr_overlayfs_setup_dir(dir, &overlay, change);
for (const auto& fsrec_mount_point : mounts) {
ret |= fs_mgr_overlayfs_setup_one(overlay, fsrec_mount_point, change);
for (const auto& entry : candidates) {
ret |= fs_mgr_overlayfs_setup_one(overlay, fs_mgr_mount_point(entry.mount_point), change);
}
return ret;
}
@ -901,7 +917,6 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool*
// If something is altered, set *change.
bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
if (change) *change = false;
mount_point = fs_mgr_mount_point(mount_point);
auto ret = true;
// If scratch exists, but is not mounted, lets gain access to clean
// specific override entries.
@ -919,7 +934,8 @@ bool fs_mgr_overlayfs_teardown(const char* mount_point, bool* change) {
fs_mgr_overlayfs_scratch_mount_type());
}
for (const auto& overlay_mount_point : kOverlayMountPoints) {
ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
ret &= fs_mgr_overlayfs_teardown_one(
overlay_mount_point, mount_point ? fs_mgr_mount_point(mount_point) : "", change);
}
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
// After obligatory teardown to make sure everything is clean, but if
@ -946,8 +962,9 @@ bool fs_mgr_overlayfs_is_setup() {
return false;
}
if (fs_mgr_overlayfs_invalid()) return false;
for (const auto& mount_point : fs_mgr_candidate_list(&fstab)) {
if (fs_mgr_overlayfs_already_mounted(mount_point)) return true;
for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
if (fs_mgr_is_verity_enabled(entry)) continue;
if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
}
return false;
}

View File

@ -21,6 +21,8 @@
#include <string>
#include <vector>
android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
std::vector<std::string> fs_mgr_overlayfs_required_devices(android::fs_mgr::Fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,

View File

@ -210,6 +210,21 @@ adb_wait() {
fi
}
[ "USAGE: usb_status > stdout
If adb_wait failed, check if device is in fastboot mode and report status
Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ]
usb_status() {
if inFastboot; then
echo "(In fastboot mode)"
elif inAdb; then
echo "(In adb mode)"
else
echo "(USB stack borken?)"
fi
}
[ "USAGE: fastboot_wait [timeout]
Returns: waits until the device has returned for fastboot or optional timeout" ]
@ -383,6 +398,17 @@ skip_administrative_mounts() {
-e " /\(cache\|mnt/scratch\|mnt/vendor/persist\|persist\|metadata\) "
}
[ "USAGE: skip_unrelated_mounts < /proc/mounts
or output from df
Filters out all apex and vendor override administrative overlay mounts
uninteresting to the test" ]
skip_unrelated_mounts() {
grep -v "^overlay.* /\(apex\|bionic\|system\|vendor\)/[^ ]" |
grep -v "[%] /\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$"
}
##
## MAINLINE
##
@ -484,9 +510,9 @@ if ${reboot}; then
echo "${ORANGE}[ WARNING ]${NORMAL} rebooting before test" >&2
adb_reboot &&
adb_wait 2m ||
die "lost device after reboot after wipe (USB stack broken?)"
die "lost device after reboot after wipe `usb_status`"
adb_root ||
die "lost device after elevation to root after wipe (USB stack broken?)"
die "lost device after elevation to root after wipe `usb_status`"
fi
D=`adb_sh df -k </dev/null` &&
H=`echo "${D}" | head -1` &&
@ -509,7 +535,8 @@ for d in ${D}; do
grep "Filesystem features:.*shared_blocks" >/dev/null &&
no_dedupe=false
done
D=`adb_sh df -k ${D} </dev/null`
D=`adb_sh df -k ${D} </dev/null |
sed 's@\([%] /\)\(apex\|bionic\|system\|vendor\)/[^ ][^ ]*$@\1@'`
echo "${D}"
if [ X"${D}" = X"${D##* 100[%] }" ] && ${no_dedupe} ; then
overlayfs_needed=false
@ -548,9 +575,9 @@ if [ X"${D}" != X"${H}" ]; then
L=`adb_logcat -b all -v nsec -t ${T} 2>&1`
adb_reboot &&
adb_wait 2m ||
die "lost device after reboot requested (USB stack broken?)"
die "lost device after reboot requested `usb_status`"
adb_root ||
die "lost device after elevation to root (USB stack broken?)"
die "lost device after elevation to root `usb_status`"
rebooted=true
# re-disable verity to see the setup remarks expected
T=`adb_date`
@ -593,7 +620,7 @@ adb remount ||
die -t "${T}" "adb remount failed"
D=`adb_sh df -k </dev/null` &&
H=`echo "${D}" | head -1` &&
D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` ||
D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` ||
( [ -n "${L}" ] && echo "${L}" && false )
ret=${?}
uses_dynamic_scratch=false
@ -637,7 +664,7 @@ if ${overlayfs_needed}; then
echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
die "overlay takeover after remount"
!(adb_sh grep "^overlay " /proc/mounts </dev/null |
grep -v "^overlay /\(vendor\|system\|bionic\)/..* overlay ro," |
skip_unrelated_mounts |
grep " overlay ro,") &&
!(adb_sh grep " rw," /proc/mounts </dev/null |
skip_administrative_mounts data) ||
@ -694,7 +721,7 @@ if ${overlayfs_needed}; then
adb_su sed -n '1,/overlay \/system/p' /proc/mounts </dev/null |
skip_administrative_mounts |
grep -v ' \(squashfs\|ext4\|f2fs\) ' &&
grep -v ' \(squashfs\|ext4\|f2fs\|vfat\) ' &&
echo "${ORANGE}[ WARNING ]${NORMAL} overlay takeover after first stage init" >&2 ||
echo "${GREEN}[ OK ]${NORMAL} overlay takeover in first stage init" >&2
fi
@ -782,7 +809,7 @@ else
adb_root &&
D=`adb_sh df -k </dev/null` &&
H=`echo "${D}" | head -1` &&
D=`echo "${D}" | grep -v " /vendor/..*$" | grep "^overlay "` &&
D=`echo "${D}" | skip_unrelated_mounts | grep "^overlay "` &&
echo "${H}" &&
echo "${D}" &&
echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
@ -888,7 +915,7 @@ echo "${GREEN}[ RUN ]${NORMAL} test raw remount commands" >&2
# Prerequisite is a prepped device from above.
adb_reboot &&
adb_wait 2m ||
die "lost device after reboot to ro state (USB stack broken?)"
die "lost device after reboot to ro state `usb_status`"
adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null &&
die "/vendor is not read-only"
adb_su mount -o rw,remount /vendor ||