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