From 2f0c6cb0f77e94e7b48a63ff843d6154618c6707 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Mon, 1 Jun 2020 12:58:04 -0700 Subject: [PATCH] Set block size in dm-bow Fix block-level checkpointing to work correctly when used in combination with 512 byte hardware sectors and metadata encryption with dm-default-key v2. Bug: 153512828 Test: Parameter is passed to dm-bow based on first_api_level Change-Id: Ic0a071221559271db20b06b2f17459b5b041e02d --- fs_mgr/fs_mgr.cpp | 24 ++++++++++++++++++++++-- fs_mgr/libdm/dm_target.cpp | 5 +++++ fs_mgr/libdm/include/libdm/dm_target.h | 5 ++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 49ca5db46..438aeb3c6 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -1094,8 +1094,28 @@ class CheckpointManager { } android::dm::DmTable table; - if (!table.AddTarget(std::make_unique( - 0, size, entry->blk_device))) { + auto bowTarget = + std::make_unique(0, size, entry->blk_device); + + // dm-bow uses the first block as a log record, and relocates the real first block + // elsewhere. For metadata encrypted devices, dm-bow sits below dm-default-key, and + // for post Android Q devices dm-default-key uses a block size of 4096 always. + // So if dm-bow's block size, which by default is the block size of the underlying + // hardware, is less than dm-default-key's, blocks will get broken up and I/O will + // fail as it won't be data_unit_size aligned. + // However, since it is possible there is an already shipping non + // metadata-encrypted device with smaller blocks, we must not change this for + // devices shipped with Q or earlier unless they explicitly selected dm-default-key + // v2 + constexpr unsigned int pre_gki_level = __ANDROID_API_Q__; + unsigned int options_format_version = android::base::GetUintProperty( + "ro.crypto.dm_default_key.options_format.version", + (android::fscrypt::GetFirstApiLevel() <= pre_gki_level ? 1 : 2)); + if (options_format_version > 1) { + bowTarget->SetBlockSize(4096); + } + + if (!table.AddTarget(std::move(bowTarget))) { LERROR << "Failed to add bow target"; return false; } diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp index 29b103282..38e4b8291 100644 --- a/fs_mgr/libdm/dm_target.cpp +++ b/fs_mgr/libdm/dm_target.cpp @@ -120,6 +120,11 @@ std::string DmTargetAndroidVerity::GetParameterString() const { return keyid_ + " " + block_device_; } +std::string DmTargetBow::GetParameterString() const { + if (!block_size_) return target_string_; + return target_string_ + " 1 block_size:" + std::to_string(block_size_); +} + std::string DmTargetSnapshot::name() const { if (mode_ == SnapshotStorageMode::Merge) { return "snapshot-merge"; diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h index 050d0b645..875efe912 100644 --- a/fs_mgr/libdm/include/libdm/dm_target.h +++ b/fs_mgr/libdm/include/libdm/dm_target.h @@ -175,11 +175,14 @@ class DmTargetBow final : public DmTarget { DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string) : DmTarget(start, length), target_string_(target_string) {} + void SetBlockSize(uint32_t block_size) { block_size_ = block_size; } + std::string name() const override { return "bow"; } - std::string GetParameterString() const override { return target_string_; } + std::string GetParameterString() const override; private: std::string target_string_; + uint32_t block_size_ = 0; }; enum class SnapshotStorageMode {