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