From c1f9cbaf8d627a86209f3afbf5754cb4d470c693 Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Wed, 5 Apr 2017 00:02:33 +0800 Subject: [PATCH 1/5] fs_mgr: adding fs_mgr_get_slot_suffix() public API The function returns "_a" or "_b" based on two possible values in kernel cmdline: - androidboot.slot = a or b OR - androidboot.slot_suffix = _a or _b Bug: 33254008 Bug: 36533366 Test: boot sailfish Change-Id: Ia0a524e4145ebf61af5821f42ecad212c95ed748 Merged-In: Ia0a524e4145ebf61af5821f42ecad212c95ed748 (cherry picked from commit 87d0836cda90b33ee97d63ef61a10dd23d82581a) --- fs_mgr/fs_mgr_avb.cpp | 12 +++------- fs_mgr/fs_mgr_fstab.cpp | 2 +- fs_mgr/fs_mgr_priv.h | 6 +---- fs_mgr/fs_mgr_slotselect.cpp | 46 ++++++++++++++++++++++-------------- fs_mgr/include/fs_mgr.h | 16 +++++++++---- 5 files changed, 45 insertions(+), 37 deletions(-) diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 7512eb934..3576b9caa 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -489,15 +489,9 @@ int fs_mgr_load_vbmeta_images(struct fstab* fstab) { // Sets requested_partitions to nullptr as it's to copy the contents // of HASH partitions into fs_mgr_avb_verify_data, which is not required as // fs_mgr only deals with HASHTREE partitions. - const char *requested_partitions[] = {nullptr}; - std::string ab_suffix; - std::string slot; - if (fs_mgr_get_boot_config("slot", &slot)) { - ab_suffix = "_" + slot; - } else { - // remove slot_suffix once bootloaders update to new androidboot.slot param - fs_mgr_get_boot_config("slot_suffix", &ab_suffix); - } + const char* requested_partitions[] = {nullptr}; + std::string ab_suffix = fs_mgr_get_slot_suffix(); + AvbSlotVerifyResult verify_result = avb_slot_verify(fs_mgr_avb_ops, requested_partitions, ab_suffix.c_str(), fs_mgr_vbmeta_prop.allow_verification_error, &fs_mgr_avb_verify_data); diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index a9a0df79e..c231a23c9 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -572,7 +572,7 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) cnt++; } /* If an A/B partition, modify block device to be the real block device */ - if (fs_mgr_update_for_slotselect(fstab) != 0) { + if (!fs_mgr_update_for_slotselect(fstab)) { LERROR << "Error updating for slotselect"; goto err; } diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 377d2ecb0..dedffd8d1 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -41,8 +41,6 @@ #define PWARNING PLOG(WARNING) << FS_MGR_TAG #define PERROR PLOG(ERROR) << FS_MGR_TAG -__BEGIN_DECLS - #define CRYPTO_TMPFS_OPTIONS "size=256m,mode=0771,uid=1000,gid=1000" #define WAIT_TIMEOUT 20 @@ -114,10 +112,8 @@ __BEGIN_DECLS int fs_mgr_set_blk_ro(const char *blockdev); int fs_mgr_test_access(const char *device); -int fs_mgr_update_for_slotselect(struct fstab *fstab); +bool fs_mgr_update_for_slotselect(struct fstab *fstab); bool is_dt_compatible(); bool is_device_secure(); -__END_DECLS - #endif /* __CORE_FS_MGR_PRIV_H */ diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp index 7a4547334..9ca15e237 100644 --- a/fs_mgr/fs_mgr_slotselect.cpp +++ b/fs_mgr/fs_mgr_slotselect.cpp @@ -16,37 +16,47 @@ #include +#include + #include "fs_mgr.h" #include "fs_mgr_priv.h" -// Updates |fstab| for slot_suffix. Returns 0 on success, -1 on error. -int fs_mgr_update_for_slotselect(struct fstab *fstab) -{ +// Returns "_a" or "_b" based on two possible values in kernel cmdline: +// - androidboot.slot = a or b OR +// - androidboot.slot_suffix = _a or _b +// TODO: remove slot_suffix once it's deprecated. +std::string fs_mgr_get_slot_suffix() { + std::string slot; + std::string ab_suffix; + + if (fs_mgr_get_boot_config("slot", &slot)) { + ab_suffix = "_" + slot; + } else if (!fs_mgr_get_boot_config("slot_suffix", &ab_suffix)) { + ab_suffix = ""; + } + return ab_suffix; +} + +// Updates |fstab| for slot_suffix. Returns true on success, false on error. +bool fs_mgr_update_for_slotselect(struct fstab *fstab) { int n; - int got_suffix = 0; - std::string suffix; + std::string ab_suffix; for (n = 0; n < fstab->num_entries; n++) { if (fstab->recs[n].fs_mgr_flags & MF_SLOTSELECT) { char *tmp; - - if (!got_suffix) { - std::string slot; - if (fs_mgr_get_boot_config("slot", &slot)) { - suffix = "_" + slot; - } else if (!fs_mgr_get_boot_config("slot_suffix", &suffix)) { - // remove slot_suffix once bootloaders update to new androidboot.slot param - return -1; - } + if (ab_suffix.empty()) { + ab_suffix = fs_mgr_get_slot_suffix(); + // Returns false as non A/B devices should not have MF_SLOTSELECT. + if (ab_suffix.empty()) return false; } - - if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device, suffix.c_str()) > 0) { + if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device, ab_suffix.c_str()) > 0) { free(fstab->recs[n].blk_device); fstab->recs[n].blk_device = tmp; } else { - return -1; + return false; } } } - return 0; + return true; } diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 2fd5f65a4..ec6a415f6 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -22,6 +22,12 @@ #include #include +// C++ only headers +// TODO: move this into separate header files under include/fs_mgr/*.h +#ifdef __cplusplus +#include +#endif + // Magic number at start of verity metadata #define VERITY_METADATA_MAGIC_NUMBER 0xb001b001 @@ -29,9 +35,7 @@ // turn verity off in userdebug builds. #define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF" -#ifdef __cplusplus -extern "C" { -#endif +__BEGIN_DECLS // Verity modes enum verity_mode { @@ -142,8 +146,12 @@ int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer); #define FS_MGR_SETUP_VERITY_SUCCESS 0 int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev); +__END_DECLS + +// C++ only functions +// TODO: move this into separate header files under include/fs_mgr/*.h #ifdef __cplusplus -} +std::string fs_mgr_get_slot_suffix(); #endif #endif /* __CORE_FS_MGR_H */ From 4ae3e510b34bbe5e0240afd7113025b2b3531cb0 Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Thu, 30 Mar 2017 18:42:54 +0800 Subject: [PATCH 2/5] fs_mgr_avb: refactors how vbmeta is loaded Adds two classes FsManagerAvbhandle and FsManagerAvbVerifier to replace the following functions or struct: - fs_mgr_load_vbmeta_images() -> FsManagerAvbhandle::Open() - fs_mgr_unload_vbmeta_images() -> deleted - fs_mgr_setup_avb() -> FsManagerAvbhandle::SetUpAvb() - androidboot_vbmeta -> FsManagerAvbVerifier - load_vbmeta_prop() -> FsManagerAvbVerifier::Create() - verify_vbmeta_images() -> FsManagerAvbVerifier::VerifyVbmetaImages() And only invokes FsManagerAvbhandle::Open() when there is a fstab entry having 'avb' flag (need HASHTREE descriptor). fs_mgr_is_avb_used() can be removed as it only checks system property "ro.boot.vbmeta.hash_alg" to decide whether vbmeta needs to be loaded, which might not be accurate. For example, there are only HASH descriptors in the verified chain but no HASHTREE descriptors. In this case, the fs_mgr doesn't have to do anything because it only takes care of HASHTREE descriptors. Also adds a new class FsManagerAvbOps to provide the C++ binding FsManagerAvbOps::AvbSlotVerify() for libavb->avb_slot_verify(). Bug: 33254008 Test: test AVB on bullhead Change-Id: I8fe15ba01c277152630a2a5c1c5c7f25fbf34030 Merged-In: I8fe15ba01c277152630a2a5c1c5c7f25fbf34030 (cherry picked from commit 95c966a8599a069c40707c933c31155d625bd355) --- fs_mgr/fs_mgr.cpp | 76 ++++++----- fs_mgr/fs_mgr_avb.cpp | 260 +++++++++++++++++--------------------- fs_mgr/fs_mgr_avb_ops.cpp | 190 ++++++++++++---------------- fs_mgr/fs_mgr_avb_ops.h | 49 +++---- fs_mgr/fs_mgr_priv_avb.h | 89 +++++++++---- fs_mgr/fs_mgr_priv_sha.h | 12 +- 6 files changed, 335 insertions(+), 341 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 120129c50..78d0c070f 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -707,6 +707,23 @@ static int handle_encryptable(const struct fstab_rec* rec) } } +static std::string extract_by_name_prefix(struct fstab* fstab) { + // We assume that there's an entry for the /misc mount point in the + // fstab file and use that to get the device file by-name prefix. + // The device needs not to have an actual /misc partition. + // e.g., + // - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc -> + // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ + struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc"); + if (fstab_entry == nullptr) { + LERROR << "/misc mount point not found in fstab"; + return ""; + } + std::string full_path(fstab_entry->blk_device); + size_t end_slash = full_path.find_last_of("/"); + return full_path.substr(0, end_slash + 1); +} + // TODO: add ueventd notifiers if they don't exist. // This is just doing a wait_for_device for maximum of 1s int fs_mgr_test_access(const char *device) { @@ -750,17 +767,12 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) int mret = -1; int mount_errno = 0; int attempted_idx = -1; - int avb_ret = FS_MGR_SETUP_AVB_FAIL; + FsManagerAvbUniquePtr avb_handle(nullptr); if (!fstab) { return -1; } - if (fs_mgr_is_avb_used() && - (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) { - return -1; - } - for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold or not for the mount mode*/ if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) || @@ -799,16 +811,15 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } - if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) { - /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we - * should set up the device without using dm-verity. - * The actual mounting still take place in the following - * mount_with_alternatives(). - */ - if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) { - LINFO << "AVB HASHTREE disabled"; - } else if (fs_mgr_setup_avb(&fstab->recs[i]) != - FS_MGR_SETUP_AVB_SUCCESS) { + if (fstab->recs[i].fs_mgr_flags & MF_AVB) { + if (!avb_handle) { + avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab)); + if (!avb_handle) { + LERROR << "Failed to open FsManagerAvbHandle"; + return -1; + } + } + if (!avb_handle->SetUpAvb(&fstab->recs[i])) { LERROR << "Failed to set up AVB on partition: " << fstab->recs[i].mount_point << ", skipping!"; /* Skips mounting the device. */ @@ -934,10 +945,6 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } - if (fs_mgr_is_avb_used()) { - fs_mgr_unload_vbmeta_images(); - } - if (error_count) { return -1; } else { @@ -976,17 +983,12 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, int mount_errors = 0; int first_mount_errno = 0; char *m; - int avb_ret = FS_MGR_SETUP_AVB_FAIL; + FsManagerAvbUniquePtr avb_handle(nullptr); if (!fstab) { return ret; } - if (fs_mgr_is_avb_used() && - (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) { - return ret; - } - for (i = 0; i < fstab->num_entries; i++) { if (!fs_match(fstab->recs[i].mount_point, n_name)) { continue; @@ -1021,16 +1023,15 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i], &fs_stat); } - if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) { - /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we - * should set up the device without using dm-verity. - * The actual mounting still take place in the following - * mount_with_alternatives(). - */ - if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) { - LINFO << "AVB HASHTREE disabled"; - } else if (fs_mgr_setup_avb(&fstab->recs[i]) != - FS_MGR_SETUP_AVB_SUCCESS) { + if (fstab->recs[i].fs_mgr_flags & MF_AVB) { + if (!avb_handle) { + avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab)); + if (!avb_handle) { + LERROR << "Failed to open FsManagerAvbHandle"; + return -1; + } + } + if (!avb_handle->SetUpAvb(&fstab->recs[i])) { LERROR << "Failed to set up AVB on partition: " << fstab->recs[i].mount_point << ", skipping!"; /* Skips mounting the device. */ @@ -1079,9 +1080,6 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, } out: - if (fs_mgr_is_avb_used()) { - fs_mgr_unload_vbmeta_images(); - } return ret; } diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 3576b9caa..76ec236b5 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -85,24 +86,6 @@ hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_start */ \ VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART -AvbSlotVerifyData* fs_mgr_avb_verify_data = nullptr; -AvbOps* fs_mgr_avb_ops = nullptr; - -enum HashAlgorithm { - kInvalid = 0, - kSHA256 = 1, - kSHA512 = 2, -}; - -struct androidboot_vbmeta { - HashAlgorithm hash_alg; - uint8_t digest[SHA512_DIGEST_LENGTH]; - size_t vbmeta_size; - bool allow_verification_error; -}; - -androidboot_vbmeta fs_mgr_vbmeta_prop; - static inline bool nibble_value(const char& c, uint8_t* value) { FS_MGR_CHECK(value != nullptr); @@ -159,27 +142,78 @@ static std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) { return hex; } -static bool load_vbmeta_prop(androidboot_vbmeta* vbmeta_prop) { - FS_MGR_CHECK(vbmeta_prop != nullptr); +template +static std::pair verify_vbmeta_digest(const AvbSlotVerifyData& verify_data, + const uint8_t* expected_digest) { + size_t total_size = 0; + Hasher hasher; + for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) { + hasher.update(verify_data.vbmeta_images[n].vbmeta_data, + verify_data.vbmeta_images[n].vbmeta_size); + total_size += verify_data.vbmeta_images[n].vbmeta_size; + } + bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0); + + return std::make_pair(total_size, matched); +} + +// Reads the following values from kernel cmdline and provides the +// VerifyVbmetaImages() to verify AvbSlotVerifyData. +// - androidboot.vbmeta.device_state +// - androidboot.vbmeta.hash_alg +// - androidboot.vbmeta.size +// - androidboot.vbmeta.digest +class FsManagerAvbVerifier { + public: + // The factory method to return a unique_ptr + static std::unique_ptr Create(); + bool VerifyVbmetaImages(const AvbSlotVerifyData& verify_data); + bool IsDeviceUnlocked() { return is_device_unlocked_; } + + protected: + FsManagerAvbVerifier() = default; + + private: + enum HashAlgorithm { + kInvalid = 0, + kSHA256 = 1, + kSHA512 = 2, + }; + + HashAlgorithm hash_alg_; + uint8_t digest_[SHA512_DIGEST_LENGTH]; + size_t vbmeta_size_; + bool is_device_unlocked_; +}; + +std::unique_ptr FsManagerAvbVerifier::Create() { std::string cmdline; - android::base::ReadFileToString("/proc/cmdline", &cmdline); + if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) { + LERROR << "Failed to read /proc/cmdline"; + return nullptr; + } + + std::unique_ptr avb_verifier(new FsManagerAvbVerifier()); + if (!avb_verifier) { + LERROR << "Failed to create unique_ptr"; + return nullptr; + } - std::string hash_alg; std::string digest; - + std::string hash_alg; for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { std::vector pieces = android::base::Split(entry, "="); const std::string& key = pieces[0]; const std::string& value = pieces[1]; if (key == "androidboot.vbmeta.device_state") { - vbmeta_prop->allow_verification_error = (value == "unlocked"); + avb_verifier->is_device_unlocked_ = (value == "unlocked"); } else if (key == "androidboot.vbmeta.hash_alg") { hash_alg = value; } else if (key == "androidboot.vbmeta.size") { - if (!android::base::ParseUint(value.c_str(), &vbmeta_prop->vbmeta_size)) { - return false; + if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) { + return nullptr; } } else if (key == "androidboot.vbmeta.digest") { digest = value; @@ -190,48 +224,31 @@ static bool load_vbmeta_prop(androidboot_vbmeta* vbmeta_prop) { size_t expected_digest_size = 0; if (hash_alg == "sha256") { expected_digest_size = SHA256_DIGEST_LENGTH * 2; - vbmeta_prop->hash_alg = kSHA256; + avb_verifier->hash_alg_ = kSHA256; } else if (hash_alg == "sha512") { expected_digest_size = SHA512_DIGEST_LENGTH * 2; - vbmeta_prop->hash_alg = kSHA512; + avb_verifier->hash_alg_ = kSHA512; } else { LERROR << "Unknown hash algorithm: " << hash_alg.c_str(); - return false; + return nullptr; } // Reads digest. if (digest.size() != expected_digest_size) { LERROR << "Unexpected digest size: " << digest.size() << " (expected: " << expected_digest_size << ")"; - return false; + return nullptr; } - if (!hex_to_bytes(vbmeta_prop->digest, sizeof(vbmeta_prop->digest), digest)) { + if (!hex_to_bytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) { LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str(); - return false; + return nullptr; } - return true; + return avb_verifier; } -template -static std::pair verify_vbmeta_digest(const AvbSlotVerifyData& verify_data, - const androidboot_vbmeta& vbmeta_prop) { - size_t total_size = 0; - Hasher hasher; - for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) { - hasher.update(verify_data.vbmeta_images[n].vbmeta_data, - verify_data.vbmeta_images[n].vbmeta_size); - total_size += verify_data.vbmeta_images[n].vbmeta_size; - } - - bool matched = (memcmp(hasher.finalize(), vbmeta_prop.digest, Hasher::DIGEST_SIZE) == 0); - - return std::make_pair(total_size, matched); -} - -static bool verify_vbmeta_images(const AvbSlotVerifyData& verify_data, - const androidboot_vbmeta& vbmeta_prop) { +bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_data) { if (verify_data.num_vbmeta_images == 0) { LERROR << "No vbmeta images"; return false; @@ -240,17 +257,17 @@ static bool verify_vbmeta_images(const AvbSlotVerifyData& verify_data, size_t total_size = 0; bool digest_matched = false; - if (vbmeta_prop.hash_alg == kSHA256) { + if (hash_alg_ == kSHA256) { std::tie(total_size, digest_matched) = - verify_vbmeta_digest(verify_data, vbmeta_prop); - } else if (vbmeta_prop.hash_alg == kSHA512) { + verify_vbmeta_digest(verify_data, digest_); + } else if (hash_alg_ == kSHA512) { std::tie(total_size, digest_matched) = - verify_vbmeta_digest(verify_data, vbmeta_prop); + verify_vbmeta_digest(verify_data, digest_); } - if (total_size != vbmeta_prop.vbmeta_size) { - LERROR << "total vbmeta size mismatch: " << total_size - << " (expected: " << vbmeta_prop.vbmeta_size << ")"; + if (total_size != vbmeta_size_) { + LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_ + << ")"; return false; } @@ -408,8 +425,7 @@ static bool get_hashtree_descriptor(const std::string& partition_name, continue; } if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) { - desc_partition_name = - (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor); + desc_partition_name = (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor); if (!avb_hashtree_descriptor_validate_and_byteswap( (AvbHashtreeDescriptor*)descriptors[j], out_hashtree_desc)) { continue; @@ -441,134 +457,96 @@ static bool get_hashtree_descriptor(const std::string& partition_name, return true; } -static bool init_is_avb_used() { - // When AVB is used, boot loader should set androidboot.vbmeta.{hash_alg, - // size, digest} in kernel cmdline or in device tree. They will then be - // imported by init process to system properties: ro.boot.vbmeta.{hash_alg, size, digest}. - // - // In case of early mount, init properties are not initialized, so we also - // ensure we look into kernel command line and device tree if the property is - // not found - // - // Checks hash_alg as an indicator for whether AVB is used. - // We don't have to parse and check all of them here. The check will - // be done in fs_mgr_load_vbmeta_images() and FS_MGR_SETUP_AVB_FAIL will - // be returned when there is an error. - - std::string hash_alg; - if (!fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg)) { - return false; - } - if (hash_alg == "sha256" || hash_alg == "sha512") { - return true; - } - return false; -} - -bool fs_mgr_is_avb_used() { - static bool result = init_is_avb_used(); - return result; -} - -int fs_mgr_load_vbmeta_images(struct fstab* fstab) { - FS_MGR_CHECK(fstab != nullptr); - - // Gets the expected hash value of vbmeta images from - // kernel cmdline. - if (!load_vbmeta_prop(&fs_mgr_vbmeta_prop)) { - return FS_MGR_SETUP_AVB_FAIL; +FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by_name_prefix) { + if (device_file_by_name_prefix.empty()) { + LERROR << "Missing device file by-name prefix"; + return nullptr; } - fs_mgr_avb_ops = fs_mgr_dummy_avb_ops_new(fstab); - if (fs_mgr_avb_ops == nullptr) { - LERROR << "Failed to allocate dummy avb_ops"; - return FS_MGR_SETUP_AVB_FAIL; + // Gets the expected hash value of vbmeta images from kernel cmdline. + std::unique_ptr avb_verifier = FsManagerAvbVerifier::Create(); + if (!avb_verifier) { + LERROR << "Failed to create FsManagerAvbVerifier"; + return nullptr; } - // Invokes avb_slot_verify() to load and verify all vbmeta images. - // Sets requested_partitions to nullptr as it's to copy the contents - // of HASH partitions into fs_mgr_avb_verify_data, which is not required as - // fs_mgr only deals with HASHTREE partitions. - const char* requested_partitions[] = {nullptr}; - std::string ab_suffix = fs_mgr_get_slot_suffix(); + FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle()); + if (!avb_handle) { + LERROR << "Failed to allocate FsManagerAvbHandle"; + return nullptr; + } - AvbSlotVerifyResult verify_result = - avb_slot_verify(fs_mgr_avb_ops, requested_partitions, ab_suffix.c_str(), - fs_mgr_vbmeta_prop.allow_verification_error, &fs_mgr_avb_verify_data); + FsManagerAvbOps avb_ops(device_file_by_name_prefix); + AvbSlotVerifyResult verify_result = avb_ops.AvbSlotVerify( + fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_); // Only allow two verify results: // - AVB_SLOT_VERIFY_RESULT_OK. // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state). if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) { - if (!fs_mgr_vbmeta_prop.allow_verification_error) { + if (!avb_verifier->IsDeviceUnlocked()) { LERROR << "ERROR_VERIFICATION isn't allowed"; - goto fail; + return nullptr; } } else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) { LERROR << "avb_slot_verify failed, result: " << verify_result; - goto fail; + return nullptr; } // Verifies vbmeta images against the digest passed from bootloader. - if (!verify_vbmeta_images(*fs_mgr_avb_verify_data, fs_mgr_vbmeta_prop)) { - LERROR << "verify_vbmeta_images failed"; - goto fail; + if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) { + LERROR << "VerifyVbmetaImages failed"; + return nullptr; } else { // Checks whether FLAGS_HASHTREE_DISABLED is set. AvbVBMetaImageHeader vbmeta_header; avb_vbmeta_image_header_to_host_byte_order( - (AvbVBMetaImageHeader*)fs_mgr_avb_verify_data->vbmeta_images[0].vbmeta_data, + (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data, &vbmeta_header); bool hashtree_disabled = ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); if (hashtree_disabled) { - return FS_MGR_SETUP_AVB_HASHTREE_DISABLED; + avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled; + return avb_handle; } } if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) { - return FS_MGR_SETUP_AVB_SUCCESS; + avb_handle->status_ = kFsManagerAvbHandleSuccess; + return avb_handle; } - -fail: - fs_mgr_unload_vbmeta_images(); - return FS_MGR_SETUP_AVB_FAIL; + return nullptr; } -void fs_mgr_unload_vbmeta_images() { - if (fs_mgr_avb_verify_data != nullptr) { - avb_slot_verify_data_free(fs_mgr_avb_verify_data); +bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry) { + if (!fstab_entry) return false; + if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) { + return false; } - - if (fs_mgr_avb_ops != nullptr) { - fs_mgr_dummy_avb_ops_free(fs_mgr_avb_ops); - } -} - -int fs_mgr_setup_avb(struct fstab_rec* fstab_entry) { - if (!fstab_entry || !fs_mgr_avb_verify_data || fs_mgr_avb_verify_data->num_vbmeta_images < 1) { - return FS_MGR_SETUP_AVB_FAIL; + if (status_ == kFsManagerAvbHandleHashtreeDisabled) { + LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point; + return true; } + if (status_ != kFsManagerAvbHandleSuccess) return false; std::string partition_name(basename(fstab_entry->mount_point)); if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) { LERROR << "Partition name: " << partition_name.c_str() << " is not valid UTF-8."; - return FS_MGR_SETUP_AVB_FAIL; + return false; } AvbHashtreeDescriptor hashtree_descriptor; std::string salt; std::string root_digest; - if (!get_hashtree_descriptor(partition_name, *fs_mgr_avb_verify_data, &hashtree_descriptor, - &salt, &root_digest)) { - return FS_MGR_SETUP_AVB_FAIL; + if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt, + &root_digest)) { + return false; } // Converts HASHTREE descriptor to verity_table_params. if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest)) { - return FS_MGR_SETUP_AVB_FAIL; + return false; } - - return FS_MGR_SETUP_AVB_SUCCESS; + return true; } diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp index 8e4966316..981e9fc04 100644 --- a/fs_mgr/fs_mgr_avb_ops.cpp +++ b/fs_mgr/fs_mgr_avb_ops.cpp @@ -39,91 +39,10 @@ #include "fs_mgr_avb_ops.h" #include "fs_mgr_priv.h" -static std::string fstab_by_name_prefix; - -static std::string extract_by_name_prefix(struct fstab* fstab) { - // In AVB, we can assume that there's an entry for the /misc mount - // point in the fstab file and use that to get the device file for - // the misc partition. The device needs not to have an actual /misc - // partition. Then returns the prefix by removing the trailing "misc": - // - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc -> - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ - - struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc"); - if (fstab_entry == nullptr) { - LERROR << "/misc mount point not found in fstab"; - return ""; - } - - std::string full_path(fstab_entry->blk_device); - size_t end_slash = full_path.find_last_of("/"); - - return full_path.substr(0, end_slash + 1); -} - -static AvbIOResult read_from_partition(AvbOps* ops ATTRIBUTE_UNUSED, const char* partition, - int64_t offset, size_t num_bytes, void* buffer, - size_t* out_num_read) { - // The input |partition| name is with ab_suffix, e.g. system_a. - // Slot suffix (e.g. _a) will be appended to the device file path - // for partitions having 'slotselect' optin in fstab file, but it - // won't be appended to the mount point. - // - // Appends |partition| to the fstab_by_name_prefix, which is obtained - // by removing the trailing "misc" from the device file of /misc mount - // point. e.g., - // - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ -> - // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a - - std::string path = fstab_by_name_prefix + partition; - - // Ensures the device path (a symlink created by init) is ready to - // access. fs_mgr_test_access() will test a few iterations if the - // path doesn't exist yet. - if (fs_mgr_test_access(path.c_str()) < 0) { - return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - } - - android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC))); - - if (fd < 0) { - PERROR << "Failed to open " << path.c_str(); - return AVB_IO_RESULT_ERROR_IO; - } - - // If offset is negative, interprets its absolute value as the - // number of bytes from the end of the partition. - if (offset < 0) { - off64_t total_size = lseek64(fd, 0, SEEK_END); - if (total_size == -1) { - LERROR << "Failed to lseek64 to end of the partition"; - return AVB_IO_RESULT_ERROR_IO; - } - offset = total_size + offset; - // Repositions the offset to the beginning. - if (lseek64(fd, 0, SEEK_SET) == -1) { - LERROR << "Failed to lseek64 to the beginning of the partition"; - return AVB_IO_RESULT_ERROR_IO; - } - } - - // On Linux, we never get partial reads from block devices (except - // for EOF). - ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset)); - - if (num_read < 0 || (size_t)num_read != num_bytes) { - PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset " - << offset; - return AVB_IO_RESULT_ERROR_IO; - } - - if (out_num_read != nullptr) { - *out_num_read = num_read; - } - - return AVB_IO_RESULT_OK; +static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset, + size_t num_bytes, void* buffer, size_t* out_num_read) { + return FsManagerAvbOps::GetInstanceFromAvbOps(ops)->ReadFromPartition( + partition, offset, num_bytes, buffer, out_num_read); } static AvbIOResult dummy_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED, @@ -145,7 +64,6 @@ static AvbIOResult dummy_validate_vbmeta_public_key( // Addtionally, user-space should check // androidboot.vbmeta.{hash_alg, size, digest} against the digest // of all vbmeta images after invoking avb_slot_verify(). - *out_is_trusted = true; return AVB_IO_RESULT_OK; } @@ -170,28 +88,86 @@ static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNU return AVB_IO_RESULT_OK; } -AvbOps* fs_mgr_dummy_avb_ops_new(struct fstab* fstab) { - AvbOps* ops; - - fstab_by_name_prefix = extract_by_name_prefix(fstab); - if (fstab_by_name_prefix.empty()) return nullptr; - - ops = (AvbOps*)calloc(1, sizeof(AvbOps)); - if (ops == nullptr) { - LERROR << "Error allocating memory for AvbOps"; - return nullptr; +FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix) + : device_file_by_name_prefix_(device_file_by_name_prefix) { + if (device_file_by_name_prefix_.back() != '/') { + device_file_by_name_prefix_ += '/'; } + // We only need to provide the implementation of read_from_partition() + // operation since that's all what is being used by the avb_slot_verify(). + // Other I/O operations are only required in bootloader but not in + // user-space so we set them as dummy operations. + avb_ops_.read_from_partition = read_from_partition; + avb_ops_.read_rollback_index = dummy_read_rollback_index; + avb_ops_.validate_vbmeta_public_key = dummy_validate_vbmeta_public_key; + avb_ops_.read_is_device_unlocked = dummy_read_is_device_unlocked; + avb_ops_.get_unique_guid_for_partition = dummy_get_unique_guid_for_partition; - // We only need these operations since that's all what is being used - // by the avb_slot_verify(); Most of them are dummy operations because - // they're only required in bootloader but not required in user-space. - ops->read_from_partition = read_from_partition; - ops->read_rollback_index = dummy_read_rollback_index; - ops->validate_vbmeta_public_key = dummy_validate_vbmeta_public_key; - ops->read_is_device_unlocked = dummy_read_is_device_unlocked; - ops->get_unique_guid_for_partition = dummy_get_unique_guid_for_partition; - - return ops; + // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps. + avb_ops_.user_data = this; } -void fs_mgr_dummy_avb_ops_free(AvbOps* ops) { free(ops); } +AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset, + size_t num_bytes, void* buffer, + size_t* out_num_read) { + // Appends |partition| to the device_file_by_name_prefix_, e.g., + // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ -> + // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a + std::string path = device_file_by_name_prefix_ + partition; + + // Ensures the device path (a symlink created by init) is ready to + // access. fs_mgr_test_access() will test a few iterations if the + // path doesn't exist yet. + if (fs_mgr_test_access(path.c_str()) < 0) { + return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; + } + + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC))); + if (fd < 0) { + PERROR << "Failed to open " << path.c_str(); + return AVB_IO_RESULT_ERROR_IO; + } + + // If offset is negative, interprets its absolute value as the + // number of bytes from the end of the partition. + if (offset < 0) { + off64_t total_size = lseek64(fd, 0, SEEK_END); + if (total_size == -1) { + LERROR << "Failed to lseek64 to end of the partition"; + return AVB_IO_RESULT_ERROR_IO; + } + offset = total_size + offset; + // Repositions the offset to the beginning. + if (lseek64(fd, 0, SEEK_SET) == -1) { + LERROR << "Failed to lseek64 to the beginning of the partition"; + return AVB_IO_RESULT_ERROR_IO; + } + } + + // On Linux, we never get partial reads from block devices (except + // for EOF). + ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset)); + if (num_read < 0 || (size_t)num_read != num_bytes) { + PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset " + << offset; + return AVB_IO_RESULT_ERROR_IO; + } + + if (out_num_read != nullptr) { + *out_num_read = num_read; + } + + return AVB_IO_RESULT_OK; +} + +AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix, + bool allow_verification_error, + AvbSlotVerifyData** out_data) { + // Invokes avb_slot_verify() to load and verify all vbmeta images. + // Sets requested_partitions to nullptr as it's to copy the contents + // of HASH partitions into handle>avb_slot_data_, which is not required as + // fs_mgr only deals with HASHTREE partitions. + const char* requested_partitions[] = {nullptr}; + return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(), + allow_verification_error, out_data); +} diff --git a/fs_mgr/fs_mgr_avb_ops.h b/fs_mgr/fs_mgr_avb_ops.h index bfdec9aef..ec4a8c94e 100644 --- a/fs_mgr/fs_mgr_avb_ops.h +++ b/fs_mgr/fs_mgr_avb_ops.h @@ -29,31 +29,34 @@ #include "fs_mgr.h" -__BEGIN_DECLS +// This class provides C++ bindings to interact with libavb, a small +// self-contained piece of code that's intended to be used in bootloaders. +// It mainly contains two functions: +// - ReadFromPartition(): to read AVB metadata from a given partition. +// It provides the implementation of AvbOps.read_from_partition() when +// reading metadata through libavb. +// - AvbSlotVerify(): the C++ binding of libavb->avb_slot_verify() to +// read and verify the metadata and store it into the out_data parameter. +// The caller MUST check the integrity of metadata against the +// androidboot.vbmeta.{hash_alg, size, digest} values from /proc/cmdline. +// e.g., see class FsManagerAvbVerifier for more details. +// +class FsManagerAvbOps { + public: + FsManagerAvbOps(const std::string& device_file_by_name_prefix); -/* Allocates a "dummy" AvbOps instance solely for use in user-space. - * Returns nullptr on OOM. - * - * It mainly provides read_from_partitions() for user-space to get - * AvbSlotVerifyData.vbmeta_images[] and the caller MUST check their - * integrity against the androidboot.vbmeta.{hash_alg, size, digest} - * values from /proc/cmdline, e.g. verify_vbmeta_images() - * in fs_mgr_avb.cpp. - * - * Other I/O operations are only required in boot loader so we set - * them as dummy operations here. - * - Will allow any public key for signing. - * - returns 0 for any rollback index location. - * - returns device is unlocked regardless of the actual state. - * - returns a dummy guid for any partition. - * - * Frees with fs_mgr_dummy_avb_ops_free(). - */ -AvbOps* fs_mgr_dummy_avb_ops_new(struct fstab* fstab); + static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) { + return reinterpret_cast(ops->user_data); + } -/* Frees an AvbOps instance previously allocated with fs_mgr_avb_ops_new(). */ -void fs_mgr_dummy_avb_ops_free(AvbOps* ops); + AvbIOResult ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes, + void* buffer, size_t* out_num_read); -__END_DECLS + AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, bool allow_verification_error, + AvbSlotVerifyData** out_data); + private: + AvbOps avb_ops_; + std::string device_file_by_name_prefix_; +}; #endif /* __CORE_FS_MGR_AVB_OPS_H */ diff --git a/fs_mgr/fs_mgr_priv_avb.h b/fs_mgr/fs_mgr_priv_avb.h index dce9f617d..99a033e59 100644 --- a/fs_mgr/fs_mgr_priv_avb.h +++ b/fs_mgr/fs_mgr_priv_avb.h @@ -17,40 +17,77 @@ #ifndef __CORE_FS_MGR_PRIV_AVB_H #define __CORE_FS_MGR_PRIV_AVB_H -#ifndef __cplusplus -#include -#endif +#include +#include + +#include #include "fs_mgr.h" -__BEGIN_DECLS +enum FsManagerAvbHandleStatus { + kFsManagerAvbHandleSuccess = 0, + kFsManagerAvbHandleHashtreeDisabled = 1, + kFsManagerAvbHandleFail = 2, +}; -#define FS_MGR_SETUP_AVB_HASHTREE_DISABLED (-2) -#define FS_MGR_SETUP_AVB_FAIL (-1) -#define FS_MGR_SETUP_AVB_SUCCESS 0 +class FsManagerAvbHandle; +using FsManagerAvbUniquePtr = std::unique_ptr; -bool fs_mgr_is_avb_used(); +// Provides a factory method to return a unique_ptr pointing to itself and the +// SetUpAvb() function to extract dm-verity parameters from AVB metadata to +// load verity table into kernel through ioctl. +class FsManagerAvbHandle { + public: + // The factory method to return a FsManagerAvbUniquePtr that holds + // the verified AVB (external/avb) metadata of all verified partitions + // in avb_slot_data_.vbmeta_images[]. + // + // The metadata is checked against the following values from /proc/cmdline. + // - androidboot.vbmeta.{hash_alg, size, digest}. + // + // A typical usage will be: + // - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open(); + // + // Possible return values: + // - nullptr: any error when reading and verifying the metadata, + // e.g., I/O error, digest value mismatch, size mismatch, etc. + // + // - a valid unique_ptr with status kFsMgrAvbHandleHashtreeDisabled: + // to support the existing 'adb disable-verity' feature in Android. + // It's very helpful for developers to make the filesystem writable to + // allow replacing binaries on the device. + // + // - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata + // is verified and can be trusted. + // + static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix); -/* Gets AVB metadata through external/avb/libavb for all partitions: - * AvbSlotVerifyData.vbmeta_images[] and checks their integrity - * against the androidboot.vbmeta.{hash_alg, size, digest} values - * from /proc/cmdline. - * - * Return values: - * - FS_MGR_SETUP_AVB_SUCCESS: the metadata cab be trusted. - * - FS_MGR_SETUP_AVB_FAIL: any error when reading and verifying the - * metadata, e.g. I/O error, digest value mismatch, size mismatch. - * - FS_MGR_SETUP_AVB_HASHTREE_DISABLED: to support the existing - * 'adb disable-verity' feature in Android. It's very helpful for - * developers to make the filesystem writable to allow replacing - * binaries on the device. - */ -int fs_mgr_load_vbmeta_images(struct fstab* fstab); + // Sets up dm-verity on the given fstab entry. + // Returns true if the mount point is eligible to mount, it includes: + // - status_ is kFsMgrAvbHandleHashtreeDisabled or + // - status_ is kFsMgrAvbHandleSuccess and sending ioctl DM_TABLE_LOAD + // to load verity table is success. + // Otherwise, returns false. + bool SetUpAvb(fstab_rec* fstab_entry); -void fs_mgr_unload_vbmeta_images(); + FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy + FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete; // no assignment -int fs_mgr_setup_avb(struct fstab_rec* fstab_entry); + FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete; // no move + FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete; // no move assignment -__END_DECLS + ~FsManagerAvbHandle() { + if (avb_slot_data_) { + avb_slot_verify_data_free(avb_slot_data_); + } + }; + + protected: + FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleFail) {} + + private: + AvbSlotVerifyData* avb_slot_data_; + FsManagerAvbHandleStatus status_; +}; #endif /* __CORE_FS_MGR_PRIV_AVB_H */ diff --git a/fs_mgr/fs_mgr_priv_sha.h b/fs_mgr/fs_mgr_priv_sha.h index 882411b40..5b53eea9e 100644 --- a/fs_mgr/fs_mgr_priv_sha.h +++ b/fs_mgr/fs_mgr_priv_sha.h @@ -20,16 +20,18 @@ #include class SHA256Hasher { - private: + private: SHA256_CTX sha256_ctx; uint8_t hash[SHA256_DIGEST_LENGTH]; - public: + public: enum { DIGEST_SIZE = SHA256_DIGEST_LENGTH }; SHA256Hasher() { SHA256_Init(&sha256_ctx); } - void update(const void* data, size_t data_size) { SHA256_Update(&sha256_ctx, data, data_size); } + void update(const uint8_t* data, size_t data_size) { + SHA256_Update(&sha256_ctx, data, data_size); + } const uint8_t* finalize() { SHA256_Final(hash, &sha256_ctx); @@ -38,11 +40,11 @@ class SHA256Hasher { }; class SHA512Hasher { - private: + private: SHA512_CTX sha512_ctx; uint8_t hash[SHA512_DIGEST_LENGTH]; - public: + public: enum { DIGEST_SIZE = SHA512_DIGEST_LENGTH }; SHA512Hasher() { SHA512_Init(&sha512_ctx); } From a01f2f68ec0b76bc6e8c8e80247608b2e8d3a9ae Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Thu, 13 Apr 2017 13:05:42 +0800 Subject: [PATCH 3/5] fs_mgr: adds/changes some public APIs for early mount in init Several changes in this CL: - Moves class FsManagerAvbHandle to public API - Adds a parameter 'wait_for_verity_dev' for FsManagerAvbHandle::SetUpAvb() to allow not to wait for verity device gets created - Adds FsManagerAvbHandle::AvbHashtreeDisabled() to query whether AVB is disabled - Adds fs_mgr_is_avb() to query whether a fstab_rec has MF_AVB flag Bug: 33254008 Test: test AVB on bullhead Change-Id: I89c43ca574ae632db8a700fc2590a1f80212c993 Merged-In: I89c43ca574ae632db8a700fc2590a1f80212c993 (cherry picked from commit 80d1ad17ed5dd1ca63cc3cca24e801c9f63bc48f) --- fs_mgr/fs_mgr.cpp | 7 +++--- fs_mgr/fs_mgr_avb.cpp | 13 ++++++----- fs_mgr/fs_mgr_fstab.cpp | 5 +++++ fs_mgr/include/fs_mgr.h | 1 + .../fs_mgr_avb.h} | 22 +++++++++++-------- 5 files changed, 30 insertions(+), 18 deletions(-) rename fs_mgr/{fs_mgr_priv_avb.h => include/fs_mgr_avb.h} (84%) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 78d0c070f..28da9dbd5 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -47,8 +47,9 @@ #include #include // for __android_log_is_debuggable() +#include "fs_mgr.h" +#include "fs_mgr_avb.h" #include "fs_mgr_priv.h" -#include "fs_mgr_priv_avb.h" #define KEY_LOC_PROP "ro.crypto.keyfile.userdata" #define KEY_IN_FOOTER "footer" @@ -819,7 +820,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) return -1; } } - if (!avb_handle->SetUpAvb(&fstab->recs[i])) { + if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) { LERROR << "Failed to set up AVB on partition: " << fstab->recs[i].mount_point << ", skipping!"; /* Skips mounting the device. */ @@ -1031,7 +1032,7 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, return -1; } } - if (!avb_handle->SetUpAvb(&fstab->recs[i])) { + if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) { LERROR << "Failed to set up AVB on partition: " << fstab->recs[i].mount_point << ", skipping!"; /* Skips mounting the device. */ diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 76ec236b5..7c82bb1e6 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -38,9 +38,9 @@ #include #include "fs_mgr.h" +#include "fs_mgr_avb.h" #include "fs_mgr_avb_ops.h" #include "fs_mgr_priv.h" -#include "fs_mgr_priv_avb.h" #include "fs_mgr_priv_dm_ioctl.h" #include "fs_mgr_priv_sha.h" @@ -336,7 +336,8 @@ static bool hashtree_load_verity_table(struct dm_ioctl* io, const std::string& d static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, const AvbHashtreeDescriptor& hashtree_desc, - const std::string& salt, const std::string& root_digest) { + 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) { @@ -375,13 +376,12 @@ static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, // Marks the underlying block device as read-only. fs_mgr_set_blk_ro(fstab_entry->blk_device); - // TODO(bowgotsai): support verified all partition at boot. // Updates fstab_rec->blk_device to verity device name. free(fstab_entry->blk_device); fstab_entry->blk_device = strdup(verity_blk_name.c_str()); // Makes sure we've set everything up properly. - if (fs_mgr_test_access(verity_blk_name.c_str()) < 0) { + if (wait_for_verity_dev && fs_mgr_test_access(verity_blk_name.c_str()) < 0) { return false; } @@ -519,7 +519,7 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by return nullptr; } -bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry) { +bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) { if (!fstab_entry) return false; if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) { return false; @@ -545,7 +545,8 @@ bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry) { } // Converts HASHTREE descriptor to verity_table_params. - if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest)) { + if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest, + wait_for_verity_dev)) { return false; } return true; diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index c231a23c9..0a694c145 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -814,6 +814,11 @@ int fs_mgr_is_verified(const struct fstab_rec *fstab) return fstab->fs_mgr_flags & MF_VERIFY; } +int fs_mgr_is_avb(const struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_AVB; +} + int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab) { return fstab->fs_mgr_flags & MF_VERIFYATBOOT; diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index ec6a415f6..458176b12 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -124,6 +124,7 @@ int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab); int fs_mgr_is_nonremovable(const struct fstab_rec *fstab); int fs_mgr_is_verified(const struct fstab_rec *fstab); int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab); +int fs_mgr_is_avb(const struct fstab_rec *fstab); int fs_mgr_is_encryptable(const struct fstab_rec *fstab); int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab); void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab, diff --git a/fs_mgr/fs_mgr_priv_avb.h b/fs_mgr/include/fs_mgr_avb.h similarity index 84% rename from fs_mgr/fs_mgr_priv_avb.h rename to fs_mgr/include/fs_mgr_avb.h index 99a033e59..526a5ce06 100644 --- a/fs_mgr/fs_mgr_priv_avb.h +++ b/fs_mgr/include/fs_mgr_avb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 The Android Open Source Project + * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef __CORE_FS_MGR_PRIV_AVB_H -#define __CORE_FS_MGR_PRIV_AVB_H +#ifndef __CORE_FS_MGR_AVB_H +#define __CORE_FS_MGR_AVB_H #include #include @@ -63,18 +63,22 @@ class FsManagerAvbHandle { static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix); // Sets up dm-verity on the given fstab entry. + // The 'wait_for_verity_dev' parameter makes this function wait for the + // verity device to get created before return. // Returns true if the mount point is eligible to mount, it includes: // - status_ is kFsMgrAvbHandleHashtreeDisabled or // - status_ is kFsMgrAvbHandleSuccess and sending ioctl DM_TABLE_LOAD // to load verity table is success. // Otherwise, returns false. - bool SetUpAvb(fstab_rec* fstab_entry); + bool SetUpAvb(fstab_rec* fstab_entry, bool wait_for_verity_dev); - FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy - FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete; // no assignment + bool AvbHashtreeDisabled() { return status_ == kFsManagerAvbHandleHashtreeDisabled; } - FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete; // no move - FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete; // no move assignment + FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy + FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete; // no assignment + + FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete; // no move + FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete; // no move assignment ~FsManagerAvbHandle() { if (avb_slot_data_) { @@ -90,4 +94,4 @@ class FsManagerAvbHandle { FsManagerAvbHandleStatus status_; }; -#endif /* __CORE_FS_MGR_PRIV_AVB_H */ +#endif /* __CORE_FS_MGR_AVB_H */ From 51c027285bcdcce615fc0084d0a738f28c19ee59 Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Thu, 6 Apr 2017 21:01:40 +0800 Subject: [PATCH 4/5] init: support early_mount with vboot 2.0 (external/avb/libavb) libavb requires verifying AVB metadata on all verified partitions at once. For example, /vbmeta, /boot, /system and /vendor. We need to invoke device_init() for those partitions even if we only want to early mount some of them, like /vendor and /system. This CL gets all AVB partitions and the early mount partitions from device tree through "firmware/android/vbmeta" and "firmware/fstab", respectively. The following is an example to early mount /vendor partition on bullhead: firmware { android { compatible = "android,firmware"; vbmeta { compatible = "android,vbmeta"; parts = "boot,system,vendor"; by_name_prefix="/dev/block/platform/soc.0/f9824900.sdhci/by-name" }; fstab { compatible = "android,fstab"; vendor { compatible = "android,vendor"; dev = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor"; type = "ext4"; mnt_flags = "ro,barrier=1,inode_readahead_blks=8"; fsmgr_flags = "wait,avb"; }; }; }; }; Bug: 33254008 Test: early mount /vendor with vboot 2.0 (AVB) on bullhead Test: early mount /system without dm-verity on bullhead Test: early mount /vendor with vboot 1.0 on sailfish Change-Id: I89a1f77c97124f309346b33d9e700544b92ecf05 Merged-In: I89a1f77c97124f309346b33d9e700544b92ecf05 (cherry picked from commit 8bba52fc4bf1f2f84add7af5d9527ae923cf8ecc) --- init/init.cpp | 237 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 182 insertions(+), 55 deletions(-) diff --git a/init/init.cpp b/init/init.cpp index d07c308a5..b05311a31 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -57,6 +57,7 @@ #include "bootchart.h" #include "devices.h" #include "fs_mgr.h" +#include "fs_mgr_avb.h" #include "import_parser.h" #include "init.h" #include "init_parser.h" @@ -478,42 +479,73 @@ static void export_kernel_boot_props() { } } -static constexpr char android_dt_dir[] = "/proc/device-tree/firmware/android"; - -static bool is_dt_compatible() { - std::string dt_value; - std::string file_name = StringPrintf("%s/compatible", android_dt_dir); - - if (android::base::ReadFileToString(file_name, &dt_value)) { - // trim the trailing '\0' out, otherwise the comparison - // will produce false-negatives. - dt_value.resize(dt_value.size() - 1); - if (dt_value == "android,firmware") { +/* Reads the content of device tree file into dt_value. + * Returns true if the read is success, false otherwise. + */ +static bool read_dt_file(const std::string& file_name, std::string* dt_value) { + if (android::base::ReadFileToString(file_name, dt_value)) { + if (!dt_value->empty()) { + dt_value->pop_back(); // Trim the trailing '\0' out. return true; } } - return false; } -static bool is_dt_fstab_compatible() { - std::string dt_value; - std::string file_name = StringPrintf("%s/%s/compatible", android_dt_dir, "fstab"); +static const std::string kAndroidDtDir("/proc/device-tree/firmware/android/"); - if (android::base::ReadFileToString(file_name, &dt_value)) { - dt_value.resize(dt_value.size() - 1); - if (dt_value == "android,fstab") { +static bool is_dt_value_expected(const std::string& dt_file_suffix, + const std::string& expected_value) { + std::string dt_value; + std::string file_name = kAndroidDtDir + dt_file_suffix; + + if (read_dt_file(file_name, &dt_value)) { + if (dt_value == expected_value) { return true; } } - return false; } +static inline bool is_dt_compatible() { + return is_dt_value_expected("compatible", "android,firmware"); +} + +static inline bool is_dt_fstab_compatible() { + return is_dt_value_expected("fstab/compatible", "android,fstab"); +} + +static inline bool is_dt_vbmeta_compatible() { + return is_dt_value_expected("vbmeta/compatible", "android,vbmeta"); +} + +// Gets the vbmeta config from device tree. Specifically, the 'parts' and 'by_name_prefix'. +// /{ +// firmware { +// android { +// vbmeta { +// compatible = "android,vbmeta"; +// parts = "vbmeta,boot,system,vendor" +// by_name_prefix="/dev/block/platform/soc.0/f9824900.sdhci/by-name/" +// }; +// }; +// }; +// } +static bool get_vbmeta_config_from_dt(std::string* vbmeta_partitions, + std::string* device_file_by_name_prefix) { + std::string file_name = kAndroidDtDir + "vbmeta/parts"; + if (!read_dt_file(file_name, vbmeta_partitions)) return false; + + file_name = kAndroidDtDir + "vbmeta/by_name_prefix"; + if (!read_dt_file(file_name, device_file_by_name_prefix)) return false; + + return true; +} + static void process_kernel_dt() { if (!is_dt_compatible()) return; - std::unique_ptrdir(opendir(android_dt_dir), closedir); + std::unique_ptr dir(opendir(kAndroidDtDir.c_str()), closedir); if (!dir) return; std::string dt_file; @@ -523,7 +555,7 @@ static void process_kernel_dt() { continue; } - std::string file_name = StringPrintf("%s/%s", android_dt_dir, dp->d_name); + std::string file_name = kAndroidDtDir + dp->d_name; android::base::ReadFileToString(file_name, &dt_file); std::replace(dt_file.begin(), dt_file.end(), ',', '.'); @@ -944,38 +976,100 @@ static void set_usb_controller() { } } -static bool early_mount_one(struct fstab_rec* rec) { - if (rec && fs_mgr_is_verified(rec)) { - // setup verity and create the dm-XX block device - // needed to mount this partition - int ret = fs_mgr_setup_verity(rec, false); - if (ret == FS_MGR_SETUP_VERITY_FAIL) { - PLOG(ERROR) << "early_mount: Failed to setup verity for '" << rec->mount_point << "'"; +// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX. +static void device_init_dm_device(const std::string& dm_device) { + const std::string device_name(basename(dm_device.c_str())); + const std::string syspath = "/sys/block/" + device_name; + + device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t { + if (uevent->device_name && device_name == uevent->device_name) { + LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device; + return COLDBOOT_STOP; + } + return COLDBOOT_CONTINUE; + }); + device_close(); +} + +static bool vboot_1_0_mount_partitions(const std::vector& fstab_recs) { + if (fstab_recs.empty()) return false; + + for (auto rec : fstab_recs) { + bool need_create_dm_device = false; + if (fs_mgr_is_verified(rec)) { + // setup verity and create the dm-XX block device + // needed to mount this partition + int ret = fs_mgr_setup_verity(rec, false /* wait_for_verity_dev */); + if (ret == FS_MGR_SETUP_VERITY_DISABLED) { + LOG(INFO) << "verity disabled for '" << rec->mount_point << "'"; + } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) { + need_create_dm_device = true; + } else { + PLOG(ERROR) << "early_mount: failed to setup verity for '" << rec->mount_point + << "'"; + return false; + } + } + if (need_create_dm_device) { + // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX". + // Need to create it because ueventd isn't started during early mount. + device_init_dm_device(rec->blk_device); + } + if (fs_mgr_do_mount_one(rec)) { + PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'"; return false; } - - // The exact block device name is added as a mount source by - // fs_mgr_setup_verity() in ->blk_device as "/dev/block/dm-XX" - // We create that device by running coldboot on /sys/block/dm-XX - std::string dm_device(basename(rec->blk_device)); - std::string syspath = StringPrintf("/sys/block/%s", dm_device.c_str()); - device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t { - if (uevent->device_name && !strcmp(dm_device.c_str(), uevent->device_name)) { - LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device; - return COLDBOOT_STOP; - } - return COLDBOOT_CONTINUE; - }); - } - - if (rec && fs_mgr_do_mount_one(rec)) { - PLOG(ERROR) << "early_mount: Failed to mount '" << rec->mount_point << "'"; - return false; } return true; } +static bool vboot_2_0_mount_partitions(const std::vector& fstab_recs, + const std::string& device_file_by_name_prefix) { + if (fstab_recs.empty()) return false; + + FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(device_file_by_name_prefix); + if (!avb_handle) { + LOG(INFO) << "Failed to Open FsManagerAvbHandle"; + return false; + } + + for (auto rec : fstab_recs) { + bool need_create_dm_device = false; + if (fs_mgr_is_avb(rec)) { + if (avb_handle->AvbHashtreeDisabled()) { + LOG(INFO) << "avb hashtree disabled for '" << rec->mount_point << "'"; + } else if (avb_handle->SetUpAvb(rec, false /* wait_for_verity_dev */)) { + need_create_dm_device = true; + } else { + PLOG(ERROR) << "early_mount: failed to set up AVB on partition: '" + << rec->mount_point << "'"; + return false; + } + } + if (need_create_dm_device) { + // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX". + // Need to create it because ueventd isn't started during early mount. + device_init_dm_device(rec->blk_device); + } + if (fs_mgr_do_mount_one(rec)) { + PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'"; + return false; + } + } + + return true; +} + +static bool mount_early_partitions(const std::vector& fstab_recs, + const std::string& device_file_by_name_prefix) { + if (is_dt_vbmeta_compatible()) { // AVB (external/avb) is used to setup dm-verity. + return vboot_2_0_mount_partitions(fstab_recs, device_file_by_name_prefix); + } else { + return vboot_1_0_mount_partitions(fstab_recs); + } +} + // Creates devices with uevent->partition_name matching one in the in/out // partition_names. Note that the partition_names MUST have A/B suffix // when A/B is used. Found partitions will then be removed from the @@ -1018,12 +1112,10 @@ static void early_device_init(std::set* partition_names) { }); } -static bool get_early_partitions(const std::vector& early_fstab_recs, - std::set* out_partitions, bool* out_need_verity) { +static bool vboot_1_0_early_partitions(const std::vector& early_fstab_recs, + std::set* out_partitions, + bool* out_need_verity) { std::string meta_partition; - out_partitions->clear(); - *out_need_verity = false; - for (auto fstab_rec : early_fstab_recs) { // don't allow verifyatboot for early mounted partitions if (fs_mgr_is_verifyatboot(fstab_rec)) { @@ -1062,6 +1154,40 @@ static bool get_early_partitions(const std::vector& early_fstab_recs return true; } +// a.k.a. AVB (external/avb) +static bool vboot_2_0_early_partitions(std::set* out_partitions, bool* out_need_verity, + std::string* out_device_file_by_name_prefix) { + std::string vbmeta_partitions; + if (!get_vbmeta_config_from_dt(&vbmeta_partitions, out_device_file_by_name_prefix)) { + return false; + } + // libavb verifies AVB metadata on all verified partitions at once. + // e.g., The vbmeta_partitions will be "vbmeta,boot,system,vendor" + // for libavb to verify metadata, even if we only need to early mount /vendor. + std::vector partitions = android::base::Split(vbmeta_partitions, ","); + std::string ab_suffix = fs_mgr_get_slot_suffix(); + for (const auto& partition : partitions) { + out_partitions->emplace(partition + ab_suffix); + } + *out_need_verity = true; + return true; +} + +static bool get_early_partitions(const std::vector& early_fstab_recs, + std::set* out_partitions, bool* out_need_verity, + std::string* out_device_file_by_name_prefix) { + *out_need_verity = false; + out_partitions->clear(); + out_device_file_by_name_prefix->clear(); + + if (is_dt_vbmeta_compatible()) { // AVB (external/avb) is used to setup dm-verity. + return vboot_2_0_early_partitions(out_partitions, out_need_verity, + out_device_file_by_name_prefix); + } else { + return vboot_1_0_early_partitions(early_fstab_recs, out_partitions, out_need_verity); + } +} + /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */ static bool early_mount() { // skip early mount if we're in recovery mode @@ -1096,9 +1222,11 @@ static bool early_mount() { if (early_fstab_recs.empty()) return true; bool need_verity; + std::string device_file_by_name_prefix; std::set partition_names; // partition_names MUST have A/B suffix when A/B is used - if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity)) { + if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity, + &device_file_by_name_prefix)) { return false; } @@ -1121,10 +1249,9 @@ static bool early_mount() { [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; }); } - for (auto fstab_rec : early_fstab_recs) { - if (!early_mount_one(fstab_rec)) goto done; + if (mount_early_partitions(early_fstab_recs, device_file_by_name_prefix)) { + success = true; } - success = true; done: device_close(); From 92ca58b5bddd07075faa8179302013f9c13e85b7 Mon Sep 17 00:00:00 2001 From: Bowgo Tsai Date: Thu, 2 Mar 2017 00:03:56 +0800 Subject: [PATCH 5/5] fs_mgr: support AVB in fs_mgr_update_verity_state() fs_mgr_update_verity_state() is invoked by 'verity_update_state' in init.rc. It will then set property "partition.system.verified" and "partition.vendor.verified" to verify_mode. We should support this for AVB as well. Also change the order of static libs in init to fix the build error after this change: system/extras/ext4_utils/ext4_crypt.cpp:69: error: undefined reference to 'property_get' Bug: 35416769 Test: Mount /system and /vendor with vboot 2.0 (AVB), check the following properties exist. - [partition.system.verified]: [2] - [partition.vendor.verified]: [2] Test: Mount /system and /vendor with vboot 1.0, check the following properties exist. - [partition.system.verified]: [0] - [partition.vendor.verified]: [0] Change-Id: I4328d66a8cb93f26e7960e620a0b2292d5f15900 Merged-In: I4328d66a8cb93f26e7960e620a0b2292d5f15900 (cherry picked from commit aaf70e77dc232fde152249bb6f66a227eab35a10) --- fs_mgr/fs_mgr.cpp | 98 ++++++++++++++++++++++++++++++ fs_mgr/fs_mgr_priv.h | 1 + fs_mgr/fs_mgr_verity.cpp | 126 +-------------------------------------- fs_mgr/include/fs_mgr.h | 4 +- init/Android.mk | 2 +- init/builtins.cpp | 8 +-- 6 files changed, 107 insertions(+), 132 deletions(-) diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 28da9dbd5..ea9cb375c 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -31,7 +31,10 @@ #include #include +#include + #include +#include #include #include #include @@ -50,6 +53,7 @@ #include "fs_mgr.h" #include "fs_mgr_avb.h" #include "fs_mgr_priv.h" +#include "fs_mgr_priv_dm_ioctl.h" #define KEY_LOC_PROP "ro.crypto.keyfile.userdata" #define KEY_IN_FOOTER "footer" @@ -1258,3 +1262,97 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev return 0; } + +bool fs_mgr_load_verity_state(int* mode) { + /* return the default mode, unless any of the verified partitions are in + * logging mode, in which case return that */ + *mode = VERITY_MODE_DEFAULT; + + std::unique_ptr fstab(fs_mgr_read_fstab_default(), + fs_mgr_free_fstab); + if (!fstab) { + LERROR << "Failed to read default fstab"; + return false; + } + + for (int i = 0; i < fstab->num_entries; i++) { + if (fs_mgr_is_avb(&fstab->recs[i])) { + *mode = VERITY_MODE_RESTART; // avb only supports restart mode. + break; + } else if (!fs_mgr_is_verified(&fstab->recs[i])) { + continue; + } + + int current; + if (load_verity_state(&fstab->recs[i], ¤t) < 0) { + continue; + } + if (current != VERITY_MODE_DEFAULT) { + *mode = current; + break; + } + } + + return true; +} + +bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) { + if (!callback) { + return false; + } + + int mode; + if (!fs_mgr_load_verity_state(&mode)) { + return false; + } + + android::base::unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC))); + if (fd == -1) { + PERROR << "Error opening device mapper"; + return false; + } + + std::unique_ptr fstab(fs_mgr_read_fstab_default(), + fs_mgr_free_fstab); + if (!fstab) { + LERROR << "Failed to read default fstab"; + return false; + } + + alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; + struct dm_ioctl* io = (struct dm_ioctl*)buffer; + bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true"; + + for (int i = 0; i < fstab->num_entries; i++) { + if (!fs_mgr_is_verified(&fstab->recs[i]) && !fs_mgr_is_avb(&fstab->recs[i])) { + continue; + } + + std::string mount_point; + if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) { + mount_point = "system"; + } else { + mount_point = basename(fstab->recs[i].mount_point); + } + + fs_mgr_verity_ioctl_init(io, mount_point, 0); + + const char* status; + if (ioctl(fd, DM_TABLE_STATUS, io)) { + if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) { + status = "V"; + } else { + PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str(); + continue; + } + } + + status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; + + if (*status == 'C' || *status == 'V') { + callback(&fstab->recs[i], mount_point.c_str(), mode, *status); + } + } + + return true; +} diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index dedffd8d1..c985462af 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -115,5 +115,6 @@ int fs_mgr_test_access(const char *device); bool fs_mgr_update_for_slotselect(struct fstab *fstab); bool is_dt_compatible(); bool is_device_secure(); +int load_verity_state(struct fstab_rec* fstab, int* mode); #endif /* __CORE_FS_MGR_PRIV_H */ diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp index 8c7a8ca6d..0bf173bd8 100644 --- a/fs_mgr/fs_mgr_verity.cpp +++ b/fs_mgr/fs_mgr_verity.cpp @@ -653,8 +653,7 @@ static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset) offset); } -static int load_verity_state(struct fstab_rec *fstab, int *mode) -{ +int load_verity_state(struct fstab_rec* fstab, int* mode) { int match = 0; off64_t offset = 0; @@ -690,129 +689,6 @@ static int load_verity_state(struct fstab_rec *fstab, int *mode) return read_verity_state(fstab->verity_loc, offset, mode); } -int fs_mgr_load_verity_state(int *mode) -{ - int rc = -1; - int i; - int current; - struct fstab *fstab = NULL; - - /* return the default mode, unless any of the verified partitions are in - * logging mode, in which case return that */ - *mode = VERITY_MODE_DEFAULT; - - fstab = fs_mgr_read_fstab_default(); - if (!fstab) { - LERROR << "Failed to read default fstab"; - goto out; - } - - for (i = 0; i < fstab->num_entries; i++) { - if (!fs_mgr_is_verified(&fstab->recs[i])) { - continue; - } - - rc = load_verity_state(&fstab->recs[i], ¤t); - if (rc < 0) { - continue; - } - - if (current != VERITY_MODE_DEFAULT) { - *mode = current; - break; - } - } - - rc = 0; - -out: - if (fstab) { - fs_mgr_free_fstab(fstab); - } - - return rc; -} - -int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) -{ - alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; - bool system_root = false; - std::string mount_point; - char propbuf[PROPERTY_VALUE_MAX]; - const char *status; - int fd = -1; - int i; - int mode; - int rc = -1; - struct dm_ioctl *io = (struct dm_ioctl *) buffer; - struct fstab *fstab = NULL; - - if (!callback) { - return -1; - } - - if (fs_mgr_load_verity_state(&mode) == -1) { - return -1; - } - - fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); - if (fd == -1) { - PERROR << "Error opening device mapper"; - goto out; - } - - property_get("ro.build.system_root_image", propbuf, ""); - system_root = !strcmp(propbuf, "true"); - fstab = fs_mgr_read_fstab_default(); - if (!fstab) { - LERROR << "Failed to read default fstab"; - goto out; - } - - for (i = 0; i < fstab->num_entries; i++) { - if (!fs_mgr_is_verified(&fstab->recs[i])) { - continue; - } - - if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) { - mount_point = "system"; - } else { - mount_point = basename(fstab->recs[i].mount_point); - } - - fs_mgr_verity_ioctl_init(io, mount_point, 0); - - if (ioctl(fd, DM_TABLE_STATUS, io)) { - if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) { - status = "V"; - } else { - PERROR << "Failed to query DM_TABLE_STATUS for " - << mount_point.c_str(); - continue; - } - } - - status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; - - if (*status == 'C' || *status == 'V') { - callback(&fstab->recs[i], mount_point.c_str(), mode, *status); - } - } - - rc = 0; - -out: - if (fstab) { - fs_mgr_free_fstab(fstab); - } - - if (fd) { - close(fd); - } - - return rc; -} - static void update_verity_table_blk_device(char *blk_device, char **table) { std::string result, word; diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 458176b12..fd63dfd38 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -114,8 +114,8 @@ int fs_mgr_do_tmpfs_mount(const char *n_name); int fs_mgr_unmount_all(struct fstab *fstab); int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size); -int fs_mgr_load_verity_state(int *mode); -int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback); +bool fs_mgr_load_verity_state(int* mode); +bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback); int fs_mgr_add_entry(struct fstab *fstab, const char *mount_point, const char *fs_type, const char *blk_device); diff --git a/init/Android.mk b/init/Android.mk index e97f4f2f2..6dc02293f 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -109,8 +109,8 @@ LOCAL_STATIC_LIBRARIES := \ libfec_rs \ libsquashfs_utils \ liblogwrap \ - libcutils \ libext4_utils \ + libcutils \ libbase \ libc \ libselinux \ diff --git a/init/builtins.cpp b/init/builtins.cpp index 75b3c6104..2be70bf5f 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -678,11 +678,11 @@ static int do_sysclktz(const std::vector& args) { static int do_verity_load_state(const std::vector& args) { int mode = -1; - int rc = fs_mgr_load_verity_state(&mode); - if (rc == 0 && mode != VERITY_MODE_DEFAULT) { + bool loaded = fs_mgr_load_verity_state(&mode); + if (loaded && mode != VERITY_MODE_DEFAULT) { ActionManager::GetInstance().QueueEventTrigger("verity-logging"); } - return rc; + return loaded ? 0 : 1; } static void verity_update_property(fstab_rec *fstab, const char *mount_point, @@ -692,7 +692,7 @@ static void verity_update_property(fstab_rec *fstab, const char *mount_point, } static int do_verity_update_state(const std::vector& args) { - return fs_mgr_update_verity_state(verity_update_property); + return fs_mgr_update_verity_state(verity_update_property) ? 0 : 1; } static int do_write(const std::vector& args) {