From dd20dc3128b3c719b96a297865e986991352c67b Mon Sep 17 00:00:00 2001 From: "faqiang.zhu" Date: Mon, 19 Jul 2021 12:27:37 +0800 Subject: [PATCH] Do not reboot with commit failure when ext4 userdata is wiped When userdata partition is the type of ext4, checkpoint and metadata encryption are enabled, boot up the images, if the slot currently in use is not marked as "successful" and userdata is wiped, a reboot will be triggered because of "Checkpoint commit failed" In this patch, do not create checkpoint when the preceding condition occurs, otherwise "dm-default-key" sits below "dm-bow". Because cp_needsCheckpoint(), cp_prepareCheckpoint() and cp_commitChanges() are always executed when the system boots up, and now there is a condition that BOW device is not created while the slot in use is not marked as "successful", set "isBow" to be "false" if BOW state fails to be set to 1, if "isBow" is false, then there is no need to commit the checkpoint, and the system won't automatically reboot. Bug: 193457319 Test: i.MX 8M Plus EVK, images flashed to board, misc and userdata partitions are wiped, checkpoint and metadata encryption are enabled for ext4 userdata partition. Signed-off-by: faqiang.zhu Change-Id: I4ad47a9504f1be0407f0fd196001a0e96919be33 --- Checkpoint.cpp | 5 +++-- MetadataCrypt.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Checkpoint.cpp b/Checkpoint.cpp index 948231d..4766d79 100644 --- a/Checkpoint.cpp +++ b/Checkpoint.cpp @@ -138,6 +138,7 @@ Status cp_startCheckpoint(int retry) { namespace { volatile bool isCheckpointing = false; +volatile bool isBow = true; volatile bool needsCheckpointWasCalled = false; @@ -194,7 +195,7 @@ Status cp_commitChanges() { return error(EINVAL, "Failed to remount"); } } - } else if (fstab_rec->fs_mgr_flags.checkpoint_blk) { + } else if (fstab_rec->fs_mgr_flags.checkpoint_blk && isBow) { if (!setBowState(mount_rec.blk_device, "2")) return error(EINVAL, "Failed to set bow state"); } @@ -381,7 +382,7 @@ Status cp_prepareCheckpoint() { LOG(INFO) << "Trimmed " << range.len << " bytes on " << mount_rec.mount_point << " in " << nanoseconds_to_milliseconds(time) << "ms for checkpoint"; - setBowState(mount_rec.blk_device, "1"); + isBow &= setBowState(mount_rec.blk_device, "1"); } if (fstab_rec->fs_mgr_flags.checkpoint_blk || fstab_rec->fs_mgr_flags.checkpoint_fs) { std::thread(cp_healthDaemon, std::string(mount_rec.mount_point), diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp index 91a8d62..0396138 100644 --- a/MetadataCrypt.cpp +++ b/MetadataCrypt.cpp @@ -95,7 +95,7 @@ void defaultkey_precreate_dm_device() { } } -static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) { +static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device, bool needs_encrypt) { // fs_mgr_do_mount runs fsck. Use setexeccon to run trusted // partitions in the fsck domain. if (setexeccon(android::vold::sFsckContext)) { @@ -104,7 +104,8 @@ static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) { } auto mount_rc = fs_mgr_do_mount(&fstab_default, const_cast(mount_point), const_cast(blk_device), nullptr, - android::vold::cp_needsCheckpoint(), true); + needs_encrypt? false: android::vold::cp_needsCheckpoint(), + true); if (setexeccon(nullptr)) { PLOG(ERROR) << "Failed to clear setexeccon"; return false; @@ -350,7 +351,7 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std:: } LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point; - mount_via_fs_mgr(mount_point.c_str(), crypto_blkdev.c_str()); + mount_via_fs_mgr(mount_point.c_str(), crypto_blkdev.c_str(), needs_encrypt); // Record that there's at least one fstab entry with metadata encryption if (!android::base::SetProperty("ro.crypto.metadata.enabled", "true")) {