libsnapshot_fuzzer: Fuzz CreateUpdateSnapshots

Test: run it
Bug: 154633114
Change-Id: I56ed2953e85714d23a9273224a28eb8e8e47a54d
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index c1213f6..00991f4 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -256,30 +256,38 @@
     srcs: [
         // Compile the protobuf definition again with type full.
         "android/snapshot/snapshot_fuzz.proto",
+        "update_engine/update_metadata.proto",
         "fuzz_utils.cpp",
         "snapshot_fuzz.cpp",
         "snapshot_fuzz_utils.cpp",
+
+        // Compile libsnapshot sources directly to avoid dependency
+        // to update_metadata-protos
+        ":libsnapshot_sources",
     ],
     static_libs: [
         "libbase",
         "libcrypto_static",
         "libcutils",
+        "libext2_uuid",
+        "libext4_utils",
+        "libfstab",
         "libfs_mgr",
         "libgtest", // from libsnapshot_test_helpers
         "libgmock", // from libsnapshot_test_helpers
         "liblog",
         "liblp",
-        "libsnapshot_init", // don't use binder or hwbinder
         "libsnapshot_test_helpers",
         "libprotobuf-mutator",
-        "update_metadata-protos",
     ],
     header_libs: [
+        "libfiemap_headers",
         "libstorage_literals_headers",
     ],
     proto: {
         type: "full",
         canonical_path_from_root: false,
+        local_include_dirs: ["."],
     },
 
     fuzz_config: {
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
index 2df54e2..7e8559b 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
@@ -15,6 +15,8 @@
 syntax = "proto3";
 package android.snapshot;
 
+import "update_engine/update_metadata.proto";
+
 // Controls the behavior of IDeviceInfo.
 // Next: 6
 message FuzzDeviceInfoData {
@@ -49,8 +51,6 @@
         bool has_metadata_device_object = 1;
         bool metadata_mounted = 2;
     }
-    reserved 7;
-    reserved "create_update_snapshots";
     reserved 8;
     reserved "map_update_snapshot";
     oneof value {
@@ -60,6 +60,7 @@
         NoArgs initiate_merge = 4;
         ProcessUpdateStateArgs process_update_state = 5;
         bool get_update_state = 6;
+        chromeos_update_engine.DeltaArchiveManifest create_update_snapshots = 7;
         string unmap_update_snapshot = 9;
         NoArgs need_snapshots_in_first_stage_mount = 10;
         CreateLogicalAndSnapshotPartitionsArgs create_logical_and_snapshot_partitions = 11;
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz.cpp b/fs_mgr/libsnapshot/snapshot_fuzz.cpp
index 3e02ba7..ece1c06 100644
--- a/fs_mgr/libsnapshot/snapshot_fuzz.cpp
+++ b/fs_mgr/libsnapshot/snapshot_fuzz.cpp
@@ -35,6 +35,7 @@
 using android::fuzz::CheckedCast;
 using android::snapshot::SnapshotFuzzData;
 using android::snapshot::SnapshotFuzzEnv;
+using chromeos_update_engine::DeltaArchiveManifest;
 using google::protobuf::RepeatedPtrField;
 
 // Avoid linking to libgsi since it needs disk I/O.
@@ -102,6 +103,10 @@
     (void)snapshot->Dump(ss);
 }
 
+SNAPSHOT_FUZZ_FUNCTION(CreateUpdateSnapshots, const DeltaArchiveManifest& manifest) {
+    (void)snapshot->CreateUpdateSnapshots(manifest);
+}
+
 SNAPSHOT_FUZZ_FUNCTION(UnmapUpdateSnapshot, const std::string& name) {
     (void)snapshot->UnmapUpdateSnapshot(name);
 }
diff --git a/fs_mgr/libsnapshot/update_engine/update_metadata.proto b/fs_mgr/libsnapshot/update_engine/update_metadata.proto
new file mode 100644
index 0000000..be5e1fe
--- /dev/null
+++ b/fs_mgr/libsnapshot/update_engine/update_metadata.proto
@@ -0,0 +1,75 @@
+//
+// Copyright (C) 2020 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.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// A subset of system/update_engine/update_metadata.proto. A separate file is
+// used here because:
+// - The original file is optimized for LITE_RUNTIME, but fuzzing needs
+// reflection.
+// - The definition here has less fields. libsnapshot only uses fields declared
+// here, and all fields declared here are fuzzed by libsnapshot_fuzzer. If
+// libsnapshot uses more fields in system/update_engine/update_metadata.proto
+// in the future, they must be added here too, otherwise it will fail to
+// compile.
+//
+// It is okay that this file is older than
+// system/update_engine/update_metadata.proto as long as the messages defined
+// here can also be parsed by protobuf defined there. However, it is not
+// okay to add fields here without adding them to
+// system/update_engine/update_metadata.proto. Doing so will cause a compiler
+// error when libsnapshot code starts to use these dangling fields.
+
+syntax = "proto2";
+
+package chromeos_update_engine;
+
+message Extent {
+    optional uint64 start_block = 1;
+    optional uint64 num_blocks = 2;
+}
+
+message PartitionInfo {
+    optional uint64 size = 1;
+}
+
+message InstallOperation {
+    enum Type { SOURCE_COPY = 4; }
+    required Type type = 1;
+    repeated Extent src_extents = 4;
+    repeated Extent dst_extents = 6;
+}
+
+message PartitionUpdate {
+    required string partition_name = 1;
+    optional PartitionInfo new_partition_info = 7;
+    repeated InstallOperation operations = 8;
+    optional Extent hash_tree_extent = 11;
+    optional Extent fec_extent = 15;
+}
+
+message DynamicPartitionGroup {
+    required string name = 1;
+    optional uint64 size = 2;
+    repeated string partition_names = 3;
+}
+
+message DynamicPartitionMetadata {
+    repeated DynamicPartitionGroup groups = 1;
+}
+
+message DeltaArchiveManifest {
+    repeated PartitionUpdate partitions = 13;
+    optional DynamicPartitionMetadata dynamic_partition_metadata = 15;
+}