diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 5e0bfe48b..8c19a812c 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -839,7 +839,8 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) return FS_MGR_MNTALL_FAIL; } } - if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) { + if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) == + SetUpAvbHashtreeResult::kFail) { LERROR << "Failed to set up AVB on partition: " << fstab->recs[i].mount_point << ", skipping!"; /* Skips mounting the device. */ @@ -1055,7 +1056,8 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, return FS_MGR_DOMNT_FAILED; } } - if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) { + if (avb_handle->SetUpAvbHashtree(&fstab->recs[i], true /* wait_for_verity_dev */) == + SetUpAvbHashtreeResult::kFail) { 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 661800374..2c99aa7c5 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -114,7 +114,6 @@ static std::pair verify_vbmeta_digest(const AvbSlotVerifyData& ver // 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 @@ -123,7 +122,6 @@ class FsManagerAvbVerifier { // 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; @@ -138,7 +136,6 @@ class FsManagerAvbVerifier { HashAlgorithm hash_alg_; uint8_t digest_[SHA512_DIGEST_LENGTH]; size_t vbmeta_size_; - bool is_device_unlocked_; }; std::unique_ptr FsManagerAvbVerifier::Create() { @@ -161,9 +158,7 @@ std::unique_ptr FsManagerAvbVerifier::Create() { const std::string& key = pieces[0]; const std::string& value = pieces[1]; - if (key == "androidboot.vbmeta.device_state") { - avb_verifier->is_device_unlocked_ = (value == "unlocked"); - } else if (key == "androidboot.vbmeta.hash_alg") { + if (key == "androidboot.vbmeta.hash_alg") { hash_alg = value; } else if (key == "androidboot.vbmeta.size") { if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) { @@ -478,6 +473,16 @@ static bool get_hashtree_descriptor(const std::string& partition_name, return true; } +// Orange state means the device is unlocked, see the following link for details. +// https://source.android.com/security/verifiedboot/verified-boot#device_state +static inline bool IsDeviceUnlocked() { + std::string verified_boot_state; + if (fs_mgr_get_boot_config("verifiedbootstate", &verified_boot_state)) { + return verified_boot_state == "orange"; + } + return false; +} + FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) { FsManagerAvbOps avb_ops(fstab); return DoOpen(&avb_ops); @@ -493,12 +498,7 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlin } FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { - // 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; - } + bool is_device_unlocked = IsDeviceUnlocked(); FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle()); if (!avb_handle) { @@ -506,9 +506,8 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { return nullptr; } - AvbSlotVerifyFlags flags = avb_verifier->IsDeviceUnlocked() - ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR - : AVB_SLOT_VERIFY_FLAGS_NONE; + AvbSlotVerifyFlags flags = is_device_unlocked ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR + : AVB_SLOT_VERIFY_FLAGS_NONE; AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_); @@ -526,62 +525,81 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { // for more details. switch (verify_result) { case AVB_SLOT_VERIFY_RESULT_OK: - avb_handle->status_ = kFsManagerAvbHandleSuccess; + avb_handle->status_ = kAvbHandleSuccess; break; case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: - if (!avb_verifier->IsDeviceUnlocked()) { + if (!is_device_unlocked) { LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED"; return nullptr; } - avb_handle->status_ = kFsManagerAvbHandleErrorVerification; + avb_handle->status_ = kAvbHandleVerificationError; break; default: LERROR << "avb_slot_verify failed, result: " << verify_result; return nullptr; } - // Verifies vbmeta images against the digest passed from bootloader. - if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) { - LERROR << "VerifyVbmetaImages failed"; - return nullptr; - } - // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version". avb_handle->avb_version_ = android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR); - // Checks whether FLAGS_HASHTREE_DISABLED is set. + // Checks whether FLAGS_VERIFICATION_DISABLED is set: + // - Only the top-level vbmeta struct is read. + // - vbmeta struct in other partitions are NOT processed, including AVB HASH descriptor(s) + // and AVB HASHTREE descriptor(s). AvbVBMetaImageHeader vbmeta_header; avb_vbmeta_image_header_to_host_byte_order( (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data, &vbmeta_header); + bool verification_disabled = + ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED); - bool hashtree_disabled = - ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); - if (hashtree_disabled) { - avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled; + if (verification_disabled) { + avb_handle->status_ = kAvbHandleVerificationDisabled; + } else { + // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline. + std::unique_ptr avb_verifier = FsManagerAvbVerifier::Create(); + if (!avb_verifier) { + LERROR << "Failed to create FsManagerAvbVerifier"; + return nullptr; + } + if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) { + LERROR << "VerifyVbmetaImages failed"; + return nullptr; + } + + // Checks whether FLAGS_HASHTREE_DISABLED is set. + bool hashtree_disabled = + ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); + if (hashtree_disabled) { + avb_handle->status_ = kAvbHandleHashtreeDisabled; + } } LINFO << "Returning avb_handle with status: " << avb_handle->status_; return avb_handle; } -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; +SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fstab_entry, + bool wait_for_verity_dev) { + if (!fstab_entry || status_ == kAvbHandleUninitialized || !avb_slot_data_ || + avb_slot_data_->num_vbmeta_images < 1) { + return SetUpAvbHashtreeResult::kFail; } - if (status_ == kFsManagerAvbHandleUninitialized) return false; - if (status_ == kFsManagerAvbHandleHashtreeDisabled) { - LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point; - return true; + if (status_ == kAvbHandleHashtreeDisabled || status_ == kAvbHandleVerificationDisabled) { + LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point; + return SetUpAvbHashtreeResult::kDisabled; } - 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 false; + // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor + // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix. + std::string partition_name(basename(fstab_entry->blk_device)); + if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) { + auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix()); + if (ab_suffix != std::string::npos) { + partition_name.erase(ab_suffix); + } } AvbHashtreeDescriptor hashtree_descriptor; @@ -589,13 +607,14 @@ bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_v std::string root_digest; if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt, &root_digest)) { - return false; + return SetUpAvbHashtreeResult::kFail; } // Converts HASHTREE descriptor to verity_table_params. if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest, wait_for_verity_dev)) { - return false; + return SetUpAvbHashtreeResult::kFail; } - return true; + + return SetUpAvbHashtreeResult::kSuccess; } diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp index 512839b48..ba1262fde 100644 --- a/fs_mgr/fs_mgr_avb_ops.cpp +++ b/fs_mgr/fs_mgr_avb_ops.cpp @@ -89,6 +89,15 @@ static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNU return AVB_IO_RESULT_OK; } +static AvbIOResult dummy_get_size_of_partition(AvbOps* ops ATTRIBUTE_UNUSED, + const char* partition ATTRIBUTE_UNUSED, + uint64_t* out_size_num_byte) { + // The function is for bootloader to load entire content of AVB HASH partitions. + // In user-space, returns 0 as we only need to set up AVB HASHTHREE partitions. + *out_size_num_byte = 0; + return AVB_IO_RESULT_OK; +} + void FsManagerAvbOps::InitializeAvbOps() { // 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(). @@ -101,6 +110,7 @@ void FsManagerAvbOps::InitializeAvbOps() { 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; + avb_ops_.get_size_of_partition = dummy_get_size_of_partition; // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps. avb_ops_.user_data = this; diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h index bbafe1a03..73a22c863 100644 --- a/fs_mgr/include/fs_mgr_avb.h +++ b/fs_mgr/include/fs_mgr_avb.h @@ -25,11 +25,10 @@ #include "fs_mgr.h" -enum FsManagerAvbHandleStatus { - kFsManagerAvbHandleUninitialized = -1, - kFsManagerAvbHandleSuccess = 0, - kFsManagerAvbHandleHashtreeDisabled = 1, - kFsManagerAvbHandleErrorVerification = 2, +enum class SetUpAvbHashtreeResult { + kSuccess = 0, + kFail, + kDisabled, }; class FsManagerAvbOps; @@ -40,8 +39,8 @@ using FsManagerAvbUniquePtr = std::unique_ptr; using ByNameSymlinkMap = std::map; // 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. +// SetUpAvbHashtree() function to extract dm-verity parameters from AVB HASHTREE +// descriptors to load verity table into kernel through ioctl. class FsManagerAvbHandle { public: // The factory method to return a FsManagerAvbUniquePtr that holds @@ -65,12 +64,22 @@ class FsManagerAvbHandle { // - 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: + // - a valid unique_ptr with status kAvbHandleHashtreeDisabled: // 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 + // - a valid unique_ptr with status kAvbHandleVerificationDisabled: + // to support 'avbctl disable-verification': only the top-level + // vbmeta is read, vbmeta structs in other partitions are not processed. + // It's needed to bypass AVB when using the generic system.img to run + // VTS for project Treble. + // + // - a valid unique_ptr with status kAvbHandleVerificationError: + // there is verification error when libavb loads vbmeta from each + // partition. This is only allowed when the device is unlocked. + // + // - a valid unique_ptr with status kAvbHandleSuccess: the metadata // is verified and can be trusted. // static FsManagerAvbUniquePtr Open(const fstab& fstab); @@ -79,14 +88,15 @@ class FsManagerAvbHandle { // 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 wait_for_verity_dev); + // + // Return value: + // - kSuccess: successfully loads dm-verity table into kernel. + // - kFailed: failed to setup dm-verity, e.g., vbmeta verification error, + // failed to get the HASHTREE descriptor, runtime error when set up + // device-mapper, etc. + // - kDisabled: hashtree is disabled. + SetUpAvbHashtreeResult SetUpAvbHashtree(fstab_rec* fstab_entry, bool wait_for_verity_dev); - bool hashtree_disabled() const { return status_ == kFsManagerAvbHandleHashtreeDisabled; } const std::string& avb_version() const { return avb_version_; } FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy @@ -102,11 +112,19 @@ class FsManagerAvbHandle { }; private: - FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {} + enum AvbHandleStatus { + kAvbHandleSuccess = 0, + kAvbHandleUninitialized, + kAvbHandleHashtreeDisabled, + kAvbHandleVerificationDisabled, + kAvbHandleVerificationError, + }; + + FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kAvbHandleUninitialized) {} static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops); AvbSlotVerifyData* avb_slot_data_; - FsManagerAvbHandleStatus status_; + AvbHandleStatus status_; std::string avb_version_; }; diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp index 1e4654e96..e10c3b29c 100644 --- a/init/init_first_stage.cpp +++ b/init/init_first_stage.cpp @@ -310,17 +310,17 @@ bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) { if (fs_mgr_is_verified(fstab_rec)) { int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */); switch (ret) { - case FS_MGR_SETUP_VERITY_SKIPPED: - case FS_MGR_SETUP_VERITY_DISABLED: - LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'"; - break; - case FS_MGR_SETUP_VERITY_SUCCESS: - // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX". - // Needs to create it because ueventd isn't started in init first stage. - return InitVerityDevice(fstab_rec->blk_device); - break; - default: - return false; + case FS_MGR_SETUP_VERITY_SKIPPED: + case FS_MGR_SETUP_VERITY_DISABLED: + LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'"; + return true; + case FS_MGR_SETUP_VERITY_SUCCESS: + // The exact block device name (fstab_rec->blk_device) is changed to + // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init + // first stage. + return InitVerityDevice(fstab_rec->blk_device); + default: + return false; } } return true; // Returns true to mount the partition. @@ -409,14 +409,18 @@ ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) { bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) { if (fs_mgr_is_avb(fstab_rec)) { if (!InitAvbHandle()) return false; - if (avb_handle_->hashtree_disabled()) { - LOG(INFO) << "avb hashtree disabled for '" << fstab_rec->mount_point << "'"; - } else if (avb_handle_->SetUpAvb(fstab_rec, false /* wait_for_verity_dev */)) { - // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX". - // Needs to create it because ueventd isn't started in init first stage. - InitVerityDevice(fstab_rec->blk_device); - } else { - return false; + SetUpAvbHashtreeResult hashtree_result = + avb_handle_->SetUpAvbHashtree(fstab_rec, false /* wait_for_verity_dev */); + switch (hashtree_result) { + case SetUpAvbHashtreeResult::kDisabled: + return true; // Returns true to mount the partition. + case SetUpAvbHashtreeResult::kSuccess: + // The exact block device name (fstab_rec->blk_device) is changed to + // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init + // first stage. + return InitVerityDevice(fstab_rec->blk_device); + default: + return false; } } return true; // Returns true to mount the partition.