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