Merge "AVB: allow no metadata in the generic system.img for project Treble"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 5e0bfe4..8c19a81 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -839,7 +839,8 @@
                     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 @@
                     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 6618003..2c99aa7 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -114,7 +114,6 @@
 
 // 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 @@
     // 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 @@
     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 @@
         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 @@
     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::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,9 +506,8 @@
         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 @@
     //     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<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_ = 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 @@
     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 512839b..ba1262f 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -89,6 +89,15 @@
     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 @@
     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 bbafe1a..73a22c8 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 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 @@
     //   - 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 @@
     // 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 @@
     };
 
   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 1e4654e..e10c3b2 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -310,17 +310,17 @@
     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 @@
 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.