From 2091c878fd003857da28d7ef88248a1c060def75 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Tue, 23 Apr 2024 19:01:26 -0700 Subject: [PATCH] Support multiple partition for /data Bug: 336319772 Change-Id: I92eca566063b7d8ad74a15c7b74d809b452ace72 Signed-off-by: Jaegeuk Kim --- MetadataCrypt.cpp | 54 +++++++++++++++++++++--------------- MetadataCrypt.h | 4 +-- VoldNativeService.cpp | 12 ++++---- VoldNativeService.h | 6 ++-- binder/android/os/IVold.aidl | 4 +-- fs/F2fs.cpp | 12 ++++---- fs/F2fs.h | 3 +- model/PrivateVolume.cpp | 2 +- vdc.cpp | 44 +++++++++++++++++++++++------ 9 files changed, 90 insertions(+), 51 deletions(-) diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp index 0e2cad1..a1106fd 100644 --- a/MetadataCrypt.cpp +++ b/MetadataCrypt.cpp @@ -47,6 +47,7 @@ namespace android { namespace vold { +using android::base::Basename; using android::fs_mgr::FstabEntry; using android::fs_mgr::GetEntryForMountPoint; using android::fscrypt::GetFirstApiLevel; @@ -63,7 +64,6 @@ struct CryptoOptions { }; static const std::string kDmNameUserdata = "userdata"; -static const std::string kDmNameUserdataZoned = "userdata_zoned"; // The first entry in this table is the default crypto type. constexpr CryptoType supported_crypto_types[] = {aes_256_xts, adiantum}; @@ -153,7 +153,7 @@ static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_s static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& blk_device, const KeyBuffer& key, const CryptoOptions& options, - std::string* crypto_blkdev, uint64_t* nr_sec) { + std::string* crypto_blkdev, uint64_t* nr_sec, bool is_userdata) { if (!get_number_of_sectors(blk_device, nr_sec)) return false; // TODO(paulcrowley): don't hardcode that DmTargetDefaultKey uses 4096-byte // sectors @@ -204,7 +204,7 @@ static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& // If there are multiple partitions used for a single mount, F2FS stores // their partition paths in superblock. If the paths are dm targets, we // cannot guarantee them across device boots. Let's use the logical paths. - if (dm_name == kDmNameUserdata || dm_name == kDmNameUserdataZoned) { + if (is_userdata) { *crypto_blkdev = "/dev/block/mapper/" + dm_name; } return true; @@ -246,11 +246,16 @@ static bool parse_options(const std::string& options_string, CryptoOptions* opti bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point, bool needs_encrypt, bool should_format, - const std::string& fs_type, const std::string& zoned_device) { + const std::string& fs_type, bool is_zoned, + const std::vector& user_devices) { LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point << " encrypt: " << needs_encrypt << " format: " << should_format << " with " - << fs_type << " block device: " << blk_device - << " and zoned device: " << zoned_device; + << fs_type << " block device: " << blk_device << " with zoned " << is_zoned; + + for (auto& device : user_devices) { + LOG(DEBUG) << " - user devices: " << device; + } + auto encrypted_state = android::base::GetProperty("ro.crypto.state", ""); if (encrypted_state != "" && encrypted_state != "encrypted") { LOG(ERROR) << "fscrypt_mount_metadata_encrypted got unexpected starting state: " @@ -290,7 +295,7 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std:: } auto default_metadata_key_dir = data_rec->metadata_key_dir; - if (!zoned_device.empty()) { + if (!user_devices.empty()) { default_metadata_key_dir = default_metadata_key_dir + "/default"; } auto gen = needs_encrypt ? makeGen(options) : neverGen(); @@ -302,27 +307,28 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std:: std::string crypto_blkdev; uint64_t nr_sec; - if (!create_crypto_blk_dev(kDmNameUserdata, blk_device, key, options, &crypto_blkdev, - &nr_sec)) { + if (!create_crypto_blk_dev(kDmNameUserdata, blk_device, key, options, &crypto_blkdev, &nr_sec, + true)) { LOG(ERROR) << "create_crypto_blk_dev failed in mountFstab"; return false; } - // create dm-default-key for zoned device - std::string crypto_zoned_blkdev; - if (!zoned_device.empty()) { - auto zoned_metadata_key_dir = data_rec->metadata_key_dir + "/zoned"; + // create dm-default-key for user devices + std::vector crypto_user_blkdev; + for (auto& device : user_devices) { + std::string name = Basename(device); + auto metadata_key_dir = data_rec->metadata_key_dir + "/" + name; - if (!read_key(zoned_metadata_key_dir, gen, false, &key)) { - LOG(ERROR) << "read_key failed with zoned device: " << zoned_device; + if (!read_key(metadata_key_dir, gen, false, &key)) { + LOG(ERROR) << "read_key failed with zoned device: " << device; return false; } - if (!create_crypto_blk_dev(kDmNameUserdataZoned, zoned_device, key, options, - &crypto_zoned_blkdev, &nr_sec)) { - LOG(ERROR) << "fscrypt_mount_metadata_encrypted: failed with zoned device: " - << zoned_device; + std::string crypto_blkdev_arg; + if (!create_crypto_blk_dev(name, device, key, options, &crypto_blkdev_arg, &nr_sec, true)) { + LOG(ERROR) << "fscrypt_mount_metadata_encrypted: failed with device: " << device; return false; } + crypto_user_blkdev.push_back(crypto_blkdev_arg.c_str()); } if (needs_encrypt) { @@ -332,7 +338,7 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std:: if (fs_type == "ext4") { error = ext4::Format(crypto_blkdev, 0, mount_point); } else if (fs_type == "f2fs") { - error = f2fs::Format(crypto_blkdev, crypto_zoned_blkdev); + error = f2fs::Format(crypto_blkdev, is_zoned, crypto_user_blkdev); } else { LOG(ERROR) << "Unknown filesystem type: " << fs_type; return false; @@ -344,8 +350,9 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std:: } LOG(DEBUG) << "Format of " << crypto_blkdev << " for " << mount_point << " succeeded."; } else { - if (!zoned_device.empty()) { - LOG(ERROR) << "encrypt_inplace cannot support zoned device; should format it."; + if (!user_devices.empty()) { + LOG(ERROR) << "encrypt_inplace cannot support zoned or userdata_exp device; should " + "format it."; return false; } if (!encrypt_inplace(crypto_blkdev, blk_device, nr_sec)) { @@ -384,7 +391,8 @@ bool defaultkey_setup_ext_volume(const std::string& label, const std::string& bl CryptoOptions options; if (!get_volume_options(&options)) return false; uint64_t nr_sec; - return create_crypto_blk_dev(label, blk_device, key, options, out_crypto_blkdev, &nr_sec); + return create_crypto_blk_dev(label, blk_device, key, options, out_crypto_blkdev, &nr_sec, + false); } bool destroy_dsu_metadata_key(const std::string& dsu_slot) { diff --git a/MetadataCrypt.h b/MetadataCrypt.h index f6d6b8e..2c07a14 100644 --- a/MetadataCrypt.h +++ b/MetadataCrypt.h @@ -28,8 +28,8 @@ namespace vold { void defaultkey_precreate_dm_device(); bool fscrypt_mount_metadata_encrypted(const std::string& block_device, const std::string& mount_point, bool needs_encrypt, - bool should_format, const std::string& fs_type, - const std::string& zoned_device); + bool should_format, const std::string& fs_type, bool is_zoned, + const std::vector& user_devices); bool defaultkey_volume_keygen(KeyGeneration* gen); diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 96f4eaf..d3f2e3e 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -588,24 +588,24 @@ binder::Status VoldNativeService::initUser0() { } binder::Status VoldNativeService::mountFstab(const std::string& blkDevice, - const std::string& mountPoint, - const std::string& zonedDevice) { + const std::string& mountPoint, bool isZoned, + const std::vector& userDevices) { ENFORCE_SYSTEM_OR_ROOT; ACQUIRE_LOCK; return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false, false, - "null", zonedDevice)); + "null", isZoned, userDevices)); } binder::Status VoldNativeService::encryptFstab(const std::string& blkDevice, const std::string& mountPoint, bool shouldFormat, - const std::string& fsType, - const std::string& zonedDevice) { + const std::string& fsType, bool isZoned, + const std::vector& userDevices) { ENFORCE_SYSTEM_OR_ROOT; ACQUIRE_LOCK; return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat, - fsType, zonedDevice)); + fsType, isZoned, userDevices)); } binder::Status VoldNativeService::setStorageBindingSeed(const std::vector& seed) { diff --git a/VoldNativeService.h b/VoldNativeService.h index bb00d35..01c2e4b 100644 --- a/VoldNativeService.h +++ b/VoldNativeService.h @@ -106,10 +106,10 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status initUser0(); binder::Status mountFstab(const std::string& blkDevice, const std::string& mountPoint, - const std::string& zonedDevice); + bool isZoned, const std::vector& userDevices); binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint, - bool shouldFormat, const std::string& fsType, - const std::string& zonedDevice); + bool shouldFormat, const std::string& fsType, bool isZoned, + const std::vector& userDevices); binder::Status setStorageBindingSeed(const std::vector& seed); diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index dfccc00..d2cbecc 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -83,8 +83,8 @@ interface IVold { void fbeEnable(); void initUser0(); - void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, @utf8InCpp String zonedDevice); - void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType, @utf8InCpp String zonedDevice); + void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean isZoned, in @utf8InCpp String[] userDevices); + void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType, boolean isZoned, in @utf8InCpp String[] userDevices); void setStorageBindingSeed(in byte[] seed); diff --git a/fs/F2fs.cpp b/fs/F2fs.cpp index 07f8480..99afc32 100644 --- a/fs/F2fs.cpp +++ b/fs/F2fs.cpp @@ -71,7 +71,8 @@ status_t Mount(const std::string& source, const std::string& target) { return res; } -status_t Format(const std::string& source, const std::string& zoned_device) { +status_t Format(const std::string& source, bool is_zoned, + const std::vector& user_devices) { std::vector cmd; cmd.emplace_back(kMkfsPath); @@ -96,12 +97,13 @@ status_t Format(const std::string& source, const std::string& zoned_device) { cmd.emplace_back("-C"); cmd.emplace_back("utf8"); } - if (!zoned_device.empty()) { - cmd.emplace_back("-c"); - cmd.emplace_back(zoned_device.c_str()); + if (is_zoned) { cmd.emplace_back("-m"); } - + for (auto& device : user_devices) { + cmd.emplace_back("-c"); + cmd.emplace_back(device.c_str()); + } std::string block_size = std::to_string(getpagesize()); cmd.emplace_back("-b"); cmd.emplace_back(block_size.c_str()); diff --git a/fs/F2fs.h b/fs/F2fs.h index cdad581..7192b54 100644 --- a/fs/F2fs.h +++ b/fs/F2fs.h @@ -29,7 +29,8 @@ bool IsSupported(); status_t Check(const std::string& source); status_t Mount(const std::string& source, const std::string& target); -status_t Format(const std::string& source, const std::string& zoned_device = ""); +status_t Format(const std::string& source, const bool is_zoned, + const std::vector& user_devices); } // namespace f2fs } // namespace vold diff --git a/model/PrivateVolume.cpp b/model/PrivateVolume.cpp index 55b8d0b..bb52647 100644 --- a/model/PrivateVolume.cpp +++ b/model/PrivateVolume.cpp @@ -234,7 +234,7 @@ status_t PrivateVolume::doFormat(const std::string& fsType) { return -EIO; } } else if (resolvedFsType == "f2fs") { - if (f2fs::Format(mDmDevPath)) { + if (f2fs::Format(mDmDevPath, false, {})) { PLOG(ERROR) << getId() << " failed to format"; return -EIO; } diff --git a/vdc.cpp b/vdc.cpp index 7d72535..ee8cf9e 100644 --- a/vdc.cpp +++ b/vdc.cpp @@ -86,6 +86,38 @@ static void bindkeys(std::vector& args, const android::spsetStorageBindingSeed(seed)); } +static void mountFstab(std::vector& args, + const android::sp& vold) { + auto isZoned = android::base::ParseBool(args[4]); + if (isZoned == android::base::ParseBoolResult::kError) exit(EINVAL); + + std::vector userDevices = {}; + if (args[5] != "") { + userDevices = android::base::Split(args[5], " "); + } + checkStatus(args, + vold->mountFstab(args[2], args[3], isZoned == android::base::ParseBoolResult::kTrue, + userDevices)); +} + +static void encryptFstab(std::vector& args, + const android::sp& vold) { + auto shouldFormat = android::base::ParseBool(args[4]); + if (shouldFormat == android::base::ParseBoolResult::kError) exit(EINVAL); + + auto isZoned = android::base::ParseBool(args[6]); + if (isZoned == android::base::ParseBoolResult::kError) exit(EINVAL); + + std::vector userDevices = {}; + if (args[7] != "") { + userDevices = android::base::Split(args[7], " "); + } + checkStatus(args, + vold->encryptFstab(args[2], args[3], + shouldFormat == android::base::ParseBoolResult::kTrue, args[5], + isZoned == android::base::ParseBoolResult::kTrue, userDevices)); +} + int main(int argc, char** argv) { setenv("ANDROID_LOG_TAGS", "*:v", 1); if (getppid() == 1) { @@ -128,14 +160,10 @@ int main(int argc, char** argv) { LOG(INFO) << size; } else if (args[0] == "cryptfs" && args[1] == "bindkeys") { bindkeys(args, vold); - } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 5) { - checkStatus(args, vold->mountFstab(args[2], args[3], args[4])); - } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 7) { - auto shouldFormat = android::base::ParseBool(args[4]); - if (shouldFormat == android::base::ParseBoolResult::kError) exit(EINVAL); - checkStatus(args, vold->encryptFstab(args[2], args[3], - shouldFormat == android::base::ParseBoolResult::kTrue, - args[5], args[6])); + } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 6) { + mountFstab(args, vold); + } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 8) { + encryptFstab(args, vold); } else if (args[0] == "checkpoint" && args[1] == "supportsCheckpoint" && args.size() == 2) { bool supported = false; checkStatus(args, vold->supportsCheckpoint(&supported));