Merge "Set hashtree algorithm for verity partitions"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 2876094..1efe793 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -2143,6 +2143,41 @@
     return false;
 }
 
+std::string fs_mgr_get_hashtree_algorithm(const android::fs_mgr::FstabEntry& entry) {
+    if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
+        return "";
+    }
+    DeviceMapper& dm = DeviceMapper::Instance();
+    std::string device = GetVerityDeviceName(entry);
+
+    std::vector<DeviceMapper::TargetInfo> table;
+    if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
+        return "";
+    }
+    for (const auto& target : table) {
+        if (strcmp(target.spec.target_type, "verity") != 0) {
+            continue;
+        }
+
+        // The format is stable for dm-verity version 0 & 1. And the data is expected to have
+        // the fixed format:
+        // <version> <dev> <hash_dev> <data_block_size> <hash_block_size> <num_data_blocks>
+        // <hash_start_block> <algorithm> <digest> <salt>
+        // Details in https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html
+
+        std::vector<std::string> tokens = android::base::Split(target.data, " \t\r\n");
+        if (tokens[0] != "0" && tokens[0] != "1") {
+            LOG(WARNING) << "Unrecognized device mapper version in " << target.data;
+            return "";
+        }
+
+        // Hashtree algorithm is the 8th token in the output
+        return android::base::Trim(tokens[7]);
+    }
+
+    return "";
+}
+
 bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
     if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
         return false;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 11e3664..22c02cc 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -88,6 +88,10 @@
 bool fs_mgr_load_verity_state(int* mode);
 // Returns true if verity is enabled on this particular FstabEntry.
 bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry);
+// Returns the hash algorithm used to build the hashtree of this particular FstabEntry. Returns an
+// empty string if the input isn't a dm-verity entry, or if there is an error.
+std::string fs_mgr_get_hashtree_algorithm(const android::fs_mgr::FstabEntry& entry);
+
 bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
 bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
 
diff --git a/init/builtins.cpp b/init/builtins.cpp
index c44e03e..6b7d1e9 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -861,6 +861,11 @@
         // for system as root, so it has property [partition.system.verified].
         std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
         SetProperty("partition." + partition + ".verified", std::to_string(mode));
+
+        std::string hash_alg = fs_mgr_get_hashtree_algorithm(entry);
+        if (!hash_alg.empty()) {
+            SetProperty("partition." + partition + ".verified.hash_alg", hash_alg);
+        }
     }
 
     return {};