Merge changes I1f104422,Iada733bc,I1428eed9
* changes:
remount: Refactor remounting into a helper function.
remount: Refactor dsu enabling into a helper function.
remount: Refactor verity disabling into a helper function.
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 07eaf58..b1606d9 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -85,6 +85,10 @@
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
+bool fs_mgr_wants_overlayfs(FstabEntry*) {
+ return false;
+}
+
Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
return {};
}
@@ -388,26 +392,6 @@
return false;
}
-bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
- // Don't check entries that are managed by vold.
- if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
-
- // *_other doesn't want overlayfs.
- if (entry->fs_mgr_flags.slot_select_other) return false;
-
- // Only concerned with readonly partitions.
- if (!(entry->flags & MS_RDONLY)) return false;
-
- // If unbindable, do not allow overlayfs as this could expose us to
- // security issues. On Android, this could also be used to turn off
- // the ability to overlay an otherwise acceptable filesystem since
- // /system and /vendor are never bound(sic) to.
- if (entry->flags & MS_UNBINDABLE) return false;
-
- if (!fs_mgr_overlayfs_enabled(entry)) return false;
-
- return true;
-}
constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
@@ -1284,6 +1268,27 @@
} // namespace
+bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
+ // Don't check entries that are managed by vold.
+ if (entry->fs_mgr_flags.vold_managed || entry->fs_mgr_flags.recovery_only) return false;
+
+ // *_other doesn't want overlayfs.
+ if (entry->fs_mgr_flags.slot_select_other) return false;
+
+ // Only concerned with readonly partitions.
+ if (!(entry->flags & MS_RDONLY)) return false;
+
+ // If unbindable, do not allow overlayfs as this could expose us to
+ // security issues. On Android, this could also be used to turn off
+ // the ability to overlay an otherwise acceptable filesystem since
+ // /system and /vendor are never bound(sic) to.
+ if (entry->flags & MS_UNBINDABLE) return false;
+
+ if (!fs_mgr_overlayfs_enabled(entry)) return false;
+
+ return true;
+}
+
Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
Fstab candidates;
for (const auto& entry : fstab) {
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index ab17c5c..c47d110 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -261,9 +261,168 @@
return REMOUNT_SUCCESS;
}
-static int do_remount(int argc, char* argv[]) {
- RemountStatus retval = REMOUNT_SUCCESS;
+struct RemountCheckResult {
+ bool reboot_later = false;
+ bool setup_overlayfs = false;
+ bool disabled_verity = false;
+ bool verity_error = false;
+};
+static RemountStatus CheckVerity(const FstabEntry& entry, RemountCheckResult* result) {
+ if (!fs_mgr_is_verity_enabled(entry)) {
+ return REMOUNT_SUCCESS;
+ }
+ if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
+ return VERITY_PARTITION;
+ }
+
+ bool ok = false;
+
+ std::unique_ptr<AvbOps, decltype(&::avb_ops_user_free)> ops(avb_ops_user_new(),
+ &::avb_ops_user_free);
+ if (ops) {
+ auto suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
+ ok = avb_user_verity_set(ops.get(), suffix.c_str(), false);
+ }
+ if (!ok && fs_mgr_set_blk_ro(entry.blk_device, false)) {
+ fec::io fh(entry.blk_device.c_str(), O_RDWR);
+ ok = fh && fh.set_verity_status(false);
+ }
+ if (!ok) {
+ return VERITY_PARTITION;
+ }
+ result->disabled_verity = true;
+ result->reboot_later = true;
+ return REMOUNT_SUCCESS;
+}
+
+static RemountStatus CheckVerityAndOverlayfs(Fstab* partitions, RemountCheckResult* result) {
+ RemountStatus status = REMOUNT_SUCCESS;
+ for (auto it = partitions->begin(); it != partitions->end();) {
+ auto& entry = *it;
+ const auto& mount_point = entry.mount_point;
+
+ if (auto rv = CheckVerity(entry, result); rv != REMOUNT_SUCCESS) {
+ LOG(ERROR) << "Skipping verified partition " << mount_point << " for remount";
+ status = rv;
+ it = partitions->erase(it);
+ continue;
+ }
+
+ if (fs_mgr_wants_overlayfs(&entry)) {
+ bool change = false;
+ bool force = result->disabled_verity;
+ if (!fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, force)) {
+ LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
+ status = BAD_OVERLAY;
+ it = partitions->erase(it);
+ continue;
+ }
+ if (change) {
+ LOG(INFO) << "Using overlayfs for " << mount_point;
+ result->reboot_later = true;
+ result->setup_overlayfs = true;
+ }
+ }
+ it++;
+ }
+ return status;
+}
+
+static RemountStatus EnableDsuIfNeeded() {
+ auto gsid = android::gsi::GetGsiService();
+ if (!gsid) {
+ return REMOUNT_SUCCESS;
+ }
+
+ auto dsu_running = false;
+ if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
+ LOG(ERROR) << "Failed to get DSU running state: " << status;
+ return BINDER_ERROR;
+ }
+ auto dsu_enabled = false;
+ if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
+ LOG(ERROR) << "Failed to get DSU enabled state: " << status;
+ return BINDER_ERROR;
+ }
+ if (dsu_running && !dsu_enabled) {
+ std::string dsu_slot;
+ if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
+ LOG(ERROR) << "Failed to get active DSU slot: " << status;
+ return BINDER_ERROR;
+ }
+ LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
+ "DSU guest system after reboot";
+ int error = 0;
+ if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error);
+ !status.isOk() || error != android::gsi::IGsiService::INSTALL_OK) {
+ LOG(ERROR) << "Failed to enable DSU: " << status << ", error code: " << error;
+ return !status.isOk() ? BINDER_ERROR : GSID_ERROR;
+ }
+ LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
+ }
+ return REMOUNT_SUCCESS;
+}
+
+static RemountStatus RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
+ // 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;
+
+ auto found = false;
+ for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
+ auto& rentry = *it;
+ if (mount_point == rentry.mount_point) {
+ blk_device = rentry.blk_device;
+ found = true;
+ break;
+ }
+ // Find overlayfs mount point?
+ if ((mount_point == "/" && rentry.mount_point == "/system") ||
+ (mount_point == "/system" && rentry.mount_point == "/")) {
+ blk_device = rentry.blk_device;
+ mount_point = "/system";
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
+ return REMOUNT_SUCCESS;
+ }
+ if (blk_device == "/dev/root") {
+ auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
+ if (from_fstab) blk_device = from_fstab->blk_device;
+ }
+ fs_mgr_set_blk_ro(blk_device, false);
+
+ // Find system-as-root mount point?
+ if ((mount_point == "/system") && !GetEntryForMountPoint(&mounts, mount_point) &&
+ GetEntryForMountPoint(&mounts, "/")) {
+ mount_point = "/";
+ }
+
+ // Now remount!
+ if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
+ nullptr) == 0) {
+ return REMOUNT_SUCCESS;
+ }
+ 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) {
+ return REMOUNT_SUCCESS;
+ }
+ }
+
+ PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
+ return REMOUNT_FAILED;
+}
+
+static int do_remount(int argc, char* argv[]) {
// 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.
@@ -342,97 +501,26 @@
}
// Check verity and optionally setup overlayfs backing.
- auto reboot_later = false;
- auto user_please_reboot_later = false;
- auto setup_overlayfs = false;
- auto just_disabled_verity = 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)) {
- retval = VERITY_PARTITION;
- auto ret = false;
- if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") != "locked") {
- if (AvbOps* ops = avb_ops_user_new()) {
- ret = avb_user_verity_set(
- ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
- false);
- avb_ops_user_free(ops);
- }
- if (!ret && fs_mgr_set_blk_ro(entry.blk_device, false)) {
- fec::io fh(entry.blk_device.c_str(), O_RDWR);
- ret = fh && fh.set_verity_status(false);
- }
- if (ret) {
- LOG(WARNING) << "Disabling verity for " << mount_point;
- just_disabled_verity = true;
- reboot_later = can_reboot;
- user_please_reboot_later = true;
- }
- }
- if (!ret) {
- LOG(ERROR) << "Skipping " << mount_point << " for remount";
- it = partitions.erase(it);
- continue;
- }
- }
+ RemountCheckResult check_result;
+ auto retval = CheckVerityAndOverlayfs(&partitions, &check_result);
- auto change = false;
- errno = 0;
- if (fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, just_disabled_verity)) {
- if (change) {
- LOG(INFO) << "Using overlayfs for " << mount_point;
- reboot_later = can_reboot;
- user_please_reboot_later = true;
- setup_overlayfs = true;
- }
- } else if (errno) {
- PLOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
- retval = BAD_OVERLAY;
- it = partitions.erase(it);
- continue;
- }
- ++it;
- }
+ bool auto_reboot = check_result.reboot_later && can_reboot;
// If (1) remount requires a reboot to take effect, (2) system is currently
// running a DSU guest and (3) DSU is disabled, then enable DSU so that the
// next reboot would not take us back to the host system but stay within
// the guest system.
- if (reboot_later) {
- if (auto gsid = android::gsi::GetGsiService()) {
- auto dsu_running = false;
- if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
- LOG(ERROR) << "Failed to get DSU running state: " << status;
- return BINDER_ERROR;
- }
- auto dsu_enabled = false;
- if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
- LOG(ERROR) << "Failed to get DSU enabled state: " << status;
- return BINDER_ERROR;
- }
- if (dsu_running && !dsu_enabled) {
- std::string dsu_slot;
- if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
- LOG(ERROR) << "Failed to get active DSU slot: " << status;
- return BINDER_ERROR;
- }
- LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
- "DSU guest system after reboot";
- int error = 0;
- if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error);
- !status.isOk() || error != android::gsi::IGsiService::INSTALL_OK) {
- LOG(ERROR) << "Failed to enable DSU: " << status << ", error code: " << error;
- return !status.isOk() ? BINDER_ERROR : GSID_ERROR;
- }
- LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
- }
+ if (auto_reboot) {
+ if (auto rv = EnableDsuIfNeeded(); rv != REMOUNT_SUCCESS) {
+ return rv;
}
}
- if (partitions.empty() || just_disabled_verity) {
- if (reboot_later) reboot(setup_overlayfs);
- if (user_please_reboot_later) {
+ if (partitions.empty() || check_result.disabled_verity) {
+ if (auto_reboot) {
+ reboot(check_result.setup_overlayfs);
+ }
+ if (check_result.reboot_later) {
return MUST_REBOOT;
}
LOG(WARNING) << "No partitions to remount";
@@ -442,88 +530,28 @@
// Mount overlayfs.
errno = 0;
if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
- retval = BAD_OVERLAY;
PLOG(ERROR) << "Can not mount overlayfs for partitions";
+ return BAD_OVERLAY;
}
// 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;
+ return 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);
+ if (auto rv = RemountPartition(fstab, mounts, entry); rv != REMOUNT_SUCCESS) {
+ retval = rv;
}
- auto blk_device = entry.blk_device;
- auto mount_point = entry.mount_point;
-
- auto found = false;
- for (auto it = mounts.rbegin(); it != mounts.rend(); ++it) {
- auto& rentry = *it;
- if (mount_point == rentry.mount_point) {
- blk_device = rentry.blk_device;
- found = true;
- break;
- }
- // Find overlayfs mount point?
- if ((mount_point == "/" && rentry.mount_point == "/system") ||
- (mount_point == "/system" && rentry.mount_point == "/")) {
- blk_device = rentry.blk_device;
- mount_point = "/system";
- found = true;
- break;
- }
- }
- if (!found) {
- PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
- continue;
- }
- if (blk_device == "/dev/root") {
- auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
- if (from_fstab) blk_device = from_fstab->blk_device;
- }
- fs_mgr_set_blk_ro(blk_device, false);
-
- // Find system-as-root mount point?
- if ((mount_point == "/system") && !GetEntryForMountPoint(&mounts, mount_point) &&
- GetEntryForMountPoint(&mounts, "/")) {
- mount_point = "/";
- }
-
- // 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(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
- // If errno is 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.
- if (errno == EROFS) {
- LOG(ERROR) << "Consider providing all the dependencies to enable overlayfs";
- }
- retval = REMOUNT_FAILED;
}
- if (reboot_later) reboot(setup_overlayfs);
- if (user_please_reboot_later) {
+ if (auto_reboot) reboot(check_result.setup_overlayfs);
+ if (check_result.reboot_later) {
LOG(INFO) << "Now reboot your device for settings to take effect";
- return 0;
}
-
return retval;
}
diff --git a/fs_mgr/include/fs_mgr_overlayfs.h b/fs_mgr/include/fs_mgr_overlayfs.h
index 6caab1f..21d7cd9 100644
--- a/fs_mgr/include/fs_mgr_overlayfs.h
+++ b/fs_mgr/include/fs_mgr_overlayfs.h
@@ -26,6 +26,7 @@
android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
+bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
bool* change = nullptr, bool force = true);