Merge "set-verity-state: Simplify code path around overlayfs_setup()"
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 deaf5f7..c47d110 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -43,6 +43,8 @@
#include <libgsi/libgsid.h>
using namespace std::literals;
+using android::fs_mgr::Fstab;
+using android::fs_mgr::FstabEntry;
namespace {
@@ -62,22 +64,12 @@
::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) {
+const FstabEntry* GetWrappedEntry(const Fstab& overlayfs_candidates, const 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) {
@@ -147,9 +139,290 @@
CLEAN_SCRATCH_FILES,
};
-static int do_remount(int argc, char* argv[]) {
- RemountStatus retval = REMOUNT_SUCCESS;
+static bool ReadFstab(const char* fstab_file, android::fs_mgr::Fstab* fstab) {
+ if (fstab_file) {
+ return android::fs_mgr::ReadFstabFromFile(fstab_file, fstab);
+ }
+ if (!android::fs_mgr::ReadDefaultFstab(fstab)) {
+ return false;
+ }
+ // Manufacture a / entry from /proc/mounts if missing.
+ if (!GetEntryForMountPoint(fstab, "/system") && !GetEntryForMountPoint(fstab, "/")) {
+ android::fs_mgr::Fstab mounts;
+ if (android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
+ if (auto entry = GetEntryForMountPoint(&mounts, "/")) {
+ if (entry->fs_type != "rootfs") fstab->emplace_back(*entry);
+ }
+ }
+ }
+ return true;
+}
+
+static RemountStatus VerifyCheckpointing() {
+ if (!android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
+ !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
+ return REMOUNT_SUCCESS;
+ }
+
+ // Virtual A/B devices can use /data as backing storage; make sure we're
+ // not checkpointing.
+ auto vold = GetVold();
+ bool checkpointing = false;
+ if (!vold->isCheckpointing(&checkpointing).isOk()) {
+ LOG(ERROR) << "Could not determine checkpointing status.";
+ return BINDER_ERROR;
+ }
+ if (checkpointing) {
+ LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
+ return CHECKPOINTING;
+ }
+ return REMOUNT_SUCCESS;
+}
+
+static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
+ if (entry.fs_mgr_flags.vold_managed || entry.fs_mgr_flags.recovery_only ||
+ entry.fs_mgr_flags.slot_select_other) {
+ return false;
+ }
+ if (!(entry.flags & MS_RDONLY)) {
+ return false;
+ }
+ if (entry.fs_type == "vfat") {
+ return false;
+ }
+ if (GetEntryForMountPoint(&candidates, entry.mount_point)) {
+ return true;
+ }
+ if (GetWrappedEntry(candidates, entry)) {
+ return false;
+ }
+ return true;
+}
+
+static Fstab::const_iterator FindPartition(const Fstab& fstab, const std::string& partition) {
+ for (auto iter = fstab.begin(); iter != fstab.end(); iter++) {
+ const auto mount_point = system_mount_point(*iter);
+ if (partition == mount_point) {
+ return iter;
+ }
+ if (partition == android::base::Basename(mount_point)) {
+ return iter;
+ }
+ }
+ return fstab.end();
+}
+
+static Fstab GetAllRemountablePartitions(Fstab& fstab) {
+ auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
+
+ Fstab partitions;
+ for (const auto& entry : fstab) {
+ if (IsRemountable(candidates, entry)) {
+ partitions.emplace_back(entry);
+ }
+ }
+ return partitions;
+}
+
+static RemountStatus GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv,
+ Fstab* partitions) {
+ auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
+
+ for (const auto& arg : argv) {
+ std::string partition = arg;
+ if (partition == "/") {
+ partition = "/system";
+ }
+
+ auto it = FindPartition(fstab, partition);
+ if (it == fstab.end()) {
+ LOG(ERROR) << "Unknown partition " << arg;
+ return UNKNOWN_PARTITION;
+ }
+
+ const FstabEntry* entry = &*it;
+ if (auto wrap = GetWrappedEntry(candidates, *entry); wrap != nullptr) {
+ LOG(INFO) << "partition " << arg << " covered by overlayfs for " << wrap->mount_point
+ << ", switching";
+ entry = wrap;
+ }
+
+ if (!IsRemountable(candidates, *entry)) {
+ LOG(ERROR) << "Invalid partition " << arg;
+ return INVALID_PARTITION;
+ }
+ if (GetEntryForMountPoint(partitions, entry->mount_point) != nullptr) {
+ continue;
+ }
+ partitions->emplace_back(*entry);
+ }
+
+ return 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.
@@ -160,6 +433,7 @@
const char* fstab_file = nullptr;
auto can_reboot = false;
+ std::vector<std::string> partition_args;
struct option longopts[] = {
{"fstab", required_argument, nullptr, 'T'},
@@ -196,6 +470,10 @@
}
}
+ for (; argc > optind; ++optind) {
+ partition_args.emplace_back(argv[optind]);
+ }
+
// Make sure we are root.
if (::getuid() != 0) {
LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
@@ -203,191 +481,46 @@
}
// 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);
- // Manufacture a / entry from /proc/mounts if missing.
- if (!GetEntryForMountPoint(&fstab, "/system") && !GetEntryForMountPoint(&fstab, "/")) {
- android::fs_mgr::Fstab mounts;
- if (android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
- if (auto entry = GetEntryForMountPoint(&mounts, "/")) {
- if (entry->fs_type != "rootfs") fstab.emplace_back(*entry);
- }
- }
- }
- }
- if (!fstab_read || fstab.empty()) {
+ Fstab fstab;
+ if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
PLOG(ERROR) << "Failed to read fstab";
return NO_FSTAB;
}
- if (android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
- !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
- // Virtual A/B devices can use /data as backing storage; make sure we're
- // not checkpointing.
- auto vold = GetVold();
- bool checkpointing = false;
- if (!vold->isCheckpointing(&checkpointing).isOk()) {
- LOG(ERROR) << "Could not determine checkpointing status.";
- return BINDER_ERROR;
- }
- if (checkpointing) {
- LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
- return CHECKPOINTING;
- }
+ if (auto rv = VerifyCheckpointing(); rv != REMOUNT_SUCCESS) {
+ return rv;
}
- // 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 all;
- 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)) {
- all.emplace_back(entry);
+ Fstab partitions;
+ if (partition_args.empty()) {
+ partitions = GetAllRemountablePartitions(fstab);
+ } else {
+ if (auto rv = GetRemountList(fstab, partition_args, &partitions); rv != REMOUNT_SUCCESS) {
+ return rv;
}
}
- // Parse the unique list of valid partition arguments.
- android::fs_mgr::Fstab partitions;
- for (; argc > optind; ++optind) {
- auto partition = std::string(argv[optind]);
- if (partition.empty()) continue;
- if (partition == "/") partition = "/system";
- auto find_part = [&partition](const auto& entry) {
- const auto mount_point = system_mount_point(entry);
- if (partition == mount_point) return true;
- if (partition == android::base::Basename(mount_point)) return true;
- return false;
- };
- // Do we know about the partition?
- auto it = std::find_if(fstab.begin(), fstab.end(), find_part);
- if (it == fstab.end()) {
- LOG(ERROR) << "Unknown partition " << argv[optind] << ", skipping";
- retval = UNKNOWN_PARTITION;
- continue;
- }
- // Is that one covered by an existing overlayfs?
- auto wrap = is_wrapped(overlayfs_candidates, *it);
- if (wrap) {
- LOG(INFO) << "partition " << argv[optind] << " covered by overlayfs for "
- << wrap->mount_point << ", switching";
- partition = system_mount_point(*wrap);
- }
- // Is it a remountable partition?
- it = std::find_if(all.begin(), all.end(), find_part);
- if (it == all.end()) {
- LOG(ERROR) << "Invalid partition " << argv[optind] << ", skipping";
- retval = INVALID_PARTITION;
- continue;
- }
- if (GetEntryForMountPoint(&partitions, it->mount_point) == nullptr) {
- partitions.emplace_back(*it);
- }
- }
-
- if (partitions.empty() && !retval) {
- partitions = all;
- }
-
// 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";
@@ -397,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);
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index 653492c..c8a0249 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -38,7 +38,7 @@
: fd_(-1),
header_(),
fd_size_(0),
- merge_op_blocks_(std::make_shared<std::vector<uint32_t>>()),
+ block_pos_index_(std::make_shared<std::vector<int>>()),
reader_flag_(reader_flag) {}
static void SHA256(const void*, size_t, uint8_t[]) {
@@ -58,13 +58,12 @@
cow->fd_size_ = fd_size_;
cow->last_label_ = last_label_;
cow->ops_ = ops_;
- cow->merge_op_blocks_ = merge_op_blocks_;
cow->merge_op_start_ = merge_op_start_;
- cow->block_map_ = block_map_;
cow->num_total_data_ops_ = num_total_data_ops_;
cow->num_ordered_ops_to_merge_ = num_ordered_ops_to_merge_;
cow->has_seq_ops_ = has_seq_ops_;
cow->data_loc_ = data_loc_;
+ cow->block_pos_index_ = block_pos_index_;
return cow;
}
@@ -415,10 +414,10 @@
// Replace-op-4, Zero-op-9, Replace-op-5 }
//==============================================================
bool CowReader::PrepMergeOps() {
- auto merge_op_blocks = std::make_shared<std::vector<uint32_t>>();
+ auto merge_op_blocks = std::make_unique<std::vector<uint32_t>>();
std::vector<int> other_ops;
auto seq_ops_set = std::unordered_set<uint32_t>();
- auto block_map = std::make_shared<std::unordered_map<uint32_t, int>>();
+ auto block_map = std::make_unique<std::unordered_map<uint32_t, int>>();
size_t num_seqs = 0;
size_t read;
@@ -477,13 +476,18 @@
merge_op_blocks->insert(merge_op_blocks->end(), other_ops.begin(), other_ops.end());
+ for (auto block : *merge_op_blocks) {
+ block_pos_index_->push_back(block_map->at(block));
+ }
+
num_total_data_ops_ = merge_op_blocks->size();
if (header_.num_merge_ops > 0) {
merge_op_start_ = header_.num_merge_ops;
}
- block_map_ = block_map;
- merge_op_blocks_ = merge_op_blocks;
+ block_map->clear();
+ merge_op_blocks->clear();
+
return true;
}
@@ -589,9 +593,7 @@
class CowRevMergeOpIter final : public ICowOpIter {
public:
explicit CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
- std::shared_ptr<std::unordered_map<uint32_t, int>> map,
- uint64_t start);
+ std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
bool Done() override;
const CowOperation& Get() override;
@@ -602,17 +604,15 @@
private:
std::shared_ptr<std::vector<CowOperation>> ops_;
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks_;
- std::shared_ptr<std::unordered_map<uint32_t, int>> map_;
- std::vector<uint32_t>::reverse_iterator block_riter_;
+ std::vector<int>::reverse_iterator block_riter_;
+ std::shared_ptr<std::vector<int>> cow_op_index_vec_;
uint64_t start_;
};
class CowMergeOpIter final : public ICowOpIter {
public:
explicit CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
- std::shared_ptr<std::unordered_map<uint32_t, int>> map, uint64_t start);
+ std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start);
bool Done() override;
const CowOperation& Get() override;
@@ -623,26 +623,21 @@
private:
std::shared_ptr<std::vector<CowOperation>> ops_;
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks_;
- std::shared_ptr<std::unordered_map<uint32_t, int>> map_;
- std::vector<uint32_t>::iterator block_iter_;
+ std::vector<int>::iterator block_iter_;
+ std::shared_ptr<std::vector<int>> cow_op_index_vec_;
uint64_t start_;
};
CowMergeOpIter::CowMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
- std::shared_ptr<std::unordered_map<uint32_t, int>> map,
- uint64_t start) {
+ std::shared_ptr<std::vector<int>> block_pos_index, uint64_t start) {
ops_ = ops;
- merge_op_blocks_ = merge_op_blocks;
- map_ = map;
start_ = start;
-
- block_iter_ = merge_op_blocks->begin() + start;
+ cow_op_index_vec_ = block_pos_index;
+ block_iter_ = cow_op_index_vec_->begin() + start;
}
bool CowMergeOpIter::RDone() {
- return block_iter_ == merge_op_blocks_->begin();
+ return block_iter_ == cow_op_index_vec_->begin();
}
void CowMergeOpIter::Prev() {
@@ -651,7 +646,7 @@
}
bool CowMergeOpIter::Done() {
- return block_iter_ == merge_op_blocks_->end();
+ return block_iter_ == cow_op_index_vec_->end();
}
void CowMergeOpIter::Next() {
@@ -661,23 +656,20 @@
const CowOperation& CowMergeOpIter::Get() {
CHECK(!Done());
- return ops_->data()[map_->at(*block_iter_)];
+ return ops_->data()[*block_iter_];
}
CowRevMergeOpIter::CowRevMergeOpIter(std::shared_ptr<std::vector<CowOperation>> ops,
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks,
- std::shared_ptr<std::unordered_map<uint32_t, int>> map,
+ std::shared_ptr<std::vector<int>> block_pos_index,
uint64_t start) {
ops_ = ops;
- merge_op_blocks_ = merge_op_blocks;
- map_ = map;
start_ = start;
-
- block_riter_ = merge_op_blocks->rbegin();
+ cow_op_index_vec_ = block_pos_index;
+ block_riter_ = cow_op_index_vec_->rbegin();
}
bool CowRevMergeOpIter::RDone() {
- return block_riter_ == merge_op_blocks_->rbegin();
+ return block_riter_ == cow_op_index_vec_->rbegin();
}
void CowRevMergeOpIter::Prev() {
@@ -686,7 +678,7 @@
}
bool CowRevMergeOpIter::Done() {
- return block_riter_ == merge_op_blocks_->rend() - start_;
+ return block_riter_ == cow_op_index_vec_->rend() - start_;
}
void CowRevMergeOpIter::Next() {
@@ -696,7 +688,7 @@
const CowOperation& CowRevMergeOpIter::Get() {
CHECK(!Done());
- return ops_->data()[map_->at(*block_riter_)];
+ return ops_->data()[*block_riter_];
}
std::unique_ptr<ICowOpIter> CowReader::GetOpIter() {
@@ -704,12 +696,12 @@
}
std::unique_ptr<ICowOpIter> CowReader::GetRevMergeOpIter(bool ignore_progress) {
- return std::make_unique<CowRevMergeOpIter>(ops_, merge_op_blocks_, block_map_,
+ return std::make_unique<CowRevMergeOpIter>(ops_, block_pos_index_,
ignore_progress ? 0 : merge_op_start_);
}
std::unique_ptr<ICowOpIter> CowReader::GetMergeOpIter(bool ignore_progress) {
- return std::make_unique<CowMergeOpIter>(ops_, merge_op_blocks_, block_map_,
+ return std::make_unique<CowMergeOpIter>(ops_, block_pos_index_,
ignore_progress ? 0 : merge_op_start_);
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index f4d5c72..fbdd6b9 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -170,9 +170,8 @@
uint64_t fd_size_;
std::optional<uint64_t> last_label_;
std::shared_ptr<std::vector<CowOperation>> ops_;
- std::shared_ptr<std::vector<uint32_t>> merge_op_blocks_;
uint64_t merge_op_start_{};
- std::shared_ptr<std::unordered_map<uint32_t, int>> block_map_;
+ std::shared_ptr<std::vector<int>> block_pos_index_;
uint64_t num_total_data_ops_{};
uint64_t num_ordered_ops_to_merge_{};
bool has_seq_ops_{};
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 4ffa98d..a3ef131 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -22,6 +22,10 @@
name: "libstatspull_bindgen",
wrapper_src: "statslog.h",
crate_name: "statspull_bindgen",
+ visibility: [
+ "//frameworks/proto_logging/stats/stats_log_api_gen",
+ "//packages/modules/Virtualization/libs/statslog_virtualization",
+ ],
source_stem: "bindings",
bindgen_flags: [
"--size_t-is-usize",
@@ -48,7 +52,7 @@
apex_available: [
"//apex_available:platform",
"com.android.virt",
- ]
+ ],
}
rust_library {
diff --git a/set-verity-state/OWNERS b/set-verity-state/OWNERS
new file mode 100644
index 0000000..e849450
--- /dev/null
+++ b/set-verity-state/OWNERS
@@ -0,0 +1,3 @@
+dvander@google.com
+yochiang@google.com
+bowgotsai@google.com
diff --git a/trusty/OWNERS b/trusty/OWNERS
index 5c4e03a..61b97c6 100644
--- a/trusty/OWNERS
+++ b/trusty/OWNERS
@@ -1,9 +1,11 @@
armellel@google.com
arve@android.com
+danielangell@google.com
gmar@google.com
marcone@google.com
mmaurer@google.com
ncbray@google.com
swillden@google.com
+thurston@google.com
trong@google.com
wenhaowang@google.com
diff --git a/trusty/storage/interface/include/trusty/interface/storage.h b/trusty/storage/interface/include/trusty/interface/storage.h
index 3f1dcb8..255ade1 100644
--- a/trusty/storage/interface/include/trusty/interface/storage.h
+++ b/trusty/storage/interface/include/trusty/interface/storage.h
@@ -70,6 +70,9 @@
* @STORAGE_ERR_TRANSACT returned by various operations to indicate that current transaction
* is in error state. Such state could be only cleared by sending
* STORAGE_END_TRANSACTION message.
+ * @STORAGE_ERR_SYNC_FAILURE indicates that the current operation failed to sync
+ * to disk. Only returned if STORAGE_MSG_FLAG_PRE_COMMIT or
+ * STORAGE_MSG_FLAG_POST_COMMIT was set for the request.
*/
enum storage_err {
STORAGE_NO_ERROR = 0,
@@ -80,6 +83,7 @@
STORAGE_ERR_NOT_FOUND = 5,
STORAGE_ERR_EXIST = 6,
STORAGE_ERR_TRANSACT = 7,
+ STORAGE_ERR_SYNC_FAILURE = 8,
};
/**
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index 7cbc24f..b970406 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -73,10 +73,11 @@
static int handle_req(struct storage_msg* msg, const void* req, size_t req_len) {
int rc;
- if ((msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) && (msg->cmd != STORAGE_RPMB_SEND)) {
+ if ((msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) && msg->cmd != STORAGE_RPMB_SEND &&
+ msg->cmd != STORAGE_FILE_WRITE) {
/*
- * handling post commit messages on non rpmb commands are not
- * implemented as there is no use case for this yet.
+ * handling post commit messages on commands other than rpmb and write
+ * operations are not implemented as there is no use case for this yet.
*/
ALOGE("cmd 0x%x: post commit option is not implemented\n", msg->cmd);
msg->result = STORAGE_ERR_UNIMPLEMENTED;
@@ -86,7 +87,7 @@
if (msg->flags & STORAGE_MSG_FLAG_PRE_COMMIT) {
rc = storage_sync_checkpoint();
if (rc < 0) {
- msg->result = STORAGE_ERR_GENERIC;
+ msg->result = STORAGE_ERR_SYNC_FAILURE;
return ipc_respond(msg, NULL, 0);
}
}
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index c00c399..c531cfd 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -407,6 +407,14 @@
goto err_response;
}
+ if (msg->flags & STORAGE_MSG_FLAG_POST_COMMIT) {
+ rc = storage_sync_checkpoint();
+ if (rc < 0) {
+ msg->result = STORAGE_ERR_SYNC_FAILURE;
+ goto err_response;
+ }
+ }
+
msg->result = STORAGE_NO_ERROR;
err_response: