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