• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2018 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <libsnapshot/cow_format.h>
16 #include <libsnapshot/snapshot.h>
17 
18 #include <fcntl.h>
19 #include <signal.h>
20 #include <sys/file.h>
21 #include <sys/stat.h>
22 #include <sys/statvfs.h>
23 #include <sys/types.h>
24 
25 #include <chrono>
26 #include <deque>
27 #include <future>
28 #include <iostream>
29 
30 #include <aidl/android/hardware/boot/MergeStatus.h>
31 #include <android-base/file.h>
32 #include <android-base/logging.h>
33 #include <android-base/properties.h>
34 #include <android-base/strings.h>
35 #include <android-base/unique_fd.h>
36 #include <fs_mgr/file_wait.h>
37 #include <fs_mgr/roots.h>
38 #include <fs_mgr_dm_linear.h>
39 #include <gflags/gflags.h>
40 #include <gtest/gtest.h>
41 #include <libdm/dm.h>
42 #include <libfiemap/image_manager.h>
43 #include <liblp/builder.h>
44 #include <openssl/sha.h>
45 #include <storage_literals/storage_literals.h>
46 
47 #include <android/snapshot/snapshot.pb.h>
48 #include <libsnapshot/test_helpers.h>
49 #include "partition_cow_creator.h"
50 #include "scratch_super.h"
51 #include "utility.h"
52 
53 // Mock classes are not used. Header included to ensure mocked class definition aligns with the
54 // class itself.
55 #include <libsnapshot/mock_device_info.h>
56 #include <libsnapshot/mock_snapshot.h>
57 
58 #if defined(LIBSNAPSHOT_TEST_VAB_LEGACY)
59 #define DEFAULT_MODE "vab-legacy"
60 #else
61 #define DEFAULT_MODE ""
62 #endif
63 
64 DEFINE_string(force_mode, DEFAULT_MODE,
65               "Force testing older modes (vab-legacy) ignoring device config.");
66 DEFINE_string(force_iouring_disable, "",
67               "Force testing mode (iouring_disabled) - disable io_uring");
68 DEFINE_string(compression_method, "gz", "Default compression algorithm.");
69 
70 namespace android {
71 namespace snapshot {
72 
73 using android::base::unique_fd;
74 using android::dm::DeviceMapper;
75 using android::dm::DmDeviceState;
76 using android::dm::IDeviceMapper;
77 using android::fiemap::FiemapStatus;
78 using android::fiemap::IImageManager;
79 using android::fs_mgr::BlockDeviceInfo;
80 using android::fs_mgr::CreateLogicalPartitionParams;
81 using android::fs_mgr::DestroyLogicalPartition;
82 using android::fs_mgr::EnsurePathMounted;
83 using android::fs_mgr::EnsurePathUnmounted;
84 using android::fs_mgr::Extent;
85 using android::fs_mgr::Fstab;
86 using android::fs_mgr::GetPartitionGroupName;
87 using android::fs_mgr::GetPartitionName;
88 using android::fs_mgr::Interval;
89 using android::fs_mgr::MetadataBuilder;
90 using android::fs_mgr::SlotSuffixForSlotNumber;
91 using chromeos_update_engine::DeltaArchiveManifest;
92 using chromeos_update_engine::DynamicPartitionGroup;
93 using chromeos_update_engine::PartitionUpdate;
94 using namespace ::testing;
95 using namespace android::storage_literals;
96 using namespace std::chrono_literals;
97 using namespace std::string_literals;
98 
99 // Global states. See test_helpers.h.
100 std::unique_ptr<SnapshotManager> sm;
101 TestDeviceInfo* test_device = nullptr;
102 std::string fake_super;
103 
104 void MountMetadata();
105 
106 // @VsrTest = 3.7.6
107 class SnapshotTest : public ::testing::Test {
108   public:
SnapshotTest()109     SnapshotTest() : dm_(DeviceMapper::Instance()) {}
110 
111     // This is exposed for main.
Cleanup()112     void Cleanup() {
113         InitializeState();
114         CleanupTestArtifacts();
115     }
116 
117   protected:
SetUp()118     void SetUp() override {
119         const testing::TestInfo* const test_info =
120                 testing::UnitTest::GetInstance()->current_test_info();
121         test_name_ = test_info->test_suite_name() + "/"s + test_info->name();
122 
123         LOG(INFO) << "Starting test: " << test_name_;
124 
125         SKIP_IF_NON_VIRTUAL_AB();
126         SKIP_IF_VENDOR_ON_ANDROID_S();
127 
128         SetupProperties();
129         if (!DeviceSupportsMode()) {
130             GTEST_SKIP() << "Mode not supported on this device";
131         }
132 
133         InitializeState();
134         CleanupTestArtifacts();
135         FormatFakeSuper();
136         MountMetadata();
137         ASSERT_TRUE(sm->BeginUpdate());
138     }
139 
SetupProperties()140     void SetupProperties() {
141         std::unordered_map<std::string, std::string> properties;
142 
143         ASSERT_TRUE(android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0"))
144                 << "Failed to set property: snapuserd.test.io_uring.disabled";
145 
146         if (FLAGS_force_mode == "vab-legacy") {
147             properties["ro.virtual_ab.compression.enabled"] = "false";
148             properties["ro.virtual_ab.userspace.snapshots.enabled"] = "false";
149         }
150 
151         if (FLAGS_force_iouring_disable == "iouring_disabled") {
152             ASSERT_TRUE(android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1"))
153                     << "Failed to set property: snapuserd.test.io_uring.disabled";
154             properties["ro.virtual_ab.io_uring.enabled"] = "false";
155         }
156 
157         auto fetcher = std::make_unique<SnapshotTestPropertyFetcher>("_a", std::move(properties));
158         IPropertyFetcher::OverrideForTesting(std::move(fetcher));
159 
160         if (GetLegacyCompressionEnabledProperty() || CanUseUserspaceSnapshots()) {
161             // If we're asked to test the device's actual configuration, then it
162             // may be misconfigured, so check for kernel support as libsnapshot does.
163             if (FLAGS_force_mode.empty()) {
164                 snapuserd_required_ = KernelSupportsCompressedSnapshots();
165             } else {
166                 snapuserd_required_ = true;
167             }
168         }
169     }
170 
TearDown()171     void TearDown() override {
172         RETURN_IF_NON_VIRTUAL_AB();
173         RETURN_IF_VENDOR_ON_ANDROID_S();
174 
175         LOG(INFO) << "Tearing down SnapshotTest test: " << test_name_;
176 
177         lock_ = nullptr;
178 
179         CleanupTestArtifacts();
180         SnapshotTestPropertyFetcher::TearDown();
181 
182         LOG(INFO) << "Teardown complete for test: " << test_name_;
183     }
184 
DeviceSupportsMode()185     bool DeviceSupportsMode() {
186         if (FLAGS_force_mode.empty()) {
187             return true;
188         }
189         if (snapuserd_required_ && !KernelSupportsCompressedSnapshots()) {
190             return false;
191         }
192         return true;
193     }
194 
ShouldSkipLegacyMerging()195     bool ShouldSkipLegacyMerging() {
196         if (!GetLegacyCompressionEnabledProperty() || !snapuserd_required_) {
197             return false;
198         }
199         int api_level = android::base::GetIntProperty("ro.board.api_level", -1);
200         if (api_level == -1) {
201             api_level = android::base::GetIntProperty("ro.product.first_api_level", -1);
202         }
203         return api_level != __ANDROID_API_S__;
204     }
205 
InitializeState()206     void InitializeState() {
207         ASSERT_TRUE(sm->EnsureImageManager());
208         image_manager_ = sm->image_manager();
209 
210         test_device->set_slot_suffix("_a");
211 
212         sm->set_use_first_stage_snapuserd(false);
213     }
214 
CleanupTestArtifacts()215     void CleanupTestArtifacts() {
216         // Normally cancelling inside a merge is not allowed. Since these
217         // are tests, we don't care, destroy everything that might exist.
218         // Note we hardcode this list because of an annoying quirk: when
219         // completing a merge, the snapshot stops existing, so we can't
220         // get an accurate list to remove.
221         lock_ = nullptr;
222 
223         // If there is no image manager, the test was skipped.
224         if (!image_manager_) {
225             return;
226         }
227 
228         std::vector<std::string> snapshots = {"test-snapshot", "test_partition_a",
229                                               "test_partition_b"};
230         for (const auto& snapshot : snapshots) {
231             CleanupSnapshotArtifacts(snapshot);
232         }
233 
234         // Remove stale partitions in fake super.
235         std::vector<std::string> partitions = {
236                 "base-device",
237                 "test_partition_b",
238                 "test_partition_b-base",
239                 "test_partition_b-cow",
240         };
241         for (const auto& partition : partitions) {
242             DeleteDevice(partition);
243         }
244 
245         if (sm->GetUpdateState() != UpdateState::None) {
246             auto state_file = sm->GetStateFilePath();
247             unlink(state_file.c_str());
248         }
249     }
250 
CleanupSnapshotArtifacts(const std::string & snapshot)251     void CleanupSnapshotArtifacts(const std::string& snapshot) {
252         // The device-mapper stack may have been collapsed to dm-linear, so it's
253         // necessary to check what state it's in before attempting a cleanup.
254         // SnapshotManager has no path like this because we'd never remove a
255         // merged snapshot (a live partition).
256         bool is_dm_user = false;
257         DeviceMapper::TargetInfo target;
258         if (sm->IsSnapshotDevice(snapshot, &target)) {
259             is_dm_user = (DeviceMapper::GetTargetType(target.spec) == "user");
260         }
261 
262         if (is_dm_user) {
263             ASSERT_TRUE(sm->EnsureSnapuserdConnected());
264             ASSERT_TRUE(AcquireLock());
265 
266             auto local_lock = std::move(lock_);
267             ASSERT_TRUE(sm->UnmapUserspaceSnapshotDevice(local_lock.get(), snapshot));
268         }
269 
270         ASSERT_TRUE(DeleteSnapshotDevice(snapshot));
271         DeleteBackingImage(image_manager_, snapshot + "-cow-img");
272 
273         auto status_file = sm->GetSnapshotStatusFilePath(snapshot);
274         android::base::RemoveFileIfExists(status_file);
275     }
276 
AcquireLock()277     bool AcquireLock() {
278         lock_ = sm->LockExclusive();
279         return !!lock_;
280     }
281 
282     // This is so main() can instantiate this to invoke Cleanup.
TestBody()283     virtual void TestBody() override {}
284 
FormatFakeSuper()285     void FormatFakeSuper() {
286         BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4096);
287         std::vector<BlockDeviceInfo> devices = {super_device};
288 
289         auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
290         ASSERT_NE(builder, nullptr);
291 
292         auto metadata = builder->Export();
293         ASSERT_NE(metadata, nullptr);
294 
295         TestPartitionOpener opener(fake_super);
296         ASSERT_TRUE(FlashPartitionTable(opener, fake_super, *metadata.get()));
297     }
298 
299     // If |path| is non-null, the partition will be mapped after creation.
CreatePartition(const std::string & name,uint64_t size,std::string * path=nullptr,const std::optional<std::string> group={})300     bool CreatePartition(const std::string& name, uint64_t size, std::string* path = nullptr,
301                          const std::optional<std::string> group = {}) {
302         TestPartitionOpener opener(fake_super);
303         auto builder = MetadataBuilder::New(opener, "super", 0);
304         if (!builder) return false;
305 
306         std::string partition_group = std::string(android::fs_mgr::kDefaultGroup);
307         if (group) {
308             partition_group = *group;
309         }
310         return CreatePartition(builder.get(), name, size, path, partition_group);
311     }
312 
CreatePartition(MetadataBuilder * builder,const std::string & name,uint64_t size,std::string * path,const std::string & group)313     bool CreatePartition(MetadataBuilder* builder, const std::string& name, uint64_t size,
314                          std::string* path, const std::string& group) {
315         auto partition = builder->AddPartition(name, group, 0);
316         if (!partition) return false;
317         if (!builder->ResizePartition(partition, size)) {
318             return false;
319         }
320 
321         // Update the source slot.
322         auto metadata = builder->Export();
323         if (!metadata) return false;
324 
325         TestPartitionOpener opener(fake_super);
326         if (!UpdatePartitionTable(opener, "super", *metadata.get(), 0)) {
327             return false;
328         }
329 
330         if (!path) return true;
331 
332         CreateLogicalPartitionParams params = {
333                 .block_device = fake_super,
334                 .metadata = metadata.get(),
335                 .partition_name = name,
336                 .force_writable = true,
337                 .timeout_ms = 10s,
338         };
339         return CreateLogicalPartition(params, path);
340     }
341 
MapUpdateSnapshot(const std::string & name,std::unique_ptr<ICowWriter> * writer)342     AssertionResult MapUpdateSnapshot(const std::string& name,
343                                       std::unique_ptr<ICowWriter>* writer) {
344         TestPartitionOpener opener(fake_super);
345         CreateLogicalPartitionParams params{
346                 .block_device = fake_super,
347                 .metadata_slot = 1,
348                 .partition_name = name,
349                 .timeout_ms = 10s,
350                 .partition_opener = &opener,
351         };
352 
353         auto result = sm->OpenSnapshotWriter(params, {});
354         if (!result) {
355             return AssertionFailure() << "Cannot open snapshot for writing: " << name;
356         }
357 
358         if (writer) {
359             *writer = std::move(result);
360         }
361         return AssertionSuccess();
362     }
363 
MapUpdateSnapshot(const std::string & name,std::string * path)364     AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path) {
365         TestPartitionOpener opener(fake_super);
366         CreateLogicalPartitionParams params{
367                 .block_device = fake_super,
368                 .metadata_slot = 1,
369                 .partition_name = name,
370                 .timeout_ms = 10s,
371                 .partition_opener = &opener,
372         };
373 
374         auto result = sm->MapUpdateSnapshot(params, path);
375         if (!result) {
376             return AssertionFailure() << "Cannot open snapshot for writing: " << name;
377         }
378         return AssertionSuccess();
379     }
380 
DeleteSnapshotDevice(const std::string & snapshot)381     AssertionResult DeleteSnapshotDevice(const std::string& snapshot) {
382         AssertionResult res = AssertionSuccess();
383         if (!(res = DeleteDevice(snapshot))) return res;
384         if (!sm->UnmapDmUserDevice(snapshot + "-user-cow")) {
385             return AssertionFailure() << "Cannot delete dm-user device for " << snapshot;
386         }
387         if (!(res = DeleteDevice(snapshot + "-inner"))) return res;
388         if (!(res = DeleteDevice(snapshot + "-cow"))) return res;
389         if (!image_manager_->UnmapImageIfExists(snapshot + "-cow-img")) {
390             return AssertionFailure() << "Cannot unmap image " << snapshot << "-cow-img";
391         }
392         if (!(res = DeleteDevice(snapshot + "-base"))) return res;
393         if (!(res = DeleteDevice(snapshot + "-src"))) return res;
394         return AssertionSuccess();
395     }
396 
DeleteDevice(const std::string & device)397     AssertionResult DeleteDevice(const std::string& device) {
398         if (!sm->DeleteDeviceIfExists(device, 1s)) {
399             return AssertionFailure() << "Can't delete " << device;
400         }
401         return AssertionSuccess();
402     }
403 
CreateCowImage(const std::string & name)404     AssertionResult CreateCowImage(const std::string& name) {
405         if (!sm->CreateCowImage(lock_.get(), name)) {
406             return AssertionFailure() << "Cannot create COW image " << name;
407         }
408         std::string cow_device;
409         auto map_res = MapCowImage(name, 10s, &cow_device);
410         if (!map_res) {
411             return map_res;
412         }
413         if (!InitializeKernelCow(cow_device)) {
414             return AssertionFailure() << "Cannot zero fill " << cow_device;
415         }
416         if (!sm->UnmapCowImage(name)) {
417             return AssertionFailure() << "Cannot unmap " << name << " after zero filling it";
418         }
419         return AssertionSuccess();
420     }
421 
MapCowImage(const std::string & name,const std::chrono::milliseconds & timeout_ms,std::string * path)422     AssertionResult MapCowImage(const std::string& name,
423                                 const std::chrono::milliseconds& timeout_ms, std::string* path) {
424         auto cow_image_path = sm->MapCowImage(name, timeout_ms);
425         if (!cow_image_path.has_value()) {
426             return AssertionFailure() << "Cannot map cow image " << name;
427         }
428         *path = *cow_image_path;
429         return AssertionSuccess();
430     }
431 
432     // Prepare A/B slot for a partition named "test_partition".
PrepareOneSnapshot(uint64_t device_size,std::unique_ptr<ICowWriter> * writer=nullptr)433     AssertionResult PrepareOneSnapshot(uint64_t device_size,
434                                        std::unique_ptr<ICowWriter>* writer = nullptr) {
435         lock_ = nullptr;
436 
437         DeltaArchiveManifest manifest;
438 
439         auto dynamic_partition_metadata = manifest.mutable_dynamic_partition_metadata();
440         dynamic_partition_metadata->set_vabc_enabled(snapuserd_required_);
441         dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
442         if (snapuserd_required_) {
443             dynamic_partition_metadata->set_vabc_compression_param(FLAGS_compression_method);
444         }
445 
446         auto group = dynamic_partition_metadata->add_groups();
447         group->set_name("group");
448         group->set_size(device_size * 2);
449         group->add_partition_names("test_partition");
450 
451         auto pu = manifest.add_partitions();
452         pu->set_partition_name("test_partition");
453         pu->set_estimate_cow_size(device_size);
454         SetSize(pu, device_size);
455 
456         auto extent = pu->add_operations()->add_dst_extents();
457         extent->set_start_block(0);
458         if (device_size) {
459             extent->set_num_blocks(device_size / manifest.block_size());
460         }
461 
462         TestPartitionOpener opener(fake_super);
463         auto builder = MetadataBuilder::New(opener, "super", 0);
464         if (!builder) {
465             return AssertionFailure() << "Failed to open MetadataBuilder";
466         }
467         builder->AddGroup("group_a", 16_GiB);
468         builder->AddGroup("group_b", 16_GiB);
469         if (!CreatePartition(builder.get(), "test_partition_a", device_size, nullptr, "group_a")) {
470             return AssertionFailure() << "Failed create test_partition_a";
471         }
472 
473         if (!sm->CreateUpdateSnapshots(manifest)) {
474             return AssertionFailure() << "Failed to create update snapshots";
475         }
476 
477         if (writer) {
478             auto res = MapUpdateSnapshot("test_partition_b", writer);
479             if (!res) {
480                 return res;
481             }
482         } else if (!snapuserd_required_) {
483             std::string ignore;
484             if (!MapUpdateSnapshot("test_partition_b", &ignore)) {
485                 return AssertionFailure() << "Failed to map test_partition_b";
486             }
487         }
488         if (!AcquireLock()) {
489             return AssertionFailure() << "Failed to acquire lock";
490         }
491         return AssertionSuccess();
492     }
493 
494     // Simulate a reboot into the new slot.
SimulateReboot()495     AssertionResult SimulateReboot() {
496         lock_ = nullptr;
497         if (!sm->FinishedSnapshotWrites(false)) {
498             return AssertionFailure() << "Failed to finish snapshot writes";
499         }
500         if (!sm->UnmapUpdateSnapshot("test_partition_b")) {
501             return AssertionFailure() << "Failed to unmap COW for test_partition_b";
502         }
503         if (!dm_.DeleteDeviceIfExists("test_partition_b")) {
504             return AssertionFailure() << "Failed to delete test_partition_b";
505         }
506         if (!dm_.DeleteDeviceIfExists("test_partition_b-base")) {
507             return AssertionFailure() << "Failed to destroy test_partition_b-base";
508         }
509         return AssertionSuccess();
510     }
511 
NewManagerForFirstStageMount(const std::string & slot_suffix="_a")512     std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(
513             const std::string& slot_suffix = "_a") {
514         auto info = new TestDeviceInfo(fake_super, slot_suffix);
515         return NewManagerForFirstStageMount(info);
516     }
517 
NewManagerForFirstStageMount(TestDeviceInfo * info)518     std::unique_ptr<SnapshotManager> NewManagerForFirstStageMount(TestDeviceInfo* info) {
519         info->set_first_stage_init(true);
520         auto init = SnapshotManager::NewForFirstStageMount(info);
521         if (!init) {
522             return nullptr;
523         }
524         init->SetUeventRegenCallback([](const std::string& device) -> bool {
525             return android::fs_mgr::WaitForFile(device, snapshot_timeout_);
526         });
527         return init;
528     }
529 
530     static constexpr std::chrono::milliseconds snapshot_timeout_ = 5s;
531     DeviceMapper& dm_;
532     std::unique_ptr<SnapshotManager::LockedFile> lock_;
533     android::fiemap::IImageManager* image_manager_ = nullptr;
534     std::string fake_super_;
535     bool snapuserd_required_ = false;
536     std::string test_name_;
537 };
538 
TEST_F(SnapshotTest,CreateSnapshot)539 TEST_F(SnapshotTest, CreateSnapshot) {
540     ASSERT_TRUE(AcquireLock());
541 
542     PartitionCowCreator cow_creator;
543     cow_creator.using_snapuserd = snapuserd_required_;
544     if (cow_creator.using_snapuserd) {
545         cow_creator.compression_algorithm = FLAGS_compression_method;
546     } else {
547         cow_creator.compression_algorithm = "none";
548     }
549 
550     static const uint64_t kDeviceSize = 1024 * 1024;
551     SnapshotStatus status;
552     status.set_name("test-snapshot");
553     status.set_device_size(kDeviceSize);
554     status.set_snapshot_size(kDeviceSize);
555     status.set_cow_file_size(kDeviceSize);
556     ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
557     ASSERT_TRUE(CreateCowImage("test-snapshot"));
558 
559     std::vector<std::string> snapshots;
560     ASSERT_TRUE(sm->ListSnapshots(lock_.get(), &snapshots));
561     ASSERT_EQ(snapshots.size(), 1);
562     ASSERT_EQ(snapshots[0], "test-snapshot");
563 
564     // Scope so delete can re-acquire the snapshot file lock.
565     {
566         SnapshotStatus status;
567         ASSERT_TRUE(sm->ReadSnapshotStatus(lock_.get(), "test-snapshot", &status));
568         ASSERT_EQ(status.state(), SnapshotState::CREATED);
569         ASSERT_EQ(status.device_size(), kDeviceSize);
570         ASSERT_EQ(status.snapshot_size(), kDeviceSize);
571         ASSERT_EQ(status.using_snapuserd(), cow_creator.using_snapuserd);
572         ASSERT_EQ(status.compression_algorithm(), cow_creator.compression_algorithm);
573     }
574 
575     ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
576     ASSERT_TRUE(sm->UnmapCowImage("test-snapshot"));
577     ASSERT_TRUE(sm->DeleteSnapshot(lock_.get(), "test-snapshot"));
578 }
579 
TEST_F(SnapshotTest,MapSnapshot)580 TEST_F(SnapshotTest, MapSnapshot) {
581     ASSERT_TRUE(AcquireLock());
582 
583     PartitionCowCreator cow_creator;
584     cow_creator.using_snapuserd = snapuserd_required_;
585 
586     static const uint64_t kDeviceSize = 1024 * 1024;
587     SnapshotStatus status;
588     status.set_name("test-snapshot");
589     status.set_device_size(kDeviceSize);
590     status.set_snapshot_size(kDeviceSize);
591     status.set_cow_file_size(kDeviceSize);
592     ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
593     ASSERT_TRUE(CreateCowImage("test-snapshot"));
594 
595     std::string base_device;
596     ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
597 
598     std::string cow_device;
599     ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
600 
601     std::string snap_device;
602     ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
603                                 &snap_device));
604     ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
605 }
606 
TEST_F(SnapshotTest,NoMergeBeforeReboot)607 TEST_F(SnapshotTest, NoMergeBeforeReboot) {
608     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
609 
610     // Merge should fail, since the slot hasn't changed.
611     ASSERT_FALSE(sm->InitiateMerge());
612 }
613 
TEST_F(SnapshotTest,CleanFirstStageMount)614 TEST_F(SnapshotTest, CleanFirstStageMount) {
615     // If there's no update in progress, there should be no first-stage mount
616     // needed.
617     auto sm = NewManagerForFirstStageMount();
618     ASSERT_NE(sm, nullptr);
619     ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
620 }
621 
TEST_F(SnapshotTest,FirstStageMountAfterRollback)622 TEST_F(SnapshotTest, FirstStageMountAfterRollback) {
623     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
624 
625     // We didn't change the slot, so we shouldn't need snapshots.
626     auto sm = NewManagerForFirstStageMount();
627     ASSERT_NE(sm, nullptr);
628     ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
629 
630     auto indicator = sm->GetRollbackIndicatorPath();
631     ASSERT_EQ(access(indicator.c_str(), R_OK), 0);
632 }
633 
TEST_F(SnapshotTest,Merge)634 TEST_F(SnapshotTest, Merge) {
635     ASSERT_TRUE(AcquireLock());
636 
637     static constexpr uint64_t kDeviceSize = 1024 * 1024;
638     static constexpr uint32_t kBlockSize = 4096;
639 
640     std::string test_string = "This is a test string.";
641     test_string.resize(kBlockSize);
642 
643     bool userspace_snapshots = false;
644     if (snapuserd_required_) {
645         std::unique_ptr<ICowWriter> writer;
646         ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &writer));
647 
648         userspace_snapshots = sm->UpdateUsesUserSnapshots(lock_.get());
649 
650         // Release the lock.
651         lock_ = nullptr;
652 
653         ASSERT_TRUE(writer->AddRawBlocks(0, test_string.data(), test_string.size()));
654         ASSERT_TRUE(writer->Finalize());
655         writer = nullptr;
656     } else {
657         ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
658 
659         // Release the lock.
660         lock_ = nullptr;
661 
662         std::string path;
663         ASSERT_TRUE(dm_.GetDmDevicePathByName("test_partition_b", &path));
664 
665         unique_fd fd(open(path.c_str(), O_WRONLY));
666         ASSERT_GE(fd, 0);
667         ASSERT_TRUE(android::base::WriteFully(fd, test_string.data(), test_string.size()));
668     }
669 
670     // Done updating.
671     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
672 
673     ASSERT_TRUE(sm->UnmapUpdateSnapshot("test_partition_b"));
674 
675     test_device->set_slot_suffix("_b");
676     ASSERT_TRUE(sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
677     if (ShouldSkipLegacyMerging()) {
678         LOG(INFO) << "Skipping legacy merge in test";
679         return;
680     }
681     ASSERT_TRUE(sm->InitiateMerge());
682 
683     // Create stale files in snapshot directory. Merge should skip these files
684     // as the suffix doesn't match the current slot.
685     auto tmp_path = test_device->GetMetadataDir() + "/snapshots/test_partition_b.tmp";
686     auto other_slot = test_device->GetMetadataDir() + "/snapshots/test_partition_a";
687 
688     unique_fd fd(open(tmp_path.c_str(), O_RDWR | O_CLOEXEC | O_CREAT, 0644));
689     ASSERT_GE(fd, 0);
690 
691     fd.reset(open(other_slot.c_str(), O_RDWR | O_CLOEXEC | O_CREAT, 0644));
692     ASSERT_GE(fd, 0);
693 
694     // The device should have been switched to a snapshot-merge target.
695     DeviceMapper::TargetInfo target;
696     ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
697     if (userspace_snapshots) {
698         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
699     } else {
700         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
701     }
702 
703     // We should not be able to cancel an update now.
704     ASSERT_EQ(sm->TryCancelUpdate(), CancelResult::NEEDS_MERGE);
705     ASSERT_FALSE(sm->CancelUpdate());
706 
707     ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::MergeCompleted);
708     ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
709 
710     // Make sure that snapshot states are cleared and all stale files
711     // are deleted
712     {
713         ASSERT_TRUE(AcquireLock());
714         auto local_lock = std::move(lock_);
715         std::vector<std::string> snapshots;
716         ASSERT_TRUE(sm->ListSnapshots(local_lock.get(), &snapshots));
717         ASSERT_TRUE(snapshots.empty());
718     }
719 
720     // The device should no longer be a snapshot or snapshot-merge.
721     ASSERT_FALSE(sm->IsSnapshotDevice("test_partition_b"));
722 
723     // Test that we can read back the string we wrote to the snapshot. Note
724     // that the base device is gone now. |snap_device| contains the correct
725     // partition.
726     fd.reset(open("/dev/block/mapper/test_partition_b", O_RDONLY | O_CLOEXEC));
727     ASSERT_GE(fd, 0);
728 
729     std::string buffer(test_string.size(), '\0');
730     ASSERT_TRUE(android::base::ReadFully(fd, buffer.data(), buffer.size()));
731     ASSERT_EQ(test_string, buffer);
732 }
733 
TEST_F(SnapshotTest,FirstStageMountAndMerge)734 TEST_F(SnapshotTest, FirstStageMountAndMerge) {
735     ASSERT_TRUE(AcquireLock());
736 
737     static const uint64_t kDeviceSize = 1024 * 1024;
738     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
739     ASSERT_TRUE(SimulateReboot());
740 
741     auto init = NewManagerForFirstStageMount("_b");
742     ASSERT_NE(init, nullptr);
743     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
744     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
745 
746     ASSERT_TRUE(AcquireLock());
747 
748     bool userspace_snapshots = init->UpdateUsesUserSnapshots(lock_.get());
749 
750     // Validate that we have a snapshot device.
751     SnapshotStatus status;
752     ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
753     ASSERT_EQ(status.state(), SnapshotState::CREATED);
754     if (snapuserd_required_) {
755         ASSERT_EQ(status.compression_algorithm(), FLAGS_compression_method);
756     } else {
757         ASSERT_EQ(status.compression_algorithm(), "");
758     }
759 
760     DeviceMapper::TargetInfo target;
761     ASSERT_TRUE(init->IsSnapshotDevice("test_partition_b", &target));
762     if (userspace_snapshots) {
763         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
764     } else {
765         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
766     }
767 }
768 
TEST_F(SnapshotTest,FlashSuperDuringUpdate)769 TEST_F(SnapshotTest, FlashSuperDuringUpdate) {
770     ASSERT_TRUE(AcquireLock());
771 
772     static const uint64_t kDeviceSize = 1024 * 1024;
773     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
774     ASSERT_TRUE(SimulateReboot());
775 
776     // Reflash the super partition.
777     FormatFakeSuper();
778     ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
779 
780     auto init = NewManagerForFirstStageMount("_b");
781     ASSERT_NE(init, nullptr);
782     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
783     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
784 
785     ASSERT_TRUE(AcquireLock());
786 
787     SnapshotStatus status;
788     ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
789 
790     // We should not get a snapshot device now.
791     DeviceMapper::TargetInfo target;
792     ASSERT_FALSE(init->IsSnapshotDevice("test_partition_b", &target));
793 
794     // We should see a cancelled update as well.
795     lock_ = nullptr;
796     ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
797 }
798 
TEST_F(SnapshotTest,FlashSuperDuringMerge)799 TEST_F(SnapshotTest, FlashSuperDuringMerge) {
800     ASSERT_TRUE(AcquireLock());
801 
802     static const uint64_t kDeviceSize = 1024 * 1024;
803     ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
804     ASSERT_TRUE(SimulateReboot());
805 
806     auto init = NewManagerForFirstStageMount("_b");
807     ASSERT_NE(init, nullptr);
808     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
809     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
810     if (ShouldSkipLegacyMerging()) {
811         LOG(INFO) << "Skipping legacy merge in test";
812         return;
813     }
814     ASSERT_TRUE(init->InitiateMerge());
815 
816     // Now, reflash super. Note that we haven't called ProcessUpdateState, so the
817     // status is still Merging.
818     ASSERT_TRUE(DeleteSnapshotDevice("test_partition_b"));
819     ASSERT_TRUE(init->image_manager()->UnmapImageIfExists("test_partition_b-cow-img"));
820     FormatFakeSuper();
821     ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
822     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
823     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
824 
825     // Because the status is Merging, we must call ProcessUpdateState, which should
826     // detect a cancelled update.
827     ASSERT_EQ(init->ProcessUpdateState(), UpdateState::Cancelled);
828     ASSERT_EQ(init->GetUpdateState(), UpdateState::None);
829 }
830 
TEST_F(SnapshotTest,UpdateBootControlHal)831 TEST_F(SnapshotTest, UpdateBootControlHal) {
832     ASSERT_TRUE(AcquireLock());
833 
834     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
835     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
836 
837     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
838     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
839 
840     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
841     ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
842 
843     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
844     ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
845 
846     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
847     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
848 
849     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
850     ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
851 
852     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
853     ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
854 }
855 
TEST_F(SnapshotTest,MergeFailureCode)856 TEST_F(SnapshotTest, MergeFailureCode) {
857     ASSERT_TRUE(AcquireLock());
858 
859     ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed,
860                                      MergeFailureCode::ListSnapshots));
861     ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
862 
863     SnapshotUpdateStatus status = sm->ReadSnapshotUpdateStatus(lock_.get());
864     ASSERT_EQ(status.state(), UpdateState::MergeFailed);
865     ASSERT_EQ(status.merge_failure_code(), MergeFailureCode::ListSnapshots);
866 }
867 
868 enum class Request { UNKNOWN, LOCK_SHARED, LOCK_EXCLUSIVE, UNLOCK, EXIT };
operator <<(std::ostream & os,Request request)869 std::ostream& operator<<(std::ostream& os, Request request) {
870     switch (request) {
871         case Request::LOCK_SHARED:
872             return os << "Shared";
873         case Request::LOCK_EXCLUSIVE:
874             return os << "Exclusive";
875         case Request::UNLOCK:
876             return os << "Unlock";
877         case Request::EXIT:
878             return os << "Exit";
879         case Request::UNKNOWN:
880             [[fallthrough]];
881         default:
882             return os << "Unknown";
883     }
884 }
885 
886 class LockTestConsumer {
887   public:
MakeRequest(Request new_request)888     AssertionResult MakeRequest(Request new_request) {
889         {
890             std::unique_lock<std::mutex> ulock(mutex_);
891             requests_.push_back(new_request);
892         }
893         cv_.notify_all();
894         return AssertionSuccess() << "Request " << new_request << " successful";
895     }
896 
897     template <typename R, typename P>
WaitFulfill(std::chrono::duration<R,P> timeout)898     AssertionResult WaitFulfill(std::chrono::duration<R, P> timeout) {
899         std::unique_lock<std::mutex> ulock(mutex_);
900         if (cv_.wait_for(ulock, timeout, [this] { return requests_.empty(); })) {
901             return AssertionSuccess() << "All requests_ fulfilled.";
902         }
903         return AssertionFailure() << "Timeout waiting for fulfilling " << requests_.size()
904                                   << " request(s), first one is "
905                                   << (requests_.empty() ? Request::UNKNOWN : requests_.front());
906     }
907 
StartHandleRequestsInBackground()908     void StartHandleRequestsInBackground() {
909         future_ = std::async(std::launch::async, &LockTestConsumer::HandleRequests, this);
910     }
911 
912   private:
HandleRequests()913     void HandleRequests() {
914         static constexpr auto consumer_timeout = 3s;
915 
916         auto next_request = Request::UNKNOWN;
917         do {
918             // Peek next request.
919             {
920                 std::unique_lock<std::mutex> ulock(mutex_);
921                 if (cv_.wait_for(ulock, consumer_timeout, [this] { return !requests_.empty(); })) {
922                     next_request = requests_.front();
923                 } else {
924                     next_request = Request::EXIT;
925                 }
926             }
927 
928             // Handle next request.
929             switch (next_request) {
930                 case Request::LOCK_SHARED: {
931                     lock_ = sm->LockShared();
932                 } break;
933                 case Request::LOCK_EXCLUSIVE: {
934                     lock_ = sm->LockExclusive();
935                 } break;
936                 case Request::EXIT:
937                     [[fallthrough]];
938                 case Request::UNLOCK: {
939                     lock_.reset();
940                 } break;
941                 case Request::UNKNOWN:
942                     [[fallthrough]];
943                 default:
944                     break;
945             }
946 
947             // Pop next request. This thread is the only thread that
948             // pops from the front of the requests_ deque.
949             {
950                 std::unique_lock<std::mutex> ulock(mutex_);
951                 if (next_request == Request::EXIT) {
952                     requests_.clear();
953                 } else {
954                     requests_.pop_front();
955                 }
956             }
957             cv_.notify_all();
958         } while (next_request != Request::EXIT);
959     }
960 
961     std::mutex mutex_;
962     std::condition_variable cv_;
963     std::deque<Request> requests_;
964     std::unique_ptr<SnapshotManager::LockedFile> lock_;
965     std::future<void> future_;
966 };
967 
968 class LockTest : public ::testing::Test {
969   public:
SetUp()970     void SetUp() {
971         SKIP_IF_NON_VIRTUAL_AB();
972         first_consumer.StartHandleRequestsInBackground();
973         second_consumer.StartHandleRequestsInBackground();
974     }
975 
TearDown()976     void TearDown() {
977         RETURN_IF_NON_VIRTUAL_AB();
978         EXPECT_TRUE(first_consumer.MakeRequest(Request::EXIT));
979         EXPECT_TRUE(second_consumer.MakeRequest(Request::EXIT));
980     }
981 
982     static constexpr auto request_timeout = 500ms;
983     LockTestConsumer first_consumer;
984     LockTestConsumer second_consumer;
985 };
986 
TEST_F(LockTest,SharedShared)987 TEST_F(LockTest, SharedShared) {
988     ASSERT_TRUE(first_consumer.MakeRequest(Request::LOCK_SHARED));
989     ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
990     ASSERT_TRUE(second_consumer.MakeRequest(Request::LOCK_SHARED));
991     ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout));
992 }
993 
994 using LockTestParam = std::pair<Request, Request>;
995 class LockTestP : public LockTest, public ::testing::WithParamInterface<LockTestParam> {};
TEST_P(LockTestP,Test)996 TEST_P(LockTestP, Test) {
997     ASSERT_TRUE(first_consumer.MakeRequest(GetParam().first));
998     ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
999     ASSERT_TRUE(second_consumer.MakeRequest(GetParam().second));
1000     ASSERT_FALSE(second_consumer.WaitFulfill(request_timeout))
1001             << "Should not be able to " << GetParam().second << " while separate thread "
1002             << GetParam().first;
1003     ASSERT_TRUE(first_consumer.MakeRequest(Request::UNLOCK));
1004     ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout))
1005             << "Should be able to hold lock that is released by separate thread";
1006 }
1007 INSTANTIATE_TEST_SUITE_P(
1008         LockTest, LockTestP,
1009         testing::Values(LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_EXCLUSIVE},
1010                         LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_SHARED},
1011                         LockTestParam{Request::LOCK_SHARED, Request::LOCK_EXCLUSIVE}),
__anon1b9e41e40402(const testing::TestParamInfo<LockTestP::ParamType>& info) 1012         [](const testing::TestParamInfo<LockTestP::ParamType>& info) {
1013             std::stringstream ss;
1014             ss << info.param.first << info.param.second;
1015             return ss.str();
1016         });
1017 
1018 class SnapshotUpdateTest : public SnapshotTest {
1019   public:
SetUp()1020     void SetUp() override {
1021         SKIP_IF_NON_VIRTUAL_AB();
1022         SKIP_IF_VENDOR_ON_ANDROID_S();
1023 
1024         SnapshotTest::SetUp();
1025         if (!image_manager_) {
1026             // Test was skipped.
1027             return;
1028         }
1029 
1030         Cleanup();
1031 
1032         // Cleanup() changes slot suffix, so initialize it again.
1033         test_device->set_slot_suffix("_a");
1034 
1035         opener_ = std::make_unique<TestPartitionOpener>(fake_super);
1036 
1037         auto dynamic_partition_metadata = manifest_.mutable_dynamic_partition_metadata();
1038         dynamic_partition_metadata->set_vabc_enabled(snapuserd_required_);
1039         dynamic_partition_metadata->set_cow_version(android::snapshot::kCowVersionMajor);
1040         if (snapuserd_required_) {
1041             dynamic_partition_metadata->set_vabc_compression_param(FLAGS_compression_method);
1042         }
1043 
1044         // Create a fake update package metadata.
1045         // Not using full name "system", "vendor", "product" because these names collide with the
1046         // mapped partitions on the running device.
1047         // Each test modifies manifest_ slightly to indicate changes to the partition layout.
1048         group_ = dynamic_partition_metadata->add_groups();
1049         group_->set_name("group");
1050         group_->set_size(kGroupSize);
1051         group_->add_partition_names("sys");
1052         group_->add_partition_names("vnd");
1053         group_->add_partition_names("prd");
1054         sys_ = manifest_.add_partitions();
1055         sys_->set_partition_name("sys");
1056         sys_->set_estimate_cow_size(2_MiB);
1057         SetSize(sys_, 3_MiB);
1058         vnd_ = manifest_.add_partitions();
1059         vnd_->set_partition_name("vnd");
1060         vnd_->set_estimate_cow_size(2_MiB);
1061         SetSize(vnd_, 3_MiB);
1062         prd_ = manifest_.add_partitions();
1063         prd_->set_partition_name("prd");
1064         prd_->set_estimate_cow_size(2_MiB);
1065         SetSize(prd_, 3_MiB);
1066 
1067         // Initialize source partition metadata using |manifest_|.
1068         src_ = MetadataBuilder::New(*opener_, "super", 0);
1069         ASSERT_NE(src_, nullptr);
1070         ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
1071         // Add sys_b which is like system_other.
1072         ASSERT_TRUE(src_->AddGroup("group_b", kGroupSize));
1073         auto partition = src_->AddPartition("sys_b", "group_b", 0);
1074         ASSERT_NE(nullptr, partition);
1075         ASSERT_TRUE(src_->ResizePartition(partition, 1_MiB));
1076         auto metadata = src_->Export();
1077         ASSERT_NE(nullptr, metadata);
1078         ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1079 
1080         // Map source partitions.
1081         std::string path;
1082         for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1083             ASSERT_TRUE(CreateLogicalPartition(
1084                     CreateLogicalPartitionParams{
1085                             .block_device = fake_super,
1086                             .metadata_slot = 0,
1087                             .partition_name = name,
1088                             .timeout_ms = 1s,
1089                             .partition_opener = opener_.get(),
1090                     },
1091                     &path));
1092             ASSERT_TRUE(WriteRandomData(path));
1093             auto hash = GetHash(path);
1094             ASSERT_TRUE(hash.has_value());
1095             hashes_[name] = *hash;
1096         }
1097 
1098         // OTA client blindly unmaps all partitions that are possibly mapped.
1099         for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1100             ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
1101         }
1102     }
TearDown()1103     void TearDown() override {
1104         RETURN_IF_NON_VIRTUAL_AB();
1105         RETURN_IF_VENDOR_ON_ANDROID_S();
1106 
1107         LOG(INFO) << "Tearing down SnapshotUpdateTest test: " << test_name_;
1108 
1109         Cleanup();
1110         SnapshotTest::TearDown();
1111     }
Cleanup()1112     void Cleanup() {
1113         if (!image_manager_) {
1114             InitializeState();
1115         }
1116         MountMetadata();
1117         for (const auto& suffix : {"_a", "_b"}) {
1118             test_device->set_slot_suffix(suffix);
1119 
1120             // Cheat our way out of merge failed states.
1121             if (sm->ProcessUpdateState() == UpdateState::MergeFailed) {
1122                 ASSERT_TRUE(AcquireLock());
1123                 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
1124                 lock_ = {};
1125             }
1126 
1127             EXPECT_TRUE(sm->CancelUpdate()) << suffix;
1128         }
1129         EXPECT_TRUE(UnmapAll());
1130     }
1131 
IsPartitionUnchanged(const std::string & name)1132     AssertionResult IsPartitionUnchanged(const std::string& name) {
1133         std::string path;
1134         if (!dm_.GetDmDevicePathByName(name, &path)) {
1135             return AssertionFailure() << "Path of " << name << " cannot be determined";
1136         }
1137         auto hash = GetHash(path);
1138         if (!hash.has_value()) {
1139             return AssertionFailure() << "Cannot read partition " << name << ": " << path;
1140         }
1141         auto it = hashes_.find(name);
1142         if (it == hashes_.end()) {
1143             return AssertionFailure() << "No existing hash for " << name << ". Bad test code?";
1144         }
1145         if (it->second != *hash) {
1146             return AssertionFailure() << "Content of " << name << " has changed";
1147         }
1148         return AssertionSuccess();
1149     }
1150 
GetSnapshotSize(const std::string & name)1151     std::optional<uint64_t> GetSnapshotSize(const std::string& name) {
1152         if (!AcquireLock()) {
1153             return std::nullopt;
1154         }
1155         auto local_lock = std::move(lock_);
1156 
1157         SnapshotStatus status;
1158         if (!sm->ReadSnapshotStatus(local_lock.get(), name, &status)) {
1159             return std::nullopt;
1160         }
1161         return status.snapshot_size();
1162     }
1163 
UnmapAll()1164     AssertionResult UnmapAll() {
1165         for (const auto& name : {"sys", "vnd", "prd", "dlkm"}) {
1166             if (!dm_.DeleteDeviceIfExists(name + "_a"s)) {
1167                 return AssertionFailure() << "Cannot unmap " << name << "_a";
1168             }
1169             if (!DeleteSnapshotDevice(name + "_b"s)) {
1170                 return AssertionFailure() << "Cannot delete snapshot " << name << "_b";
1171             }
1172         }
1173         return AssertionSuccess();
1174     }
1175 
MapOneUpdateSnapshot(const std::string & name)1176     AssertionResult MapOneUpdateSnapshot(const std::string& name) {
1177         if (snapuserd_required_) {
1178             std::unique_ptr<ICowWriter> writer;
1179             return MapUpdateSnapshot(name, &writer);
1180         } else {
1181             std::string path;
1182             return MapUpdateSnapshot(name, &path);
1183         }
1184     }
1185 
WriteSnapshots()1186     AssertionResult WriteSnapshots() {
1187         for (const auto& partition : {sys_, vnd_, prd_}) {
1188             auto res = WriteSnapshotAndHash(partition);
1189             if (!res) {
1190                 return res;
1191             }
1192         }
1193         return AssertionSuccess();
1194     }
1195 
WriteSnapshotAndHash(PartitionUpdate * partition)1196     AssertionResult WriteSnapshotAndHash(PartitionUpdate* partition) {
1197         std::string name = partition->partition_name() + "_b";
1198         if (snapuserd_required_) {
1199             std::unique_ptr<ICowWriter> writer;
1200             auto res = MapUpdateSnapshot(name, &writer);
1201             if (!res) {
1202                 return res;
1203             }
1204             if (!WriteRandomSnapshotData(writer.get(), &hashes_[name])) {
1205                 return AssertionFailure() << "Unable to write random data to snapshot " << name;
1206             }
1207             if (!writer->Finalize()) {
1208                 return AssertionFailure() << "Unable to finalize COW for " << name;
1209             }
1210         } else {
1211             std::string path;
1212             auto res = MapUpdateSnapshot(name, &path);
1213             if (!res) {
1214                 return res;
1215             }
1216             if (!WriteRandomData(path, std::nullopt, &hashes_[name])) {
1217                 return AssertionFailure() << "Unable to write random data to snapshot " << name;
1218             }
1219         }
1220 
1221         // Make sure updates to one device are seen by all devices.
1222         sync();
1223 
1224         return AssertionSuccess() << "Written random data to snapshot " << name
1225                                   << ", hash: " << hashes_[name];
1226     }
1227 
WriteRandomSnapshotData(ICowWriter * writer,std::string * hash)1228     bool WriteRandomSnapshotData(ICowWriter* writer, std::string* hash) {
1229         unique_fd rand(open("/dev/urandom", O_RDONLY));
1230         if (rand < 0) {
1231             PLOG(ERROR) << "open /dev/urandom";
1232             return false;
1233         }
1234 
1235         SHA256_CTX ctx;
1236         SHA256_Init(&ctx);
1237 
1238         if (!writer->GetMaxBlocks()) {
1239             LOG(ERROR) << "CowWriter must specify maximum number of blocks";
1240             return false;
1241         }
1242         const auto num_blocks = writer->GetMaxBlocks().value();
1243 
1244         const auto block_size = writer->GetBlockSize();
1245         std::string block(block_size, '\0');
1246         for (uint64_t i = 0; i < num_blocks; i++) {
1247             if (!ReadFully(rand, block.data(), block.size())) {
1248                 PLOG(ERROR) << "read /dev/urandom";
1249                 return false;
1250             }
1251             if (!writer->AddRawBlocks(i, block.data(), block.size())) {
1252                 LOG(ERROR) << "Failed to add raw block " << i;
1253                 return false;
1254             }
1255             SHA256_Update(&ctx, block.data(), block.size());
1256         }
1257 
1258         uint8_t out[32];
1259         SHA256_Final(out, &ctx);
1260         *hash = ToHexString(out, sizeof(out));
1261         return true;
1262     }
1263 
1264     // Generate a snapshot that moves all the upper blocks down to the start.
1265     // It doesn't really matter the order, we just want copies that reference
1266     // blocks that won't exist if the partition shrinks.
ShiftAllSnapshotBlocks(const std::string & name,uint64_t old_size)1267     AssertionResult ShiftAllSnapshotBlocks(const std::string& name, uint64_t old_size) {
1268         std::unique_ptr<ICowWriter> writer;
1269         if (auto res = MapUpdateSnapshot(name, &writer); !res) {
1270             return res;
1271         }
1272         if (!writer->GetMaxBlocks() || !*writer->GetMaxBlocks()) {
1273             return AssertionFailure() << "No max blocks set for " << name << " writer";
1274         }
1275 
1276         uint64_t src_block = (old_size / writer->GetBlockSize()) - 1;
1277         uint64_t dst_block = 0;
1278         uint64_t max_blocks = *writer->GetMaxBlocks();
1279         while (dst_block < max_blocks && dst_block < src_block) {
1280             if (!writer->AddCopy(dst_block, src_block)) {
1281                 return AssertionFailure() << "Unable to add copy for " << name << " for blocks "
1282                                           << src_block << ", " << dst_block;
1283             }
1284             dst_block++;
1285             src_block--;
1286         }
1287         if (!writer->Finalize()) {
1288             return AssertionFailure() << "Unable to finalize writer for " << name;
1289         }
1290 
1291         auto old_partition = "/dev/block/mapper/" + GetOtherPartitionName(name);
1292         auto reader = writer->OpenFileDescriptor(old_partition);
1293         if (!reader) {
1294             return AssertionFailure() << "Could not open file descriptor for " << name;
1295         }
1296 
1297         auto hash = HashSnapshot(reader.get());
1298         if (hash.empty()) {
1299             return AssertionFailure() << "Unable to hash snapshot writer for " << name;
1300         }
1301         hashes_[name] = hash;
1302 
1303         return AssertionSuccess();
1304     }
1305 
MapUpdateSnapshots(const std::vector<std::string> & names={"sys_b", "vnd_b", "prd_b"})1306     AssertionResult MapUpdateSnapshots(const std::vector<std::string>& names = {"sys_b", "vnd_b",
1307                                                                                 "prd_b"}) {
1308         for (const auto& name : names) {
1309             auto res = MapOneUpdateSnapshot(name);
1310             if (!res) {
1311                 return res;
1312             }
1313         }
1314         return AssertionSuccess();
1315     }
1316 
1317     // Create fake install operations to grow the COW device size.
AddOperation(PartitionUpdate * partition_update,uint64_t size_bytes=0)1318     void AddOperation(PartitionUpdate* partition_update, uint64_t size_bytes = 0) {
1319         auto e = partition_update->add_operations()->add_dst_extents();
1320         e->set_start_block(0);
1321         if (size_bytes == 0) {
1322             size_bytes = GetSize(partition_update);
1323         }
1324         e->set_num_blocks(size_bytes / manifest_.block_size());
1325     }
1326 
AddOperationForPartitions(std::vector<PartitionUpdate * > partitions={})1327     void AddOperationForPartitions(std::vector<PartitionUpdate*> partitions = {}) {
1328         if (partitions.empty()) {
1329             partitions = {sys_, vnd_, prd_};
1330         }
1331         for (auto* partition : partitions) {
1332             AddOperation(partition);
1333         }
1334     }
1335 
1336     std::unique_ptr<TestPartitionOpener> opener_;
1337     DeltaArchiveManifest manifest_;
1338     std::unique_ptr<MetadataBuilder> src_;
1339     std::map<std::string, std::string> hashes_;
1340 
1341     PartitionUpdate* sys_ = nullptr;
1342     PartitionUpdate* vnd_ = nullptr;
1343     PartitionUpdate* prd_ = nullptr;
1344     DynamicPartitionGroup* group_ = nullptr;
1345 };
1346 
TEST_F(SnapshotUpdateTest,SuperOtaMetadataTest)1347 TEST_F(SnapshotUpdateTest, SuperOtaMetadataTest) {
1348     auto info = new TestDeviceInfo(fake_super);
1349     ASSERT_TRUE(CleanupScratchOtaMetadataIfPresent(info));
1350     ASSERT_TRUE(CreateScratchOtaMetadataOnSuper(info));
1351     std::string scratch_device = GetScratchOtaMetadataPartition();
1352     ASSERT_NE(scratch_device, "");
1353     ASSERT_NE(MapScratchOtaMetadataPartition(scratch_device), "");
1354     ASSERT_TRUE(CleanupScratchOtaMetadataIfPresent(info));
1355 }
1356 
1357 // Test full update flow executed by update_engine. Some partitions uses super empty space,
1358 // some uses images, and some uses both.
1359 // Also test UnmapUpdateSnapshot unmaps everything.
1360 // Also test first stage mount and merge after this.
TEST_F(SnapshotUpdateTest,FullUpdateFlow)1361 TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
1362     // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
1363     // fit in super, but not |prd|.
1364     constexpr uint64_t partition_size = 3788_KiB;
1365     SetSize(sys_, partition_size);
1366     SetSize(vnd_, partition_size);
1367     SetSize(prd_, 18_MiB);
1368 
1369     // Make sure |prd| does not fit in super at all. On VABC, this means we
1370     // fake an extra large COW for |vnd| to fill up super.
1371     vnd_->set_estimate_cow_size(30_MiB);
1372     prd_->set_estimate_cow_size(30_MiB);
1373 
1374     AddOperationForPartitions();
1375 
1376     // Execute the update.
1377     ASSERT_TRUE(sm->BeginUpdate());
1378     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1379 
1380     // Test that partitions prioritize using space in super.
1381     auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1382     ASSERT_NE(tgt, nullptr);
1383     ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
1384     ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
1385     ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
1386 
1387     // Write some data to target partitions.
1388     ASSERT_TRUE(WriteSnapshots());
1389 
1390     // Assert that source partitions aren't affected.
1391     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1392         ASSERT_TRUE(IsPartitionUnchanged(name));
1393     }
1394 
1395     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1396 
1397     // Simulate shutting down the device.
1398     ASSERT_TRUE(UnmapAll());
1399 
1400     // After reboot, init does first stage mount.
1401     auto init = NewManagerForFirstStageMount("_b");
1402     ASSERT_NE(init, nullptr);
1403     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1404     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1405 
1406     auto indicator = sm->GetRollbackIndicatorPath();
1407     ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1408 
1409     // Check that the target partitions have the same content.
1410     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1411         ASSERT_TRUE(IsPartitionUnchanged(name));
1412     }
1413 
1414     // Initiate the merge and wait for it to be completed.
1415     if (ShouldSkipLegacyMerging()) {
1416         LOG(INFO) << "Skipping legacy merge in test";
1417         return;
1418     }
1419     ASSERT_TRUE(init->InitiateMerge());
1420     ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
1421     {
1422         // We should have started in SECOND_PHASE since nothing shrinks.
1423         ASSERT_TRUE(AcquireLock());
1424         auto local_lock = std::move(lock_);
1425         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1426         ASSERT_EQ(status.merge_phase(), MergePhase::SECOND_PHASE);
1427     }
1428     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1429 
1430     // Make sure the second phase ran and deleted snapshots.
1431     {
1432         ASSERT_TRUE(AcquireLock());
1433         auto local_lock = std::move(lock_);
1434         std::vector<std::string> snapshots;
1435         ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1436         ASSERT_TRUE(snapshots.empty());
1437     }
1438 
1439     // Check that the target partitions have the same content after the merge.
1440     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1441         ASSERT_TRUE(IsPartitionUnchanged(name))
1442                 << "Content of " << name << " changes after the merge";
1443     }
1444 }
1445 
TEST_F(SnapshotUpdateTest,DuplicateOps)1446 TEST_F(SnapshotUpdateTest, DuplicateOps) {
1447     if (!snapuserd_required_) {
1448         GTEST_SKIP() << "snapuserd-only test";
1449     }
1450 
1451     // Execute the update.
1452     ASSERT_TRUE(sm->BeginUpdate());
1453     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1454 
1455     // Write some data to target partitions.
1456     ASSERT_TRUE(WriteSnapshots());
1457 
1458     std::vector<PartitionUpdate*> partitions = {sys_, vnd_, prd_};
1459     for (auto* partition : partitions) {
1460         AddOperation(partition);
1461 
1462         std::unique_ptr<ICowWriter> writer;
1463         auto res = MapUpdateSnapshot(partition->partition_name() + "_b", &writer);
1464         ASSERT_TRUE(res);
1465         ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
1466         ASSERT_TRUE(writer->AddZeroBlocks(0, 1));
1467         ASSERT_TRUE(writer->Finalize());
1468     }
1469 
1470     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1471 
1472     // Simulate shutting down the device.
1473     ASSERT_TRUE(UnmapAll());
1474 
1475     // After reboot, init does first stage mount.
1476     auto init = NewManagerForFirstStageMount("_b");
1477     ASSERT_NE(init, nullptr);
1478     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1479     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1480 
1481     // Initiate the merge and wait for it to be completed.
1482     if (ShouldSkipLegacyMerging()) {
1483         LOG(INFO) << "Skipping legacy merge in test";
1484         return;
1485     }
1486     ASSERT_TRUE(init->InitiateMerge());
1487     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1488 }
1489 
1490 // Test that shrinking and growing partitions at the same time is handled
1491 // correctly in VABC.
TEST_F(SnapshotUpdateTest,SpaceSwapUpdate)1492 TEST_F(SnapshotUpdateTest, SpaceSwapUpdate) {
1493     if (!snapuserd_required_) {
1494         // b/179111359
1495         GTEST_SKIP() << "Skipping snapuserd test";
1496     }
1497 
1498     auto old_sys_size = GetSize(sys_);
1499     auto old_prd_size = GetSize(prd_);
1500 
1501     // Grow |sys| but shrink |prd|.
1502     SetSize(sys_, old_sys_size * 2);
1503     sys_->set_estimate_cow_size(8_MiB);
1504     SetSize(prd_, old_prd_size / 2);
1505     prd_->set_estimate_cow_size(1_MiB);
1506 
1507     AddOperationForPartitions();
1508 
1509     ASSERT_TRUE(sm->BeginUpdate());
1510     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1511 
1512     // Check that the old partition sizes were saved correctly.
1513     {
1514         ASSERT_TRUE(AcquireLock());
1515         auto local_lock = std::move(lock_);
1516 
1517         SnapshotStatus status;
1518         ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "prd_b", &status));
1519         ASSERT_EQ(status.old_partition_size(), 3145728);
1520         ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "sys_b", &status));
1521         ASSERT_EQ(status.old_partition_size(), 3145728);
1522     }
1523 
1524     ASSERT_TRUE(WriteSnapshotAndHash(sys_));
1525     ASSERT_TRUE(WriteSnapshotAndHash(vnd_));
1526     ASSERT_TRUE(ShiftAllSnapshotBlocks("prd_b", old_prd_size));
1527 
1528     sync();
1529 
1530     // Assert that source partitions aren't affected.
1531     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1532         ASSERT_TRUE(IsPartitionUnchanged(name));
1533     }
1534 
1535     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1536 
1537     // Simulate shutting down the device.
1538     ASSERT_TRUE(UnmapAll());
1539 
1540     // After reboot, init does first stage mount.
1541     auto init = NewManagerForFirstStageMount("_b");
1542     ASSERT_NE(init, nullptr);
1543     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1544     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1545 
1546     auto indicator = sm->GetRollbackIndicatorPath();
1547     ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1548 
1549     // Check that the target partitions have the same content.
1550     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1551         ASSERT_TRUE(IsPartitionUnchanged(name));
1552     }
1553 
1554     // Initiate the merge and wait for it to be completed.
1555     if (ShouldSkipLegacyMerging()) {
1556         LOG(INFO) << "Skipping legacy merge in test";
1557         return;
1558     }
1559     ASSERT_TRUE(init->InitiateMerge());
1560     ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
1561     {
1562         // Check that the merge phase is FIRST_PHASE until at least one call
1563         // to ProcessUpdateState() occurs.
1564         ASSERT_TRUE(AcquireLock());
1565         auto local_lock = std::move(lock_);
1566         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1567         ASSERT_EQ(status.merge_phase(), MergePhase::FIRST_PHASE);
1568     }
1569 
1570     // Simulate shutting down the device and creating partitions again.
1571     ASSERT_TRUE(UnmapAll());
1572     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1573 
1574     // Check that we used the correct types after rebooting mid-merge.
1575     DeviceMapper::TargetInfo target;
1576     ASSERT_TRUE(init->IsSnapshotDevice("prd_b", &target));
1577 
1578     bool userspace_snapshots = init->UpdateUsesUserSnapshots();
1579     if (userspace_snapshots) {
1580         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1581         ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1582         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1583         ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1584         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1585     } else {
1586         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
1587         ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1588         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
1589         ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1590         ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
1591     }
1592 
1593     // Complete the merge.
1594     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1595 
1596     // Make sure the second phase ran and deleted snapshots.
1597     {
1598         ASSERT_TRUE(AcquireLock());
1599         auto local_lock = std::move(lock_);
1600         std::vector<std::string> snapshots;
1601         ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1602         ASSERT_TRUE(snapshots.empty());
1603     }
1604 
1605     // Check that the target partitions have the same content after the merge.
1606     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1607         ASSERT_TRUE(IsPartitionUnchanged(name))
1608                 << "Content of " << name << " changes after the merge";
1609     }
1610 }
1611 
1612 // Test that shrinking and growing partitions at the same time is handled
1613 // correctly in VABC.
TEST_F(SnapshotUpdateTest,InterruptMergeDuringPhaseUpdate)1614 TEST_F(SnapshotUpdateTest, InterruptMergeDuringPhaseUpdate) {
1615     if (!snapuserd_required_) {
1616         // b/179111359
1617         GTEST_SKIP() << "Skipping snapuserd test";
1618     }
1619 
1620     auto old_sys_size = GetSize(sys_);
1621     auto old_prd_size = GetSize(prd_);
1622 
1623     // Grow |sys| but shrink |prd|.
1624     SetSize(sys_, old_sys_size * 2);
1625     sys_->set_estimate_cow_size(8_MiB);
1626     SetSize(prd_, old_prd_size / 2);
1627     prd_->set_estimate_cow_size(1_MiB);
1628 
1629     AddOperationForPartitions();
1630 
1631     ASSERT_TRUE(sm->BeginUpdate());
1632     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1633 
1634     // Check that the old partition sizes were saved correctly.
1635     {
1636         ASSERT_TRUE(AcquireLock());
1637         auto local_lock = std::move(lock_);
1638 
1639         SnapshotStatus status;
1640         ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "prd_b", &status));
1641         ASSERT_EQ(status.old_partition_size(), 3145728);
1642         ASSERT_TRUE(sm->ReadSnapshotStatus(local_lock.get(), "sys_b", &status));
1643         ASSERT_EQ(status.old_partition_size(), 3145728);
1644     }
1645 
1646     ASSERT_TRUE(WriteSnapshotAndHash(sys_));
1647     ASSERT_TRUE(WriteSnapshotAndHash(vnd_));
1648     ASSERT_TRUE(ShiftAllSnapshotBlocks("prd_b", old_prd_size));
1649 
1650     sync();
1651 
1652     // Assert that source partitions aren't affected.
1653     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1654         ASSERT_TRUE(IsPartitionUnchanged(name));
1655     }
1656 
1657     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1658 
1659     // Simulate shutting down the device.
1660     ASSERT_TRUE(UnmapAll());
1661 
1662     // After reboot, init does first stage mount.
1663     auto init = NewManagerForFirstStageMount("_b");
1664     ASSERT_NE(init, nullptr);
1665     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1666     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1667 
1668     // Check that the target partitions have the same content.
1669     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1670         ASSERT_TRUE(IsPartitionUnchanged(name));
1671     }
1672 
1673     // Initiate the merge and wait for it to be completed.
1674     if (ShouldSkipLegacyMerging()) {
1675         LOG(INFO) << "Skipping legacy merge in test";
1676         return;
1677     }
1678     ASSERT_TRUE(init->InitiateMerge());
1679     ASSERT_EQ(init->IsSnapuserdRequired(), snapuserd_required_);
1680     {
1681         // Check that the merge phase is FIRST_PHASE until at least one call
1682         // to ProcessUpdateState() occurs.
1683         ASSERT_TRUE(AcquireLock());
1684         auto local_lock = std::move(lock_);
1685         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1686         ASSERT_EQ(status.merge_phase(), MergePhase::FIRST_PHASE);
1687     }
1688 
1689     // Wait until prd_b merge is completed which is part of first phase
1690     std::chrono::milliseconds timeout(6000);
1691     auto start = std::chrono::steady_clock::now();
1692     // Keep polling until the merge is complete or timeout is reached
1693     while (true) {
1694         // Query the merge status
1695         const auto merge_status = init->snapuserd_client()->QuerySnapshotStatus("prd_b");
1696         if (merge_status == "snapshot-merge-complete") {
1697             break;
1698         }
1699 
1700         auto now = std::chrono::steady_clock::now();
1701         auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
1702 
1703         ASSERT_TRUE(elapsed < timeout);
1704         // sleep for a second and allow merge to complete
1705         std::this_thread::sleep_for(std::chrono::milliseconds(1000));
1706     }
1707 
1708     // Now, forcefully update the snapshot-update status to SECOND PHASE
1709     // This will not update the snapshot status of sys_b to MERGING
1710     if (init->UpdateUsesUserSnapshots()) {
1711         ASSERT_TRUE(AcquireLock());
1712         auto local_lock = std::move(lock_);
1713         auto status = init->ReadSnapshotUpdateStatus(local_lock.get());
1714         status.set_merge_phase(MergePhase::SECOND_PHASE);
1715         ASSERT_TRUE(init->WriteSnapshotUpdateStatus(local_lock.get(), status));
1716     }
1717 
1718     // Simulate shutting down the device and creating partitions again.
1719     ASSERT_TRUE(UnmapAll());
1720     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1721 
1722     DeviceMapper::TargetInfo target;
1723     ASSERT_TRUE(init->IsSnapshotDevice("prd_b", &target));
1724 
1725     ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1726     ASSERT_TRUE(init->IsSnapshotDevice("sys_b", &target));
1727     ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1728     ASSERT_TRUE(init->IsSnapshotDevice("vnd_b", &target));
1729     ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "user");
1730 
1731     // Complete the merge; "sys" and "vnd" should resume the merge
1732     // even though merge was interrupted after update_status was updated to
1733     // SECOND_PHASE
1734     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1735 
1736     // Make sure the second phase ran and deleted snapshots.
1737     {
1738         ASSERT_TRUE(AcquireLock());
1739         auto local_lock = std::move(lock_);
1740         std::vector<std::string> snapshots;
1741         ASSERT_TRUE(init->ListSnapshots(local_lock.get(), &snapshots));
1742         ASSERT_TRUE(snapshots.empty());
1743     }
1744 
1745     // Check that the target partitions have the same content after the merge.
1746     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1747         ASSERT_TRUE(IsPartitionUnchanged(name))
1748                 << "Content of " << name << " changes after the merge";
1749     }
1750 }
1751 
1752 // Test that if new system partitions uses empty space in super, that region is not snapshotted.
TEST_F(SnapshotUpdateTest,DirectWriteEmptySpace)1753 TEST_F(SnapshotUpdateTest, DirectWriteEmptySpace) {
1754     GTEST_SKIP() << "b/141889746";
1755     SetSize(sys_, 4_MiB);
1756     // vnd_b and prd_b are unchanged.
1757     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1758     ASSERT_EQ(3_MiB, GetSnapshotSize("sys_b").value_or(0));
1759 }
1760 
1761 // Test that if new system partitions uses space of old vendor partition, that region is
1762 // snapshotted.
TEST_F(SnapshotUpdateTest,SnapshotOldPartitions)1763 TEST_F(SnapshotUpdateTest, SnapshotOldPartitions) {
1764     SetSize(sys_, 4_MiB);  // grows
1765     SetSize(vnd_, 2_MiB);  // shrinks
1766     // prd_b is unchanged
1767     ASSERT_TRUE(sm->BeginUpdate());
1768     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1769     ASSERT_EQ(4_MiB, GetSnapshotSize("sys_b").value_or(0));
1770 }
1771 
1772 // Test that even if there seem to be empty space in target metadata, COW partition won't take
1773 // it because they are used by old partitions.
TEST_F(SnapshotUpdateTest,CowPartitionDoNotTakeOldPartitions)1774 TEST_F(SnapshotUpdateTest, CowPartitionDoNotTakeOldPartitions) {
1775     SetSize(sys_, 2_MiB);  // shrinks
1776     // vnd_b and prd_b are unchanged.
1777     ASSERT_TRUE(sm->BeginUpdate());
1778     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1779 
1780     auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1781     ASSERT_NE(nullptr, tgt);
1782     auto metadata = tgt->Export();
1783     ASSERT_NE(nullptr, metadata);
1784     std::vector<std::string> written;
1785     // Write random data to all COW partitions in super
1786     for (auto p : metadata->partitions) {
1787         if (GetPartitionGroupName(metadata->groups[p.group_index]) != kCowGroupName) {
1788             continue;
1789         }
1790         std::string path;
1791         ASSERT_TRUE(CreateLogicalPartition(
1792                 CreateLogicalPartitionParams{
1793                         .block_device = fake_super,
1794                         .metadata = metadata.get(),
1795                         .partition = &p,
1796                         .timeout_ms = 1s,
1797                         .partition_opener = opener_.get(),
1798                 },
1799                 &path));
1800         ASSERT_TRUE(WriteRandomData(path));
1801         written.push_back(GetPartitionName(p));
1802     }
1803     ASSERT_FALSE(written.empty())
1804             << "No COW partitions are created even if there are empty space in super partition";
1805 
1806     // Make sure source partitions aren't affected.
1807     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1808         ASSERT_TRUE(IsPartitionUnchanged(name));
1809     }
1810 }
1811 
1812 // Test that it crashes after creating snapshot status file but before creating COW image, then
1813 // calling CreateUpdateSnapshots again works.
TEST_F(SnapshotUpdateTest,SnapshotStatusFileWithoutCow)1814 TEST_F(SnapshotUpdateTest, SnapshotStatusFileWithoutCow) {
1815     // Write some trash snapshot files to simulate leftovers from previous runs.
1816     {
1817         ASSERT_TRUE(AcquireLock());
1818         auto local_lock = std::move(lock_);
1819         SnapshotStatus status;
1820         status.set_name("sys_b");
1821         ASSERT_TRUE(sm->WriteSnapshotStatus(local_lock.get(), status));
1822         ASSERT_TRUE(image_manager_->CreateBackingImage("sys_b-cow-img", 1_MiB,
1823                                                        IImageManager::CREATE_IMAGE_DEFAULT));
1824     }
1825 
1826     // Redo the update.
1827     ASSERT_TRUE(sm->BeginUpdate());
1828     ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1829 
1830     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1831 
1832     // Check that target partitions can be mapped.
1833     EXPECT_TRUE(MapUpdateSnapshots());
1834 }
1835 
1836 // Test that the old partitions are not modified.
TEST_F(SnapshotUpdateTest,TestRollback)1837 TEST_F(SnapshotUpdateTest, TestRollback) {
1838     // Execute the update.
1839     ASSERT_TRUE(sm->BeginUpdate());
1840     ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1841 
1842     AddOperationForPartitions();
1843 
1844     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1845 
1846     // Write some data to target partitions.
1847     ASSERT_TRUE(WriteSnapshots());
1848 
1849     // Assert that source partitions aren't affected.
1850     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1851         ASSERT_TRUE(IsPartitionUnchanged(name));
1852     }
1853 
1854     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1855 
1856     // Simulate shutting down the device.
1857     ASSERT_TRUE(UnmapAll());
1858 
1859     // After reboot, init does first stage mount.
1860     auto init = NewManagerForFirstStageMount("_b");
1861     ASSERT_NE(init, nullptr);
1862     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1863     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1864 
1865     // Check that the target partitions have the same content.
1866     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1867         ASSERT_TRUE(IsPartitionUnchanged(name));
1868     }
1869 
1870     // Simulate shutting down the device again.
1871     ASSERT_TRUE(UnmapAll());
1872     init = NewManagerForFirstStageMount("_a");
1873     ASSERT_NE(init, nullptr);
1874     ASSERT_FALSE(init->NeedSnapshotsInFirstStageMount());
1875     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1876 
1877     // Assert that the source partitions aren't affected.
1878     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1879         ASSERT_TRUE(IsPartitionUnchanged(name));
1880     }
1881 }
1882 
1883 // Test that if an update is applied but not booted into, it can be canceled.
TEST_F(SnapshotUpdateTest,CancelAfterApply)1884 TEST_F(SnapshotUpdateTest, CancelAfterApply) {
1885     ASSERT_TRUE(sm->BeginUpdate());
1886     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1887     ASSERT_TRUE(sm->CancelUpdate());
1888 }
1889 
ToIntervals(const std::vector<std::unique_ptr<Extent>> & extents)1890 static std::vector<Interval> ToIntervals(const std::vector<std::unique_ptr<Extent>>& extents) {
1891     std::vector<Interval> ret;
1892     std::transform(extents.begin(), extents.end(), std::back_inserter(ret),
1893                    [](const auto& extent) { return extent->AsLinearExtent()->AsInterval(); });
1894     return ret;
1895 }
1896 
1897 // Test that at the second update, old COW partition spaces are reclaimed.
TEST_F(SnapshotUpdateTest,ReclaimCow)1898 TEST_F(SnapshotUpdateTest, ReclaimCow) {
1899     // Make sure VABC cows are small enough that they fit in fake_super.
1900     sys_->set_estimate_cow_size(64_KiB);
1901     vnd_->set_estimate_cow_size(64_KiB);
1902     prd_->set_estimate_cow_size(64_KiB);
1903 
1904     // Execute the first update.
1905     ASSERT_TRUE(sm->BeginUpdate());
1906     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1907     ASSERT_TRUE(MapUpdateSnapshots());
1908     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1909 
1910     // Simulate shutting down the device.
1911     ASSERT_TRUE(UnmapAll());
1912 
1913     // After reboot, init does first stage mount.
1914     auto init = NewManagerForFirstStageMount("_b");
1915     ASSERT_NE(init, nullptr);
1916     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1917     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1918     init = nullptr;
1919 
1920     // Initiate the merge and wait for it to be completed.
1921     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1922     if (ShouldSkipLegacyMerging()) {
1923         LOG(INFO) << "Skipping legacy merge in test";
1924         return;
1925     }
1926     ASSERT_TRUE(new_sm->InitiateMerge());
1927     ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
1928 
1929     // Execute the second update.
1930     ASSERT_TRUE(new_sm->BeginUpdate());
1931     ASSERT_TRUE(new_sm->CreateUpdateSnapshots(manifest_));
1932 
1933     // Check that the old COW space is reclaimed and does not occupy space of mapped partitions.
1934     auto src = MetadataBuilder::New(*opener_, "super", 1);
1935     ASSERT_NE(src, nullptr);
1936     auto tgt = MetadataBuilder::New(*opener_, "super", 0);
1937     ASSERT_NE(tgt, nullptr);
1938     for (const auto& cow_part_name : {"sys_a-cow", "vnd_a-cow", "prd_a-cow"}) {
1939         auto* cow_part = tgt->FindPartition(cow_part_name);
1940         ASSERT_NE(nullptr, cow_part) << cow_part_name << " does not exist in target metadata";
1941         auto cow_intervals = ToIntervals(cow_part->extents());
1942         for (const auto& old_part_name : {"sys_b", "vnd_b", "prd_b"}) {
1943             auto* old_part = src->FindPartition(old_part_name);
1944             ASSERT_NE(nullptr, old_part) << old_part_name << " does not exist in source metadata";
1945             auto old_intervals = ToIntervals(old_part->extents());
1946 
1947             auto intersect = Interval::Intersect(cow_intervals, old_intervals);
1948             ASSERT_TRUE(intersect.empty()) << "COW uses space of source partitions";
1949         }
1950     }
1951 }
1952 
TEST_F(SnapshotUpdateTest,RetrofitAfterRegularAb)1953 TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) {
1954     constexpr auto kRetrofitGroupSize = kGroupSize / 2;
1955 
1956     // Initialize device-mapper / disk
1957     ASSERT_TRUE(UnmapAll());
1958     FormatFakeSuper();
1959 
1960     // Setup source partition metadata to have both _a and _b partitions.
1961     src_ = MetadataBuilder::New(*opener_, "super", 0);
1962     ASSERT_NE(nullptr, src_);
1963     for (const auto& suffix : {"_a"s, "_b"s}) {
1964         ASSERT_TRUE(src_->AddGroup(group_->name() + suffix, kRetrofitGroupSize));
1965         for (const auto& name : {"sys"s, "vnd"s, "prd"s}) {
1966             auto partition = src_->AddPartition(name + suffix, group_->name() + suffix, 0);
1967             ASSERT_NE(nullptr, partition);
1968             ASSERT_TRUE(src_->ResizePartition(partition, 2_MiB));
1969         }
1970     }
1971     auto metadata = src_->Export();
1972     ASSERT_NE(nullptr, metadata);
1973     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1974 
1975     // Flash source partitions
1976     std::string path;
1977     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1978         ASSERT_TRUE(CreateLogicalPartition(
1979                 CreateLogicalPartitionParams{
1980                         .block_device = fake_super,
1981                         .metadata_slot = 0,
1982                         .partition_name = name,
1983                         .timeout_ms = 1s,
1984                         .partition_opener = opener_.get(),
1985                 },
1986                 &path));
1987         ASSERT_TRUE(WriteRandomData(path));
1988         auto hash = GetHash(path);
1989         ASSERT_TRUE(hash.has_value());
1990         hashes_[name] = *hash;
1991     }
1992 
1993     // Setup manifest.
1994     group_->set_size(kRetrofitGroupSize);
1995     for (auto* partition : {sys_, vnd_, prd_}) {
1996         SetSize(partition, 2_MiB);
1997     }
1998     AddOperationForPartitions();
1999 
2000     ASSERT_TRUE(sm->BeginUpdate());
2001     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2002 
2003     // Test that COW image should not be created for retrofit devices; super
2004     // should be big enough.
2005     ASSERT_FALSE(image_manager_->BackingImageExists("sys_b-cow-img"));
2006     ASSERT_FALSE(image_manager_->BackingImageExists("vnd_b-cow-img"));
2007     ASSERT_FALSE(image_manager_->BackingImageExists("prd_b-cow-img"));
2008 
2009     // Write some data to target partitions.
2010     ASSERT_TRUE(WriteSnapshots());
2011 
2012     // Assert that source partitions aren't affected.
2013     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
2014         ASSERT_TRUE(IsPartitionUnchanged(name));
2015     }
2016 
2017     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2018 }
2019 
TEST_F(SnapshotUpdateTest,MergeCannotRemoveCow)2020 TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
2021     // Make source partitions as big as possible to force COW image to be created.
2022     SetSize(sys_, 10_MiB);
2023     SetSize(vnd_, 10_MiB);
2024     SetSize(prd_, 10_MiB);
2025     sys_->set_estimate_cow_size(12_MiB);
2026     vnd_->set_estimate_cow_size(12_MiB);
2027     prd_->set_estimate_cow_size(12_MiB);
2028 
2029     src_ = MetadataBuilder::New(*opener_, "super", 0);
2030     ASSERT_NE(src_, nullptr);
2031     src_->RemoveGroupAndPartitions(group_->name() + "_a");
2032     src_->RemoveGroupAndPartitions(group_->name() + "_b");
2033     ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
2034     auto metadata = src_->Export();
2035     ASSERT_NE(nullptr, metadata);
2036     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
2037 
2038     // Add operations for sys. The whole device is written.
2039     AddOperation(sys_);
2040 
2041     // Execute the update.
2042     ASSERT_TRUE(sm->BeginUpdate());
2043     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2044     ASSERT_TRUE(MapUpdateSnapshots());
2045     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2046 
2047     // Simulate shutting down the device.
2048     ASSERT_TRUE(UnmapAll());
2049 
2050     // After reboot, init does first stage mount.
2051     // Normally we should use NewManagerForFirstStageMount, but if so,
2052     // "gsid.mapped_image.sys_b-cow-img" won't be set.
2053     auto init = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
2054     ASSERT_NE(init, nullptr);
2055     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2056 
2057     // Keep an open handle to the cow device. This should cause the merge to
2058     // be incomplete.
2059     auto cow_path = android::base::GetProperty("gsid.mapped_image.sys_b-cow-img", "");
2060     unique_fd fd(open(cow_path.c_str(), O_RDONLY | O_CLOEXEC));
2061     ASSERT_GE(fd, 0);
2062 
2063     // COW cannot be removed due to open fd, so expect a soft failure.
2064     if (ShouldSkipLegacyMerging()) {
2065         LOG(INFO) << "Skipping legacy merge in test";
2066         return;
2067     }
2068     ASSERT_TRUE(init->InitiateMerge());
2069     ASSERT_EQ(UpdateState::MergeNeedsReboot, init->ProcessUpdateState());
2070 
2071     // Simulate shutting down the device.
2072     fd.reset();
2073     ASSERT_TRUE(UnmapAll());
2074 
2075     // init does first stage mount again.
2076     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2077 
2078     // sys_b should be mapped as a dm-linear device directly.
2079     ASSERT_FALSE(sm->IsSnapshotDevice("sys_b", nullptr));
2080 
2081     // Merge should be able to complete now.
2082     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2083 }
2084 
2085 class MetadataMountedTest : public ::testing::Test {
2086   public:
2087     // This is so main() can instantiate this to invoke Cleanup.
TestBody()2088     virtual void TestBody() override {}
SetUp()2089     void SetUp() override {
2090         SKIP_IF_NON_VIRTUAL_AB();
2091         metadata_dir_ = test_device->GetMetadataDir();
2092         ASSERT_TRUE(ReadDefaultFstab(&fstab_));
2093     }
TearDown()2094     void TearDown() override {
2095         RETURN_IF_NON_VIRTUAL_AB();
2096         SetUp();
2097         // Remount /metadata
2098         test_device->set_recovery(false);
2099         EXPECT_TRUE(android::fs_mgr::EnsurePathMounted(&fstab_, metadata_dir_));
2100     }
IsMetadataMounted()2101     AssertionResult IsMetadataMounted() {
2102         Fstab mounted_fstab;
2103         if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
2104             ADD_FAILURE() << "Failed to scan mounted volumes";
2105             return AssertionFailure() << "Failed to scan mounted volumes";
2106         }
2107 
2108         auto entry = GetEntryForPath(&fstab_, metadata_dir_);
2109         if (entry == nullptr) {
2110             return AssertionFailure() << "No mount point found in fstab for path " << metadata_dir_;
2111         }
2112 
2113         auto mv = GetEntryForMountPoint(&mounted_fstab, entry->mount_point);
2114         if (mv == nullptr) {
2115             return AssertionFailure() << metadata_dir_ << " is not mounted";
2116         }
2117         return AssertionSuccess() << metadata_dir_ << " is mounted";
2118     }
2119     std::string metadata_dir_;
2120     Fstab fstab_;
2121 };
2122 
MountMetadata()2123 void MountMetadata() {
2124     MetadataMountedTest().TearDown();
2125 }
2126 
TEST_F(MetadataMountedTest,Android)2127 TEST_F(MetadataMountedTest, Android) {
2128     auto device = sm->EnsureMetadataMounted();
2129     EXPECT_NE(nullptr, device);
2130     device.reset();
2131 
2132     EXPECT_TRUE(IsMetadataMounted());
2133     EXPECT_TRUE(sm->CancelUpdate()) << "Metadata dir should never be unmounted in Android mode";
2134 }
2135 
TEST_F(MetadataMountedTest,Recovery)2136 TEST_F(MetadataMountedTest, Recovery) {
2137     GTEST_SKIP() << "b/350715463";
2138 
2139     test_device->set_recovery(true);
2140     metadata_dir_ = test_device->GetMetadataDir();
2141 
2142     EXPECT_TRUE(android::fs_mgr::EnsurePathUnmounted(&fstab_, metadata_dir_));
2143     EXPECT_FALSE(IsMetadataMounted());
2144 
2145     auto device = sm->EnsureMetadataMounted();
2146     EXPECT_NE(nullptr, device);
2147     EXPECT_TRUE(IsMetadataMounted());
2148 
2149     device.reset();
2150     EXPECT_FALSE(IsMetadataMounted());
2151 }
2152 
2153 // Test that during a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,MergeInRecovery)2154 TEST_F(SnapshotUpdateTest, MergeInRecovery) {
2155     // Execute the first update.
2156     ASSERT_TRUE(sm->BeginUpdate());
2157     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2158     ASSERT_TRUE(MapUpdateSnapshots());
2159     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2160 
2161     // Simulate shutting down the device.
2162     ASSERT_TRUE(UnmapAll());
2163 
2164     // After reboot, init does first stage mount.
2165     auto init = NewManagerForFirstStageMount("_b");
2166     ASSERT_NE(init, nullptr);
2167     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2168     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2169     init = nullptr;
2170 
2171     // Initiate the merge and then immediately stop it to simulate a reboot.
2172     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
2173     if (ShouldSkipLegacyMerging()) {
2174         LOG(INFO) << "Skipping legacy merge in test";
2175         return;
2176     }
2177     ASSERT_TRUE(new_sm->InitiateMerge());
2178     ASSERT_TRUE(UnmapAll());
2179 
2180     // Simulate a reboot into recovery.
2181     auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
2182     test_device->set_recovery(true);
2183     new_sm = NewManagerForFirstStageMount(test_device.release());
2184 
2185     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2186     ASSERT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2187 }
2188 
2189 // Test that a merge does not clear the snapshot state in fastboot.
TEST_F(SnapshotUpdateTest,MergeInFastboot)2190 TEST_F(SnapshotUpdateTest, MergeInFastboot) {
2191     // Execute the first update.
2192     ASSERT_TRUE(sm->BeginUpdate());
2193     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2194     ASSERT_TRUE(MapUpdateSnapshots());
2195     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2196 
2197     // Simulate shutting down the device.
2198     ASSERT_TRUE(UnmapAll());
2199 
2200     // After reboot, init does first stage mount.
2201     auto init = NewManagerForFirstStageMount("_b");
2202     ASSERT_NE(init, nullptr);
2203     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2204     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2205     init = nullptr;
2206 
2207     // Initiate the merge and then immediately stop it to simulate a reboot.
2208     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
2209     if (ShouldSkipLegacyMerging()) {
2210         LOG(INFO) << "Skipping legacy merge in test";
2211         return;
2212     }
2213     ASSERT_TRUE(new_sm->InitiateMerge());
2214     ASSERT_TRUE(UnmapAll());
2215 
2216     // Simulate a reboot into recovery.
2217     auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
2218     test_device->set_recovery(true);
2219     new_sm = NewManagerForFirstStageMount(test_device.release());
2220 
2221     ASSERT_TRUE(new_sm->FinishMergeInRecovery());
2222 
2223     ASSERT_TRUE(UnmapAll());
2224 
2225     auto mount = new_sm->EnsureMetadataMounted();
2226     ASSERT_TRUE(mount && mount->HasDevice());
2227     ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
2228 
2229     // Finish the merge in a normal boot.
2230     test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
2231     init = NewManagerForFirstStageMount(test_device.release());
2232     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2233     init = nullptr;
2234 
2235     test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
2236     new_sm = NewManagerForFirstStageMount(test_device.release());
2237     ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
2238     ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::None);
2239 }
2240 
2241 // Test that after an OTA, before a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeRollbackInRecovery)2242 TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) {
2243     // Execute the first update.
2244     ASSERT_TRUE(sm->BeginUpdate());
2245     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2246     ASSERT_TRUE(MapUpdateSnapshots());
2247     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2248 
2249     // Simulate shutting down the device.
2250     ASSERT_TRUE(UnmapAll());
2251 
2252     // Simulate a reboot into recovery.
2253     auto test_device = new TestDeviceInfo(fake_super, "_b");
2254     test_device->set_recovery(true);
2255     auto new_sm = NewManagerForFirstStageMount(test_device);
2256 
2257     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
2258     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2259     // Manually mount metadata so that we can call GetUpdateState() below.
2260     MountMetadata();
2261     EXPECT_TRUE(test_device->IsSlotUnbootable(1));
2262     EXPECT_FALSE(test_device->IsSlotUnbootable(0));
2263 }
2264 
2265 // Test that after an OTA and a bootloader rollback with no merge, we can wipe
2266 // data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeAfterRollback)2267 TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) {
2268     // Execute the first update.
2269     ASSERT_TRUE(sm->BeginUpdate());
2270     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2271     ASSERT_TRUE(MapUpdateSnapshots());
2272     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2273 
2274     // Simulate shutting down the device.
2275     ASSERT_TRUE(UnmapAll());
2276 
2277     // Simulate a rollback, with reboot into recovery.
2278     auto test_device = new TestDeviceInfo(fake_super, "_a");
2279     test_device->set_recovery(true);
2280     auto new_sm = NewManagerForFirstStageMount(test_device);
2281 
2282     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
2283     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2284     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2285     EXPECT_FALSE(test_device->IsSlotUnbootable(0));
2286     EXPECT_FALSE(test_device->IsSlotUnbootable(1));
2287 }
2288 
2289 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeRequiredInPackage)2290 TEST_F(SnapshotUpdateTest, DataWipeRequiredInPackage) {
2291     AddOperationForPartitions();
2292     // Execute the update.
2293     ASSERT_TRUE(sm->BeginUpdate());
2294     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2295 
2296     // Write some data to target partitions.
2297     ASSERT_TRUE(WriteSnapshots());
2298 
2299     ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2300 
2301     // Simulate shutting down the device.
2302     ASSERT_TRUE(UnmapAll());
2303 
2304     // Simulate a reboot into recovery.
2305     auto test_device = new TestDeviceInfo(fake_super, "_b");
2306     test_device->set_recovery(true);
2307     auto new_sm = NewManagerForFirstStageMount(test_device);
2308 
2309     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
2310     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2311     // Manually mount metadata so that we can call GetUpdateState() below.
2312     MountMetadata();
2313     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2314     ASSERT_FALSE(test_device->IsSlotUnbootable(1));
2315     ASSERT_FALSE(test_device->IsSlotUnbootable(0));
2316 
2317     ASSERT_TRUE(UnmapAll());
2318 
2319     // Now reboot into new slot.
2320     test_device = new TestDeviceInfo(fake_super, "_b");
2321     auto init = NewManagerForFirstStageMount(test_device);
2322     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2323     // Verify that we are on the downgraded build.
2324     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2325         ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
2326     }
2327 }
2328 
2329 // Cancel an OTA in recovery.
TEST_F(SnapshotUpdateTest,CancelInRecovery)2330 TEST_F(SnapshotUpdateTest, CancelInRecovery) {
2331     AddOperationForPartitions();
2332     // Execute the update.
2333     ASSERT_TRUE(sm->BeginUpdate());
2334     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2335 
2336     // Write some data to target partitions.
2337     ASSERT_TRUE(WriteSnapshots());
2338 
2339     ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2340 
2341     // Simulate shutting down the device.
2342     ASSERT_TRUE(UnmapAll());
2343 
2344     // Simulate a reboot into recovery.
2345     auto test_device = new TestDeviceInfo(fake_super, "_b");
2346     test_device->set_recovery(true);
2347     auto new_sm = NewManagerForFirstStageMount(test_device);
2348 
2349     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
2350     ASSERT_FALSE(new_sm->IsCancelUpdateSafe());
2351     ASSERT_TRUE(new_sm->CancelUpdate());
2352 
2353     ASSERT_TRUE(new_sm->EnsureImageManager());
2354     auto im = new_sm->image_manager();
2355     ASSERT_NE(im, nullptr);
2356     ASSERT_TRUE(im->IsImageDisabled("sys_b"));
2357     ASSERT_TRUE(im->IsImageDisabled("vnd_b"));
2358     ASSERT_TRUE(im->IsImageDisabled("prd_b"));
2359 }
2360 
2361 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeWithStaleSnapshots)2362 TEST_F(SnapshotUpdateTest, DataWipeWithStaleSnapshots) {
2363     AddOperationForPartitions();
2364 
2365     // Execute the update.
2366     ASSERT_TRUE(sm->BeginUpdate());
2367     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2368 
2369     // Write some data to target partitions.
2370     ASSERT_TRUE(WriteSnapshots());
2371 
2372     // Create a stale snapshot that should not exist.
2373     {
2374         ASSERT_TRUE(AcquireLock());
2375 
2376         PartitionCowCreator cow_creator = {
2377                 .using_snapuserd = snapuserd_required_,
2378                 .compression_algorithm = snapuserd_required_ ? FLAGS_compression_method : "",
2379         };
2380         SnapshotStatus status;
2381         status.set_name("sys_a");
2382         status.set_device_size(1_MiB);
2383         status.set_snapshot_size(2_MiB);
2384         status.set_cow_partition_size(2_MiB);
2385 
2386         ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &cow_creator, &status));
2387         lock_ = nullptr;
2388 
2389         ASSERT_TRUE(sm->EnsureImageManager());
2390         ASSERT_TRUE(sm->image_manager()->CreateBackingImage("sys_a", 1_MiB, 0));
2391     }
2392 
2393     ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
2394 
2395     // Simulate shutting down the device.
2396     ASSERT_TRUE(UnmapAll());
2397 
2398     // Simulate a reboot into recovery.
2399     auto test_device = new TestDeviceInfo(fake_super, "_b");
2400     test_device->set_recovery(true);
2401     auto new_sm = NewManagerForFirstStageMount(test_device);
2402 
2403     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
2404     ASSERT_TRUE(new_sm->HandleImminentDataWipe());
2405     // Manually mount metadata so that we can call GetUpdateState() below.
2406     MountMetadata();
2407     EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
2408     ASSERT_FALSE(test_device->IsSlotUnbootable(1));
2409     ASSERT_FALSE(test_device->IsSlotUnbootable(0));
2410 
2411     ASSERT_TRUE(UnmapAll());
2412 
2413     // Now reboot into new slot.
2414     test_device = new TestDeviceInfo(fake_super, "_b");
2415     auto init = NewManagerForFirstStageMount(test_device);
2416     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2417     // Verify that we are on the downgraded build.
2418     for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
2419         ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
2420     }
2421 }
2422 
TEST_F(SnapshotUpdateTest,Hashtree)2423 TEST_F(SnapshotUpdateTest, Hashtree) {
2424     constexpr auto partition_size = 4_MiB;
2425     constexpr auto data_size = 3_MiB;
2426     constexpr auto hashtree_size = 512_KiB;
2427     constexpr auto fec_size = partition_size - data_size - hashtree_size;
2428 
2429     const auto block_size = manifest_.block_size();
2430     SetSize(sys_, partition_size);
2431     AddOperation(sys_, data_size);
2432 
2433     sys_->set_estimate_cow_size(partition_size + data_size);
2434 
2435     // Set hastree extents.
2436     sys_->mutable_hash_tree_data_extent()->set_start_block(0);
2437     sys_->mutable_hash_tree_data_extent()->set_num_blocks(data_size / block_size);
2438 
2439     sys_->mutable_hash_tree_extent()->set_start_block(data_size / block_size);
2440     sys_->mutable_hash_tree_extent()->set_num_blocks(hashtree_size / block_size);
2441 
2442     // Set FEC extents.
2443     sys_->mutable_fec_data_extent()->set_start_block(0);
2444     sys_->mutable_fec_data_extent()->set_num_blocks((data_size + hashtree_size) / block_size);
2445 
2446     sys_->mutable_fec_extent()->set_start_block((data_size + hashtree_size) / block_size);
2447     sys_->mutable_fec_extent()->set_num_blocks(fec_size / block_size);
2448 
2449     ASSERT_TRUE(sm->BeginUpdate());
2450     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2451 
2452     // Map and write some data to target partition.
2453     ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
2454     ASSERT_TRUE(WriteSnapshotAndHash(sys_));
2455 
2456     // Finish update.
2457     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2458 
2459     // Simulate shutting down the device.
2460     ASSERT_TRUE(UnmapAll());
2461 
2462     // After reboot, init does first stage mount.
2463     auto init = NewManagerForFirstStageMount("_b");
2464     ASSERT_NE(init, nullptr);
2465     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2466     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2467 
2468     // Check that the target partition have the same content. Hashtree and FEC extents
2469     // should be accounted for.
2470     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2471 }
2472 
2473 // Test for overflow bit after update
TEST_F(SnapshotUpdateTest,Overflow)2474 TEST_F(SnapshotUpdateTest, Overflow) {
2475     if (snapuserd_required_) {
2476         GTEST_SKIP() << "No overflow bit set for snapuserd COWs";
2477     }
2478 
2479     const auto actual_write_size = GetSize(sys_);
2480     const auto declared_write_size = actual_write_size - 1_MiB;
2481 
2482     AddOperation(sys_, declared_write_size);
2483 
2484     // Execute the update.
2485     ASSERT_TRUE(sm->BeginUpdate());
2486     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2487 
2488     // Map and write some data to target partitions.
2489     ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
2490     ASSERT_TRUE(WriteSnapshotAndHash(sys_));
2491 
2492     std::vector<android::dm::DeviceMapper::TargetInfo> table;
2493     ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table));
2494     ASSERT_EQ(1u, table.size());
2495     EXPECT_TRUE(table[0].IsOverflowSnapshot());
2496 
2497     ASSERT_FALSE(sm->FinishedSnapshotWrites(false))
2498             << "FinishedSnapshotWrites should detect overflow of CoW device.";
2499 }
2500 
TEST_F(SnapshotUpdateTest,AddPartition)2501 TEST_F(SnapshotUpdateTest, AddPartition) {
2502     group_->add_partition_names("dlkm");
2503 
2504     auto dlkm = manifest_.add_partitions();
2505     dlkm->set_partition_name("dlkm");
2506     dlkm->set_estimate_cow_size(2_MiB);
2507     SetSize(dlkm, 3_MiB);
2508 
2509     // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
2510     // fit in super, but not |prd|.
2511     constexpr uint64_t partition_size = 3788_KiB;
2512     SetSize(sys_, partition_size);
2513     SetSize(vnd_, partition_size);
2514     SetSize(prd_, partition_size);
2515     SetSize(dlkm, partition_size);
2516 
2517     AddOperationForPartitions({sys_, vnd_, prd_, dlkm});
2518 
2519     // Execute the update.
2520     ASSERT_TRUE(sm->BeginUpdate());
2521     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2522 
2523     // Write some data to target partitions.
2524     for (const auto& partition : {sys_, vnd_, prd_, dlkm}) {
2525         ASSERT_TRUE(WriteSnapshotAndHash(partition));
2526     }
2527 
2528     // Assert that source partitions aren't affected.
2529     for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
2530         ASSERT_TRUE(IsPartitionUnchanged(name));
2531     }
2532 
2533     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2534 
2535     // Simulate shutting down the device.
2536     ASSERT_TRUE(UnmapAll());
2537 
2538     // After reboot, init does first stage mount.
2539     auto init = NewManagerForFirstStageMount("_b");
2540     ASSERT_NE(init, nullptr);
2541 
2542     if (snapuserd_required_) {
2543         ASSERT_TRUE(init->EnsureSnapuserdConnected());
2544         init->set_use_first_stage_snapuserd(true);
2545     }
2546 
2547     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2548     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2549 
2550     // Check that the target partitions have the same content.
2551     std::vector<std::string> partitions = {"sys_b", "vnd_b", "prd_b", "dlkm_b"};
2552     for (const auto& name : partitions) {
2553         ASSERT_TRUE(IsPartitionUnchanged(name));
2554     }
2555 
2556     if (snapuserd_required_) {
2557         ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SECOND_STAGE));
2558         for (const auto& name : partitions) {
2559             ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete(name + "-user-cow-init"));
2560         }
2561     }
2562 
2563     // Initiate the merge and wait for it to be completed.
2564     if (ShouldSkipLegacyMerging()) {
2565         LOG(INFO) << "Skipping legacy merge in test";
2566         return;
2567     }
2568     ASSERT_TRUE(init->InitiateMerge());
2569     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2570 
2571     // Check that the target partitions have the same content after the merge.
2572     for (const auto& name : {"sys_b", "vnd_b", "prd_b", "dlkm_b"}) {
2573         ASSERT_TRUE(IsPartitionUnchanged(name))
2574                 << "Content of " << name << " changes after the merge";
2575     }
2576 }
2577 
2578 class AutoKill final {
2579   public:
AutoKill(pid_t pid)2580     explicit AutoKill(pid_t pid) : pid_(pid) {}
~AutoKill()2581     ~AutoKill() {
2582         if (pid_ > 0) kill(pid_, SIGKILL);
2583     }
2584 
valid() const2585     bool valid() const { return pid_ > 0; }
2586 
2587   private:
2588     pid_t pid_;
2589 };
2590 
TEST_F(SnapshotUpdateTest,DaemonTransition)2591 TEST_F(SnapshotUpdateTest, DaemonTransition) {
2592     if (!snapuserd_required_) {
2593         GTEST_SKIP() << "Skipping snapuserd test";
2594     }
2595 
2596     // Ensure a connection to the second-stage daemon, but use the first-stage
2597     // code paths thereafter.
2598     ASSERT_TRUE(sm->EnsureSnapuserdConnected());
2599     sm->set_use_first_stage_snapuserd(true);
2600 
2601     AddOperationForPartitions();
2602     // Execute the update.
2603     ASSERT_TRUE(sm->BeginUpdate());
2604     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2605     ASSERT_TRUE(MapUpdateSnapshots());
2606     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2607     ASSERT_TRUE(UnmapAll());
2608 
2609     auto init = NewManagerForFirstStageMount("_b");
2610     ASSERT_NE(init, nullptr);
2611 
2612     ASSERT_TRUE(init->EnsureSnapuserdConnected());
2613     init->set_use_first_stage_snapuserd(true);
2614 
2615     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2616     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2617 
2618     bool userspace_snapshots = init->UpdateUsesUserSnapshots();
2619 
2620     if (userspace_snapshots) {
2621         ASSERT_EQ(access("/dev/dm-user/sys_b-init", F_OK), 0);
2622         ASSERT_EQ(access("/dev/dm-user/sys_b", F_OK), -1);
2623     } else {
2624         ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow-init", F_OK), 0);
2625         ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow", F_OK), -1);
2626     }
2627 
2628     ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SECOND_STAGE));
2629 
2630     // :TODO: this is a workaround to ensure the handler list stays empty. We
2631     // should make this test more like actual init, and spawn two copies of
2632     // snapuserd, given how many other tests we now have for normal snapuserd.
2633     if (userspace_snapshots) {
2634         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("sys_b-init"));
2635         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("vnd_b-init"));
2636         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("prd_b-init"));
2637 
2638         // The control device should have been renamed.
2639         ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted("/dev/dm-user/sys_b-init", 10s));
2640         ASSERT_EQ(access("/dev/dm-user/sys_b", F_OK), 0);
2641     } else {
2642         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("sys_b-user-cow-init"));
2643         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("vnd_b-user-cow-init"));
2644         ASSERT_TRUE(init->snapuserd_client()->WaitForDeviceDelete("prd_b-user-cow-init"));
2645 
2646         // The control device should have been renamed.
2647         ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted("/dev/dm-user/sys_b-user-cow-init", 10s));
2648         ASSERT_EQ(access("/dev/dm-user/sys_b-user-cow", F_OK), 0);
2649     }
2650 }
2651 
TEST_F(SnapshotUpdateTest,MapAllSnapshotsWithoutSlotSwitch)2652 TEST_F(SnapshotUpdateTest, MapAllSnapshotsWithoutSlotSwitch) {
2653     MountMetadata();
2654     AddOperationForPartitions();
2655     // Execute the update.
2656     ASSERT_TRUE(sm->BeginUpdate());
2657     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2658 
2659     if (!sm->UpdateUsesUserSnapshots()) {
2660         GTEST_SKIP() << "Test does not apply as UserSnapshots aren't enabled.";
2661     }
2662 
2663     ASSERT_TRUE(WriteSnapshots());
2664     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2665 
2666     if (ShouldSkipLegacyMerging()) {
2667         GTEST_SKIP() << "Skipping legacy merge test";
2668     }
2669     // Mark the indicator
2670     ASSERT_TRUE(sm->BootFromSnapshotsWithoutSlotSwitch());
2671 
2672     ASSERT_TRUE(sm->EnsureSnapuserdConnected());
2673     sm->set_use_first_stage_snapuserd(true);
2674 
2675     ASSERT_TRUE(sm->NeedSnapshotsInFirstStageMount());
2676 
2677     // Map snapshots
2678     ASSERT_TRUE(sm->MapAllSnapshots(10s));
2679 
2680     // New updates should fail
2681     ASSERT_FALSE(sm->BeginUpdate());
2682 
2683     // Snapshots cannot be cancelled
2684     ASSERT_FALSE(sm->CancelUpdate());
2685 
2686     // Merge cannot start
2687     ASSERT_FALSE(sm->InitiateMerge());
2688 
2689     // Read bytes back and verify they match the cache.
2690     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2691 
2692     // Remove the indicators
2693     ASSERT_TRUE(sm->PrepareDeviceToBootWithoutSnapshot());
2694 
2695     // Cleanup snapshots
2696     ASSERT_TRUE(sm->UnmapAllSnapshots());
2697 }
2698 
TEST_F(SnapshotUpdateTest,MapAllSnapshots)2699 TEST_F(SnapshotUpdateTest, MapAllSnapshots) {
2700     AddOperationForPartitions();
2701     // Execute the update.
2702     ASSERT_TRUE(sm->BeginUpdate());
2703     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2704     ASSERT_TRUE(WriteSnapshots());
2705     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2706     ASSERT_TRUE(sm->MapAllSnapshots(10s));
2707 
2708     // Read bytes back and verify they match the cache.
2709     ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
2710 
2711     ASSERT_TRUE(sm->UnmapAllSnapshots());
2712 }
2713 
TEST_F(SnapshotUpdateTest,CancelOnTargetSlot)2714 TEST_F(SnapshotUpdateTest, CancelOnTargetSlot) {
2715     AddOperationForPartitions();
2716 
2717     ASSERT_TRUE(UnmapAll());
2718 
2719     // Execute the update from B->A.
2720     test_device->set_slot_suffix("_b");
2721     ASSERT_TRUE(sm->BeginUpdate());
2722     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2723 
2724     std::string path;
2725     ASSERT_TRUE(CreateLogicalPartition(
2726             CreateLogicalPartitionParams{
2727                     .block_device = fake_super,
2728                     .metadata_slot = 0,
2729                     .partition_name = "sys_a",
2730                     .timeout_ms = 1s,
2731                     .partition_opener = opener_.get(),
2732             },
2733             &path));
2734 
2735     bool userspace_snapshots = sm->UpdateUsesUserSnapshots();
2736 
2737     unique_fd fd;
2738     if (!userspace_snapshots) {
2739         // Hold sys_a open so it can't be unmapped.
2740         fd.reset(open(path.c_str(), O_RDONLY));
2741     }
2742 
2743     // Switch back to "A", make sure we can cancel. Instead of unmapping sys_a
2744     // we should simply delete the old snapshots.
2745     test_device->set_slot_suffix("_a");
2746     ASSERT_TRUE(sm->BeginUpdate());
2747 }
2748 
TEST_F(SnapshotUpdateTest,QueryStatusError)2749 TEST_F(SnapshotUpdateTest, QueryStatusError) {
2750     // Grow all partitions. Set |prd| large enough that |sys| and |vnd|'s COWs
2751     // fit in super, but not |prd|.
2752     constexpr uint64_t partition_size = 3788_KiB;
2753     SetSize(sys_, partition_size);
2754 
2755     AddOperationForPartitions();
2756 
2757     // Execute the update.
2758     ASSERT_TRUE(sm->BeginUpdate());
2759     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2760 
2761     if (sm->UpdateUsesUserSnapshots()) {
2762         GTEST_SKIP() << "Test does not apply to userspace snapshots";
2763     }
2764 
2765     ASSERT_TRUE(WriteSnapshots());
2766     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2767 
2768     ASSERT_TRUE(UnmapAll());
2769 
2770     class DmStatusFailure final : public DeviceMapperWrapper {
2771       public:
2772         bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) override {
2773             if (!DeviceMapperWrapper::GetTableStatus(name, table)) {
2774                 return false;
2775             }
2776             if (name == "sys_b" && !table->empty()) {
2777                 auto& info = table->at(0);
2778                 if (DeviceMapper::GetTargetType(info.spec) == "snapshot-merge") {
2779                     info.data = "Merge failed";
2780                 }
2781             }
2782             return true;
2783         }
2784     };
2785     DmStatusFailure wrapper;
2786 
2787     // After reboot, init does first stage mount.
2788     auto info = new TestDeviceInfo(fake_super, "_b");
2789     info->set_dm(&wrapper);
2790 
2791     auto init = NewManagerForFirstStageMount(info);
2792     ASSERT_NE(init, nullptr);
2793 
2794     ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2795     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2796 
2797     // Initiate the merge and wait for it to be completed.
2798     ASSERT_TRUE(init->InitiateMerge());
2799     ASSERT_EQ(UpdateState::MergeFailed, init->ProcessUpdateState());
2800 
2801     if (ShouldSkipLegacyMerging()) {
2802         LOG(INFO) << "Skipping legacy merge in test";
2803         return;
2804     }
2805 
2806     // Simulate a reboot that tries the merge again, with the non-failing dm.
2807     ASSERT_TRUE(UnmapAll());
2808     init = NewManagerForFirstStageMount("_b");
2809     ASSERT_NE(init, nullptr);
2810     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2811     ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
2812 }
2813 
TEST_F(SnapshotUpdateTest,BadCowVersion)2814 TEST_F(SnapshotUpdateTest, BadCowVersion) {
2815     if (!snapuserd_required_) {
2816         GTEST_SKIP() << "VABC only";
2817     }
2818 
2819     ASSERT_TRUE(sm->BeginUpdate());
2820 
2821     auto dynamic_partition_metadata = manifest_.mutable_dynamic_partition_metadata();
2822     dynamic_partition_metadata->set_cow_version(kMinCowVersion - 1);
2823     ASSERT_FALSE(sm->CreateUpdateSnapshots(manifest_));
2824 
2825     dynamic_partition_metadata->set_cow_version(kMaxCowVersion + 1);
2826     ASSERT_FALSE(sm->CreateUpdateSnapshots(manifest_));
2827 
2828     dynamic_partition_metadata->set_cow_version(kMaxCowVersion);
2829     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2830 }
2831 
TEST_F(SnapshotTest,FlagCheck)2832 TEST_F(SnapshotTest, FlagCheck) {
2833     if (!snapuserd_required_) {
2834         GTEST_SKIP() << "Skipping snapuserd test";
2835     }
2836     ASSERT_TRUE(AcquireLock());
2837 
2838     SnapshotUpdateStatus status = sm->ReadSnapshotUpdateStatus(lock_.get());
2839 
2840     // Set flags in proto
2841     status.set_o_direct(true);
2842     status.set_io_uring_enabled(true);
2843     status.set_userspace_snapshots(true);
2844     status.set_cow_op_merge_size(16);
2845 
2846     sm->WriteSnapshotUpdateStatus(lock_.get(), status);
2847     // Ensure a connection to the second-stage daemon, but use the first-stage
2848     // code paths thereafter.
2849     ASSERT_TRUE(sm->EnsureSnapuserdConnected());
2850     sm->set_use_first_stage_snapuserd(true);
2851 
2852     auto init = NewManagerForFirstStageMount("_b");
2853     ASSERT_NE(init, nullptr);
2854 
2855     lock_ = nullptr;
2856 
2857     std::vector<std::string> snapuserd_argv;
2858     ASSERT_TRUE(init->PerformInitTransition(SnapshotManager::InitTransition::SELINUX_DETACH,
2859                                             &snapuserd_argv));
2860     ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-o_direct") !=
2861                 snapuserd_argv.end());
2862     ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-io_uring") !=
2863                 snapuserd_argv.end());
2864     ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-user_snapshot") !=
2865                 snapuserd_argv.end());
2866     ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-cow_op_merge_size=16") !=
2867                 snapuserd_argv.end());
2868 }
2869 
2870 class FlashAfterUpdateTest : public SnapshotUpdateTest,
2871                              public WithParamInterface<std::tuple<uint32_t, bool>> {
2872   public:
InitiateMerge(const std::string & slot_suffix)2873     AssertionResult InitiateMerge(const std::string& slot_suffix) {
2874         auto sm = SnapshotManager::New(new TestDeviceInfo(fake_super, slot_suffix));
2875         if (!sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_)) {
2876             return AssertionFailure() << "Cannot CreateLogicalAndSnapshotPartitions";
2877         }
2878         if (!sm->InitiateMerge()) {
2879             return AssertionFailure() << "Cannot initiate merge";
2880         }
2881         return AssertionSuccess();
2882     }
2883 };
2884 
TEST_P(FlashAfterUpdateTest,FlashSlotAfterUpdate)2885 TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) {
2886     // Execute the update.
2887     ASSERT_TRUE(sm->BeginUpdate());
2888     ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
2889     ASSERT_TRUE(MapUpdateSnapshots());
2890     ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
2891 
2892     // Simulate shutting down the device.
2893     ASSERT_TRUE(UnmapAll());
2894 
2895     bool after_merge = std::get<1>(GetParam());
2896     if (after_merge) {
2897         ASSERT_TRUE(InitiateMerge("_b"));
2898         // Simulate shutting down the device after merge has initiated.
2899         ASSERT_TRUE(UnmapAll());
2900     }
2901 
2902     auto flashed_slot = std::get<0>(GetParam());
2903     auto flashed_slot_suffix = SlotSuffixForSlotNumber(flashed_slot);
2904 
2905     // Simulate flashing |flashed_slot|. This clears the UPDATED flag.
2906     auto flashed_builder = MetadataBuilder::New(*opener_, "super", flashed_slot);
2907     ASSERT_NE(flashed_builder, nullptr);
2908     flashed_builder->RemoveGroupAndPartitions(group_->name() + flashed_slot_suffix);
2909     flashed_builder->RemoveGroupAndPartitions(kCowGroupName);
2910     ASSERT_TRUE(FillFakeMetadata(flashed_builder.get(), manifest_, flashed_slot_suffix));
2911 
2912     // Deliberately remove a partition from this build so that
2913     // InitiateMerge do not switch state to "merging". This is possible in
2914     // practice because the list of dynamic partitions may change.
2915     ASSERT_NE(nullptr, flashed_builder->FindPartition("prd" + flashed_slot_suffix));
2916     flashed_builder->RemovePartition("prd" + flashed_slot_suffix);
2917 
2918     // Note that fastbootd always updates the partition table of both slots.
2919     auto flashed_metadata = flashed_builder->Export();
2920     ASSERT_NE(nullptr, flashed_metadata);
2921     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 0));
2922     ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 1));
2923 
2924     std::string path;
2925     for (const auto& name : {"sys", "vnd"}) {
2926         ASSERT_TRUE(CreateLogicalPartition(
2927                 CreateLogicalPartitionParams{
2928                         .block_device = fake_super,
2929                         .metadata_slot = flashed_slot,
2930                         .partition_name = name + flashed_slot_suffix,
2931                         .timeout_ms = 1s,
2932                         .partition_opener = opener_.get(),
2933                 },
2934                 &path));
2935         ASSERT_TRUE(WriteRandomData(path));
2936         auto hash = GetHash(path);
2937         ASSERT_TRUE(hash.has_value());
2938         hashes_[name + flashed_slot_suffix] = *hash;
2939     }
2940 
2941     // Simulate shutting down the device after flash.
2942     ASSERT_TRUE(UnmapAll());
2943 
2944     // Simulate reboot. After reboot, init does first stage mount.
2945     auto init = NewManagerForFirstStageMount(flashed_slot_suffix);
2946     ASSERT_NE(init, nullptr);
2947 
2948     if (flashed_slot && after_merge) {
2949         ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
2950     }
2951     ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
2952 
2953     // Check that the target partitions have the same content.
2954     for (const auto& name : {"sys", "vnd"}) {
2955         ASSERT_TRUE(IsPartitionUnchanged(name + flashed_slot_suffix));
2956     }
2957 
2958     // There should be no snapshot to merge.
2959     auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, flashed_slot_suffix));
2960     if (flashed_slot == 0 && after_merge) {
2961         ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
2962     } else {
2963         // update_engine calls ProcessUpdateState first -- should see Cancelled.
2964         ASSERT_EQ(UpdateState::Cancelled, new_sm->ProcessUpdateState());
2965     }
2966 
2967     // Next OTA calls CancelUpdate no matter what.
2968     ASSERT_TRUE(new_sm->CancelUpdate());
2969 }
2970 
2971 INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
__anon1b9e41e40602(const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) 2972                          [](const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) {
2973                              return "Flash"s + (std::get<0>(info.param) ? "New"s : "Old"s) +
2974                                     "Slot"s + (std::get<1>(info.param) ? "After"s : "Before"s) +
2975                                     "Merge"s;
2976                          });
2977 
Mkdir(const std::string & path)2978 bool Mkdir(const std::string& path) {
2979     if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
2980         std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
2981         return false;
2982     }
2983     return true;
2984 }
2985 
2986 class SnapshotTestEnvironment : public ::testing::Environment {
2987   public:
~SnapshotTestEnvironment()2988     ~SnapshotTestEnvironment() override {}
2989     void SetUp() override;
2990     void TearDown() override;
2991 
2992   private:
2993     bool CreateFakeSuper();
2994 
2995     std::unique_ptr<IImageManager> super_images_;
2996 };
2997 
CreateFakeSuper()2998 bool SnapshotTestEnvironment::CreateFakeSuper() {
2999     // Create and map the fake super partition.
3000     static constexpr int kImageFlags =
3001             IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
3002     if (!super_images_->CreateBackingImage("fake-super", kSuperSize, kImageFlags)) {
3003         LOG(ERROR) << "Could not create fake super partition";
3004         return false;
3005     }
3006     if (!super_images_->MapImageDevice("fake-super", 10s, &fake_super)) {
3007         LOG(ERROR) << "Could not map fake super partition";
3008         return false;
3009     }
3010     test_device->set_fake_super(fake_super);
3011     return true;
3012 }
3013 
SetUp()3014 void SnapshotTestEnvironment::SetUp() {
3015     // b/163082876: GTEST_SKIP in Environment will make atest report incorrect results. Until
3016     // that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
3017     // suites.
3018     RETURN_IF_NON_VIRTUAL_AB_MSG("Virtual A/B is not enabled, skipping global setup.\n");
3019 
3020     std::vector<std::string> paths = {
3021             // clang-format off
3022             "/data/gsi/ota/test",
3023             "/data/gsi/ota/test/super",
3024             "/metadata/gsi/ota/test",
3025             "/metadata/gsi/ota/test/super",
3026             "/metadata/ota/test",
3027             "/metadata/ota/test/snapshots",
3028             // clang-format on
3029     };
3030     for (const auto& path : paths) {
3031         ASSERT_TRUE(Mkdir(path));
3032     }
3033 
3034     // Create this once, otherwise, gsid will start/stop between each test.
3035     test_device = new TestDeviceInfo();
3036     sm = SnapshotManager::New(test_device);
3037     ASSERT_NE(nullptr, sm) << "Could not create snapshot manager";
3038 
3039     // Use a separate image manager for our fake super partition.
3040     super_images_ = IImageManager::Open("ota/test/super", 10s);
3041     ASSERT_NE(nullptr, super_images_) << "Could not create image manager";
3042 
3043     // Map the old image if one exists so we can safely unmap everything that
3044     // depends on it.
3045     bool recreate_fake_super;
3046     if (super_images_->BackingImageExists("fake-super")) {
3047         if (super_images_->IsImageMapped("fake-super")) {
3048             ASSERT_TRUE(super_images_->GetMappedImageDevice("fake-super", &fake_super));
3049         } else {
3050             ASSERT_TRUE(super_images_->MapImageDevice("fake-super", 10s, &fake_super));
3051         }
3052         test_device->set_fake_super(fake_super);
3053         recreate_fake_super = true;
3054     } else {
3055         ASSERT_TRUE(CreateFakeSuper());
3056         recreate_fake_super = false;
3057     }
3058 
3059     // Clean up previous run.
3060     MetadataMountedTest().TearDown();
3061     SnapshotUpdateTest().Cleanup();
3062     SnapshotTest().Cleanup();
3063 
3064     if (recreate_fake_super) {
3065         // Clean up any old copy.
3066         DeleteBackingImage(super_images_.get(), "fake-super");
3067         ASSERT_TRUE(CreateFakeSuper());
3068     }
3069 }
3070 
TearDown()3071 void SnapshotTestEnvironment::TearDown() {
3072     RETURN_IF_NON_VIRTUAL_AB();
3073     RETURN_IF_VENDOR_ON_ANDROID_S();
3074 
3075     if (super_images_ != nullptr) {
3076         DeleteBackingImage(super_images_.get(), "fake-super");
3077     }
3078 }
3079 
KillSnapuserd()3080 void KillSnapuserd() {
3081     // Detach the daemon if it's alive
3082     auto snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
3083     if (snapuserd_client) {
3084         snapuserd_client->DetachSnapuserd();
3085     }
3086 
3087     // Now stop the service - Init will send a SIGKILL to the daemon. However,
3088     // process state will move from "running" to "stopping". Only after the
3089     // process is reaped by init, the service state is moved to "stopped".
3090     //
3091     // Since the tests involve starting the daemon immediately, wait for the
3092     // process to completely stop (aka. wait until init reaps the terminated
3093     // process).
3094     android::base::SetProperty("ctl.stop", "snapuserd");
3095     if (!android::base::WaitForProperty("init.svc.snapuserd", "stopped", 10s)) {
3096         LOG(ERROR) << "Timed out waiting for snapuserd to stop.";
3097     }
3098 }
3099 
3100 }  // namespace snapshot
3101 }  // namespace android
3102 
main(int argc,char ** argv)3103 int main(int argc, char** argv) {
3104     ::testing::InitGoogleTest(&argc, argv);
3105     ::testing::AddGlobalTestEnvironment(new ::android::snapshot::SnapshotTestEnvironment());
3106     gflags::ParseCommandLineFlags(&argc, &argv, false);
3107 
3108     // During incremental flashing, snapshot updates are in progress.
3109     //
3110     // When snapshot update is in-progress, snapuserd daemon
3111     // will be up and running. These tests will start and stop the daemon
3112     // thereby interfering with the update and snapshot-merge progress.
3113     // Hence, wait until the update is complete.
3114     auto sm = android::snapshot::SnapshotManager::New();
3115     std::vector<std::string> snapshot_partitions;
3116     while (sm->IsUserspaceSnapshotUpdateInProgress(snapshot_partitions)) {
3117         LOG(INFO) << "Waiting for: " << snapshot_partitions.size()
3118                   << " partitions to finish snapshot-merge";
3119         std::this_thread::sleep_for(std::chrono::milliseconds(1000));
3120     }
3121 
3122     bool vab_legacy = false;
3123     if (FLAGS_force_mode == "vab-legacy") {
3124         vab_legacy = true;
3125     }
3126 
3127     if (!vab_legacy) {
3128         // This is necessary if the configuration we're testing doesn't match the device.
3129         android::base::SetProperty("ctl.stop", "snapuserd");
3130         android::snapshot::KillSnapuserd();
3131     }
3132 
3133     std::unordered_set<std::string> modes = {"", "vab-legacy"};
3134     if (modes.count(FLAGS_force_mode) == 0) {
3135         std::cerr << "Unexpected force_config argument\n";
3136         return 1;
3137     }
3138 
3139     int ret = RUN_ALL_TESTS();
3140 
3141     android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
3142 
3143     if (!vab_legacy) {
3144         android::snapshot::KillSnapuserd();
3145     }
3146     return ret;
3147 }
3148