Loading fs_mgr/fs_mgr_avb.cpp +35 −124 Original line number Diff line number Diff line Loading @@ -33,11 +33,11 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <libavb/libavb.h> #include <libdm/dm.h> #include "fs_mgr.h" #include "fs_mgr_priv.h" #include "fs_mgr_priv_avb_ops.h" #include "fs_mgr_priv_dm_ioctl.h" #include "fs_mgr_priv_sha.h" static inline bool nibble_value(const char& c, uint8_t* value) { Loading Loading @@ -218,9 +218,9 @@ bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_da // Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel. // See the following link for more details: // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, static bool construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt, const std::string& root_digest, const std::string& blk_device) { const std::string& blk_device, android::dm::DmTable* table) { // Loads androidboot.veritymode from kernel cmdline. std::string verity_mode; if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) { Loading @@ -235,145 +235,56 @@ static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_ dm_verity_mode = "ignore_corruption"; } else if (verity_mode != "eio") { // Default dm_verity_mode is eio. LERROR << "Unknown androidboot.veritymode: " << verity_mode; return ""; } // dm-verity construction parameters: // <version> <dev> <hash_dev> // <data_block_size> <hash_block_size> // <num_data_blocks> <hash_start_block> // <algorithm> <digest> <salt> // [<#opt_params> <opt_params>] std::ostringstream verity_table; verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " " << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " " << hashtree_desc.image_size / hashtree_desc.data_block_size << " " << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " " << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt; // Continued from the above optional parameters: // [<#opt_params> <opt_params>] int optional_argc = 0; std::ostringstream optional_args; // dm-verity optional parameters for FEC (forward error correction): // use_fec_from_device <fec_dev> // fec_roots <num> // fec_blocks <num> // fec_start <offset> if (hashtree_desc.fec_size > 0) { // Note that fec_blocks is the size that FEC covers, *NOT* the // size of the FEC data. Since we use FEC for everything up until // the FEC data, it's the same as the offset (fec_start). optional_argc += 8; // clang-format off optional_args << "use_fec_from_device " << blk_device << " fec_roots " << hashtree_desc.fec_num_roots << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size << " "; // clang-format on } if (!dm_verity_mode.empty()) { optional_argc += 1; optional_args << dm_verity_mode << " "; return false; } // Always use ignore_zero_blocks. optional_argc += 1; optional_args << "ignore_zero_blocks"; std::ostringstream hash_algorithm; hash_algorithm << hashtree_desc.hash_algorithm; verity_table << " " << optional_argc << " " << optional_args.str(); return verity_table.str(); android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512, hashtree_desc.dm_verity_version, blk_device, blk_device, hashtree_desc.data_block_size, hashtree_desc.hash_block_size, hashtree_desc.image_size / hashtree_desc.data_block_size, hashtree_desc.tree_offset / hashtree_desc.hash_block_size, hash_algorithm.str(), root_digest, salt); if (hashtree_desc.fec_size > 0) { target.UseFec(blk_device, hashtree_desc.fec_num_roots, hashtree_desc.fec_offset / hashtree_desc.data_block_size, hashtree_desc.fec_offset / hashtree_desc.data_block_size); } static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd, uint64_t image_size, const std::string& verity_table) { fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, dm_device_name); // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. char* buffer = (char*)io; // Builds the dm_target_spec arguments. struct dm_target_spec* dm_target = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)]; io->flags = DM_READONLY_FLAG; io->target_count = 1; dm_target->status = 0; dm_target->sector_start = 0; dm_target->length = image_size / 512; strcpy(dm_target->target_type, "verity"); // Builds the verity params. char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); LINFO << "Loading verity table: '" << verity_table << "'"; // Copies verity_table to verity_params (including the terminating null byte). if (verity_table.size() > bufsize - 1) { LERROR << "Verity table size too large: " << verity_table.size() << " (max allowable size: " << bufsize - 1 << ")"; return false; if (!dm_verity_mode.empty()) { target.SetVerityMode(dm_verity_mode); } memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1); // Sets ext target boundary. verity_params += verity_table.size() + 1; verity_params = (char*)(((unsigned long)verity_params + 7) & ~7); dm_target->next = verity_params - buffer; // Always use ignore_zero_blocks. target.IgnoreZeroBlocks(); // Sends the ioctl to load the verity table. if (ioctl(fd, DM_TABLE_LOAD, io)) { PERROR << "Error loading verity table"; return false; } LINFO << "Built verity table: '" << target.GetParameterString() << "'"; return true; return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target)); } static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt, const std::string& root_digest, bool wait_for_verity_dev) { // Gets the device mapper fd. android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR)); if (fd < 0) { PERROR << "Error opening device mapper"; android::dm::DmTable table; if (!construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) || !table.valid()) { LERROR << "Failed to construct verity table."; return false; } table.set_readonly(true); // Creates the device. alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; struct dm_ioctl* io = (struct dm_ioctl*)buffer; const std::string mount_point(basename(fstab_entry->mount_point)); if (!fs_mgr_dm_create_device(io, mount_point, fd)) { android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance(); if (!dm.CreateDevice(mount_point, table)) { LERROR << "Couldn't create verity device!"; return false; } // Gets the name of the device file. std::string verity_blk_name; if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) { LERROR << "Couldn't get verity device number!"; return false; } std::string verity_table = construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device); if (verity_table.empty()) { LERROR << "Failed to construct verity table."; return false; } // Loads the verity mapping table. if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) { LERROR << "Couldn't load verity table!"; return false; } // Activates the device. if (!fs_mgr_dm_resume_table(io, mount_point, fd)) { std::string dev_path; if (!dm.GetDmDevicePathByName(mount_point, &dev_path)) { LERROR << "Couldn't get verity device path!"; return false; } Loading @@ -382,10 +293,10 @@ static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, // Updates fstab_rec->blk_device to verity device name. free(fstab_entry->blk_device); fstab_entry->blk_device = strdup(verity_blk_name.c_str()); fstab_entry->blk_device = strdup(dev_path.c_str()); // Makes sure we've set everything up properly. if (wait_for_verity_dev && !fs_mgr_wait_for_file(verity_blk_name, 1s)) { if (wait_for_verity_dev && !fs_mgr_wait_for_file(dev_path, 1s)) { return false; } Loading fs_mgr/libdm/dm_table.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ namespace android { namespace dm { bool DmTable::AddTarget(std::unique_ptr<DmTarget>&& target) { if (!target->Valid()) { return false; } targets_.push_back(std::move(target)); return true; } Loading fs_mgr/libdm/dm_target.cpp +56 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/strings.h> #include <libdm/dm.h> Loading Loading @@ -55,5 +56,60 @@ std::string DmTargetLinear::GetParameterString() const { return block_device_ + " " + std::to_string(physical_sector_); } DmTargetVerity::DmTargetVerity(uint64_t start, uint64_t length, uint32_t version, const std::string& block_device, const std::string& hash_device, uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks, uint32_t hash_start_block, const std::string& hash_algorithm, const std::string& root_digest, const std::string& salt) : DmTarget(start, length), valid_(true) { base_args_ = { std::to_string(version), block_device, hash_device, std::to_string(data_block_size), std::to_string(hash_block_size), std::to_string(num_data_blocks), std::to_string(hash_start_block), hash_algorithm, root_digest, salt, }; } void DmTargetVerity::UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start) { optional_args_.emplace_back("use_fec_from_device"); optional_args_.emplace_back(device); optional_args_.emplace_back("fec_roots"); optional_args_.emplace_back(std::to_string(num_roots)); optional_args_.emplace_back("fec_blocks"); optional_args_.emplace_back(std::to_string(num_blocks)); optional_args_.emplace_back("fec_start"); optional_args_.emplace_back(std::to_string(start)); } void DmTargetVerity::SetVerityMode(const std::string& mode) { if (mode != "restart_on_corruption" && mode != "ignore_corruption") { LOG(ERROR) << "Unknown verity mode: " << mode; valid_ = false; return; } optional_args_.emplace_back(mode); } void DmTargetVerity::IgnoreZeroBlocks() { optional_args_.emplace_back("ignore_zero_blocks"); } std::string DmTargetVerity::GetParameterString() const { std::string base = android::base::Join(base_args_, " "); if (optional_args_.empty()) { return base; } std::string optional = android::base::Join(optional_args_, " "); return base + " " + std::to_string(optional_args_.size()) + " " + optional; } } // namespace dm } // namespace android fs_mgr/libdm/dm_test.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -164,3 +164,25 @@ TEST(libdm, DmLinear) { // test should ensure that device deletion works. ASSERT_TRUE(dev.Destroy()); } TEST(libdm, DmVerityArgsAvb2) { std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a"; std::string algorithm = "sha1"; std::string digest = "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21"; std::string salt = "cc99f81ecb9484220a003b0719ee59dcf9be7e5d"; DmTargetVerity target(0, 10000, 1, device, device, 4096, 4096, 125961, 125961, algorithm, digest, salt); target.UseFec(device, 2, 126955, 126955); target.SetVerityMode("restart_on_corruption"); target.IgnoreZeroBlocks(); // Verity table from a walleye build. std::string expected = "1 /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a " "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a 4096 4096 125961 125961 sha1 " "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21 cc99f81ecb9484220a003b0719ee59dcf9be7e5d 10 " "use_fec_from_device /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a fec_roots " "2 fec_blocks 126955 fec_start 126955 restart_on_corruption ignore_zero_blocks"; EXPECT_EQ(target.GetParameterString(), expected); } fs_mgr/libdm/include/libdm/dm_target.h +25 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <stdint.h> #include <string> #include <vector> #include <android-base/logging.h> Loading Loading @@ -69,6 +70,8 @@ class DmTarget { // must implement this, for it to be used on a device. std::string Serialize() const; virtual bool Valid() const { return true; } protected: // Get the parameter string that is passed to the end of the dm_target_spec // for this target type. Loading Loading @@ -103,6 +106,28 @@ class DmTargetLinear final : public DmTarget { uint64_t physical_sector_; }; class DmTargetVerity final : public DmTarget { public: DmTargetVerity(uint64_t start, uint64_t length, uint32_t version, const std::string& block_device, const std::string& hash_device, uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks, uint32_t hash_start_block, const std::string& hash_algorithm, const std::string& root_digest, const std::string& salt); void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start); void SetVerityMode(const std::string& mode); void IgnoreZeroBlocks(); std::string name() const override { return "verity"; } std::string GetParameterString() const override; bool Valid() const override { return valid_; } private: std::vector<std::string> base_args_; std::vector<std::string> optional_args_; bool valid_; }; } // namespace dm } // namespace android Loading Loading
fs_mgr/fs_mgr_avb.cpp +35 −124 Original line number Diff line number Diff line Loading @@ -33,11 +33,11 @@ #include <android-base/strings.h> #include <android-base/unique_fd.h> #include <libavb/libavb.h> #include <libdm/dm.h> #include "fs_mgr.h" #include "fs_mgr_priv.h" #include "fs_mgr_priv_avb_ops.h" #include "fs_mgr_priv_dm_ioctl.h" #include "fs_mgr_priv_sha.h" static inline bool nibble_value(const char& c, uint8_t* value) { Loading Loading @@ -218,9 +218,9 @@ bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_da // Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel. // See the following link for more details: // https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, static bool construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt, const std::string& root_digest, const std::string& blk_device) { const std::string& blk_device, android::dm::DmTable* table) { // Loads androidboot.veritymode from kernel cmdline. std::string verity_mode; if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) { Loading @@ -235,145 +235,56 @@ static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_ dm_verity_mode = "ignore_corruption"; } else if (verity_mode != "eio") { // Default dm_verity_mode is eio. LERROR << "Unknown androidboot.veritymode: " << verity_mode; return ""; } // dm-verity construction parameters: // <version> <dev> <hash_dev> // <data_block_size> <hash_block_size> // <num_data_blocks> <hash_start_block> // <algorithm> <digest> <salt> // [<#opt_params> <opt_params>] std::ostringstream verity_table; verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " " << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " " << hashtree_desc.image_size / hashtree_desc.data_block_size << " " << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " " << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt; // Continued from the above optional parameters: // [<#opt_params> <opt_params>] int optional_argc = 0; std::ostringstream optional_args; // dm-verity optional parameters for FEC (forward error correction): // use_fec_from_device <fec_dev> // fec_roots <num> // fec_blocks <num> // fec_start <offset> if (hashtree_desc.fec_size > 0) { // Note that fec_blocks is the size that FEC covers, *NOT* the // size of the FEC data. Since we use FEC for everything up until // the FEC data, it's the same as the offset (fec_start). optional_argc += 8; // clang-format off optional_args << "use_fec_from_device " << blk_device << " fec_roots " << hashtree_desc.fec_num_roots << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size << " "; // clang-format on } if (!dm_verity_mode.empty()) { optional_argc += 1; optional_args << dm_verity_mode << " "; return false; } // Always use ignore_zero_blocks. optional_argc += 1; optional_args << "ignore_zero_blocks"; std::ostringstream hash_algorithm; hash_algorithm << hashtree_desc.hash_algorithm; verity_table << " " << optional_argc << " " << optional_args.str(); return verity_table.str(); android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512, hashtree_desc.dm_verity_version, blk_device, blk_device, hashtree_desc.data_block_size, hashtree_desc.hash_block_size, hashtree_desc.image_size / hashtree_desc.data_block_size, hashtree_desc.tree_offset / hashtree_desc.hash_block_size, hash_algorithm.str(), root_digest, salt); if (hashtree_desc.fec_size > 0) { target.UseFec(blk_device, hashtree_desc.fec_num_roots, hashtree_desc.fec_offset / hashtree_desc.data_block_size, hashtree_desc.fec_offset / hashtree_desc.data_block_size); } static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd, uint64_t image_size, const std::string& verity_table) { fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, dm_device_name); // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. char* buffer = (char*)io; // Builds the dm_target_spec arguments. struct dm_target_spec* dm_target = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)]; io->flags = DM_READONLY_FLAG; io->target_count = 1; dm_target->status = 0; dm_target->sector_start = 0; dm_target->length = image_size / 512; strcpy(dm_target->target_type, "verity"); // Builds the verity params. char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); LINFO << "Loading verity table: '" << verity_table << "'"; // Copies verity_table to verity_params (including the terminating null byte). if (verity_table.size() > bufsize - 1) { LERROR << "Verity table size too large: " << verity_table.size() << " (max allowable size: " << bufsize - 1 << ")"; return false; if (!dm_verity_mode.empty()) { target.SetVerityMode(dm_verity_mode); } memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1); // Sets ext target boundary. verity_params += verity_table.size() + 1; verity_params = (char*)(((unsigned long)verity_params + 7) & ~7); dm_target->next = verity_params - buffer; // Always use ignore_zero_blocks. target.IgnoreZeroBlocks(); // Sends the ioctl to load the verity table. if (ioctl(fd, DM_TABLE_LOAD, io)) { PERROR << "Error loading verity table"; return false; } LINFO << "Built verity table: '" << target.GetParameterString() << "'"; return true; return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target)); } static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc, const std::string& salt, const std::string& root_digest, bool wait_for_verity_dev) { // Gets the device mapper fd. android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR)); if (fd < 0) { PERROR << "Error opening device mapper"; android::dm::DmTable table; if (!construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) || !table.valid()) { LERROR << "Failed to construct verity table."; return false; } table.set_readonly(true); // Creates the device. alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; struct dm_ioctl* io = (struct dm_ioctl*)buffer; const std::string mount_point(basename(fstab_entry->mount_point)); if (!fs_mgr_dm_create_device(io, mount_point, fd)) { android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance(); if (!dm.CreateDevice(mount_point, table)) { LERROR << "Couldn't create verity device!"; return false; } // Gets the name of the device file. std::string verity_blk_name; if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) { LERROR << "Couldn't get verity device number!"; return false; } std::string verity_table = construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device); if (verity_table.empty()) { LERROR << "Failed to construct verity table."; return false; } // Loads the verity mapping table. if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) { LERROR << "Couldn't load verity table!"; return false; } // Activates the device. if (!fs_mgr_dm_resume_table(io, mount_point, fd)) { std::string dev_path; if (!dm.GetDmDevicePathByName(mount_point, &dev_path)) { LERROR << "Couldn't get verity device path!"; return false; } Loading @@ -382,10 +293,10 @@ static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, // Updates fstab_rec->blk_device to verity device name. free(fstab_entry->blk_device); fstab_entry->blk_device = strdup(verity_blk_name.c_str()); fstab_entry->blk_device = strdup(dev_path.c_str()); // Makes sure we've set everything up properly. if (wait_for_verity_dev && !fs_mgr_wait_for_file(verity_blk_name, 1s)) { if (wait_for_verity_dev && !fs_mgr_wait_for_file(dev_path, 1s)) { return false; } Loading
fs_mgr/libdm/dm_table.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ namespace android { namespace dm { bool DmTable::AddTarget(std::unique_ptr<DmTarget>&& target) { if (!target->Valid()) { return false; } targets_.push_back(std::move(target)); return true; } Loading
fs_mgr/libdm/dm_target.cpp +56 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <android-base/logging.h> #include <android-base/macros.h> #include <android-base/strings.h> #include <libdm/dm.h> Loading Loading @@ -55,5 +56,60 @@ std::string DmTargetLinear::GetParameterString() const { return block_device_ + " " + std::to_string(physical_sector_); } DmTargetVerity::DmTargetVerity(uint64_t start, uint64_t length, uint32_t version, const std::string& block_device, const std::string& hash_device, uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks, uint32_t hash_start_block, const std::string& hash_algorithm, const std::string& root_digest, const std::string& salt) : DmTarget(start, length), valid_(true) { base_args_ = { std::to_string(version), block_device, hash_device, std::to_string(data_block_size), std::to_string(hash_block_size), std::to_string(num_data_blocks), std::to_string(hash_start_block), hash_algorithm, root_digest, salt, }; } void DmTargetVerity::UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start) { optional_args_.emplace_back("use_fec_from_device"); optional_args_.emplace_back(device); optional_args_.emplace_back("fec_roots"); optional_args_.emplace_back(std::to_string(num_roots)); optional_args_.emplace_back("fec_blocks"); optional_args_.emplace_back(std::to_string(num_blocks)); optional_args_.emplace_back("fec_start"); optional_args_.emplace_back(std::to_string(start)); } void DmTargetVerity::SetVerityMode(const std::string& mode) { if (mode != "restart_on_corruption" && mode != "ignore_corruption") { LOG(ERROR) << "Unknown verity mode: " << mode; valid_ = false; return; } optional_args_.emplace_back(mode); } void DmTargetVerity::IgnoreZeroBlocks() { optional_args_.emplace_back("ignore_zero_blocks"); } std::string DmTargetVerity::GetParameterString() const { std::string base = android::base::Join(base_args_, " "); if (optional_args_.empty()) { return base; } std::string optional = android::base::Join(optional_args_, " "); return base + " " + std::to_string(optional_args_.size()) + " " + optional; } } // namespace dm } // namespace android
fs_mgr/libdm/dm_test.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -164,3 +164,25 @@ TEST(libdm, DmLinear) { // test should ensure that device deletion works. ASSERT_TRUE(dev.Destroy()); } TEST(libdm, DmVerityArgsAvb2) { std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a"; std::string algorithm = "sha1"; std::string digest = "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21"; std::string salt = "cc99f81ecb9484220a003b0719ee59dcf9be7e5d"; DmTargetVerity target(0, 10000, 1, device, device, 4096, 4096, 125961, 125961, algorithm, digest, salt); target.UseFec(device, 2, 126955, 126955); target.SetVerityMode("restart_on_corruption"); target.IgnoreZeroBlocks(); // Verity table from a walleye build. std::string expected = "1 /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a " "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a 4096 4096 125961 125961 sha1 " "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21 cc99f81ecb9484220a003b0719ee59dcf9be7e5d 10 " "use_fec_from_device /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a fec_roots " "2 fec_blocks 126955 fec_start 126955 restart_on_corruption ignore_zero_blocks"; EXPECT_EQ(target.GetParameterString(), expected); }
fs_mgr/libdm/include/libdm/dm_target.h +25 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <stdint.h> #include <string> #include <vector> #include <android-base/logging.h> Loading Loading @@ -69,6 +70,8 @@ class DmTarget { // must implement this, for it to be used on a device. std::string Serialize() const; virtual bool Valid() const { return true; } protected: // Get the parameter string that is passed to the end of the dm_target_spec // for this target type. Loading Loading @@ -103,6 +106,28 @@ class DmTargetLinear final : public DmTarget { uint64_t physical_sector_; }; class DmTargetVerity final : public DmTarget { public: DmTargetVerity(uint64_t start, uint64_t length, uint32_t version, const std::string& block_device, const std::string& hash_device, uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks, uint32_t hash_start_block, const std::string& hash_algorithm, const std::string& root_digest, const std::string& salt); void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start); void SetVerityMode(const std::string& mode); void IgnoreZeroBlocks(); std::string name() const override { return "verity"; } std::string GetParameterString() const override; bool Valid() const override { return valid_; } private: std::vector<std::string> base_args_; std::vector<std::string> optional_args_; bool valid_; }; } // namespace dm } // namespace android Loading