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 <faqiang.zhu@nxp.com>
Change-Id: I4ad47a9504f1be0407f0fd196001a0e96919be33
This commit is contained in:
faqiang.zhu 2021-07-19 12:27:37 +08:00 committed by Keith Mok
parent 0777c5d604
commit dd20dc3128
2 changed files with 7 additions and 5 deletions

View file

@ -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),

View file

@ -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<char*>(mount_point),
const_cast<char*>(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")) {