Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad692c9b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "AVB: allow no metadata in the generic system.img for project Treble" into oc-dr1-dev

parents 4d88b493 1773266f
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -851,7 +851,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. */
@@ -1071,7 +1072,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. */
+63 −44
Original line number Diff line number Diff line
@@ -114,7 +114,6 @@ static std::pair<size_t, bool> 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<FsManagerAvbVerifier>
    static std::unique_ptr<FsManagerAvbVerifier> 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> FsManagerAvbVerifier::Create() {
@@ -161,9 +158,7 @@ std::unique_ptr<FsManagerAvbVerifier> 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<FsManagerAvbVerifier> 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,8 +506,7 @@ FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
        return nullptr;
    }

    AvbSlotVerifyFlags flags = avb_verifier->IsDeviceUnlocked()
                                   ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
    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);

    if (verification_disabled) {
        avb_handle->status_ = kAvbHandleVerificationDisabled;
    } else {
        // Verifies vbmeta structs against the digest passed from bootloader in kernel cmdline.
        std::unique_ptr<FsManagerAvbVerifier> 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_ = kFsManagerAvbHandleHashtreeDisabled;
            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) {
    if (status_ == kAvbHandleHashtreeDisabled || status_ == kAvbHandleVerificationDisabled) {
        LINFO << "AVB HASHTREE disabled on: " << fstab_entry->mount_point;
        return true;
        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;
}
+10 −0
Original line number Diff line number Diff line
@@ -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;
+37 −19
Original line number Diff line number Diff line
@@ -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<FsManagerAvbHandle>;
using ByNameSymlinkMap = std::map<std::string, std::string>;

// 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);

    bool hashtree_disabled() const { return status_ == kFsManagerAvbHandleHashtreeDisabled; }
    //
    // 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);

    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_;
};

+23 −19
Original line number Diff line number Diff line
@@ -310,12 +310,12 @@ bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
            case FS_MGR_SETUP_VERITY_SKIPPED:
            case FS_MGR_SETUP_VERITY_DISABLED:
                LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'";
            break;
                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.
                // 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;
        }
@@ -406,13 +406,17 @@ 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 {
        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;
        }
    }