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/snapshot.h>
16
17 #include <fcntl.h>
18 #include <sys/file.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21
22 #include <chrono>
23 #include <deque>
24 #include <future>
25 #include <iostream>
26
27 #include <android-base/file.h>
28 #include <android-base/logging.h>
29 #include <android-base/properties.h>
30 #include <android-base/strings.h>
31 #include <android-base/unique_fd.h>
32 #include <fs_mgr/roots.h>
33 #include <fs_mgr_dm_linear.h>
34 #include <gtest/gtest.h>
35 #include <libdm/dm.h>
36 #include <libfiemap/image_manager.h>
37 #include <liblp/builder.h>
38 #include <storage_literals/storage_literals.h>
39
40 #include <android/snapshot/snapshot.pb.h>
41 #include <libsnapshot/test_helpers.h>
42 #include "utility.h"
43
44 // Mock classes are not used. Header included to ensure mocked class definition aligns with the
45 // class itself.
46 #include <libsnapshot/mock_device_info.h>
47 #include <libsnapshot/mock_snapshot.h>
48
49 namespace android {
50 namespace snapshot {
51
52 using android::base::unique_fd;
53 using android::dm::DeviceMapper;
54 using android::dm::DmDeviceState;
55 using android::fiemap::FiemapStatus;
56 using android::fiemap::IImageManager;
57 using android::fs_mgr::BlockDeviceInfo;
58 using android::fs_mgr::CreateLogicalPartitionParams;
59 using android::fs_mgr::DestroyLogicalPartition;
60 using android::fs_mgr::EnsurePathMounted;
61 using android::fs_mgr::EnsurePathUnmounted;
62 using android::fs_mgr::Extent;
63 using android::fs_mgr::Fstab;
64 using android::fs_mgr::GetPartitionGroupName;
65 using android::fs_mgr::GetPartitionName;
66 using android::fs_mgr::Interval;
67 using android::fs_mgr::MetadataBuilder;
68 using android::fs_mgr::SlotSuffixForSlotNumber;
69 using chromeos_update_engine::DeltaArchiveManifest;
70 using chromeos_update_engine::DynamicPartitionGroup;
71 using chromeos_update_engine::PartitionUpdate;
72 using namespace ::testing;
73 using namespace android::storage_literals;
74 using namespace std::chrono_literals;
75 using namespace std::string_literals;
76
77 // Global states. See test_helpers.h.
78 std::unique_ptr<SnapshotManager> sm;
79 TestDeviceInfo* test_device = nullptr;
80 std::string fake_super;
81
82 void MountMetadata();
83
84 class SnapshotTest : public ::testing::Test {
85 public:
SnapshotTest()86 SnapshotTest() : dm_(DeviceMapper::Instance()) {
87 is_virtual_ab_ = android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
88 }
89
90 // This is exposed for main.
Cleanup()91 void Cleanup() {
92 InitializeState();
93 CleanupTestArtifacts();
94 }
95
96 protected:
SetUp()97 void SetUp() override {
98 if (!is_virtual_ab_) GTEST_SKIP() << "Test for Virtual A/B devices only";
99
100 SnapshotTestPropertyFetcher::SetUp();
101 InitializeState();
102 CleanupTestArtifacts();
103 FormatFakeSuper();
104 MountMetadata();
105 ASSERT_TRUE(sm->BeginUpdate());
106 }
107
TearDown()108 void TearDown() override {
109 if (!is_virtual_ab_) return;
110
111 lock_ = nullptr;
112
113 CleanupTestArtifacts();
114 SnapshotTestPropertyFetcher::TearDown();
115 }
116
InitializeState()117 void InitializeState() {
118 ASSERT_TRUE(sm->EnsureImageManager());
119 image_manager_ = sm->image_manager();
120
121 test_device->set_slot_suffix("_a");
122 }
123
CleanupTestArtifacts()124 void CleanupTestArtifacts() {
125 // Normally cancelling inside a merge is not allowed. Since these
126 // are tests, we don't care, destroy everything that might exist.
127 // Note we hardcode this list because of an annoying quirk: when
128 // completing a merge, the snapshot stops existing, so we can't
129 // get an accurate list to remove.
130 lock_ = nullptr;
131
132 std::vector<std::string> snapshots = {"test-snapshot", "test_partition_a",
133 "test_partition_b"};
134 for (const auto& snapshot : snapshots) {
135 ASSERT_TRUE(DeleteSnapshotDevice(snapshot));
136 DeleteBackingImage(image_manager_, snapshot + "-cow-img");
137
138 auto status_file = sm->GetSnapshotStatusFilePath(snapshot);
139 android::base::RemoveFileIfExists(status_file);
140 }
141
142 // Remove stale partitions in fake super.
143 std::vector<std::string> partitions = {
144 "base-device",
145 "test_partition_b",
146 "test_partition_b-base",
147 };
148 for (const auto& partition : partitions) {
149 DeleteDevice(partition);
150 }
151
152 if (sm->GetUpdateState() != UpdateState::None) {
153 auto state_file = sm->GetStateFilePath();
154 unlink(state_file.c_str());
155 }
156 }
157
AcquireLock()158 bool AcquireLock() {
159 lock_ = sm->LockExclusive();
160 return !!lock_;
161 }
162
163 // This is so main() can instantiate this to invoke Cleanup.
TestBody()164 virtual void TestBody() override {}
165
FormatFakeSuper()166 void FormatFakeSuper() {
167 BlockDeviceInfo super_device("super", kSuperSize, 0, 0, 4096);
168 std::vector<BlockDeviceInfo> devices = {super_device};
169
170 auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
171 ASSERT_NE(builder, nullptr);
172
173 auto metadata = builder->Export();
174 ASSERT_NE(metadata, nullptr);
175
176 TestPartitionOpener opener(fake_super);
177 ASSERT_TRUE(FlashPartitionTable(opener, fake_super, *metadata.get()));
178 }
179
180 // If |path| is non-null, the partition will be mapped after creation.
CreatePartition(const std::string & name,uint64_t size,std::string * path=nullptr)181 bool CreatePartition(const std::string& name, uint64_t size, std::string* path = nullptr) {
182 TestPartitionOpener opener(fake_super);
183 auto builder = MetadataBuilder::New(opener, "super", 0);
184 if (!builder) return false;
185
186 auto partition = builder->AddPartition(name, 0);
187 if (!partition) return false;
188 if (!builder->ResizePartition(partition, size)) {
189 return false;
190 }
191
192 // Update the source slot.
193 auto metadata = builder->Export();
194 if (!metadata) return false;
195 if (!UpdatePartitionTable(opener, "super", *metadata.get(), 0)) {
196 return false;
197 }
198
199 if (!path) return true;
200
201 CreateLogicalPartitionParams params = {
202 .block_device = fake_super,
203 .metadata = metadata.get(),
204 .partition_name = name,
205 .force_writable = true,
206 .timeout_ms = 10s,
207 };
208 return CreateLogicalPartition(params, path);
209 }
210
MapUpdatePartitions()211 bool MapUpdatePartitions() {
212 TestPartitionOpener opener(fake_super);
213 auto builder = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
214 if (!builder) return false;
215
216 auto metadata = builder->Export();
217 if (!metadata) return false;
218
219 // Update the destination slot, mark it as updated.
220 if (!UpdatePartitionTable(opener, "super", *metadata.get(), 1)) {
221 return false;
222 }
223
224 for (const auto& partition : metadata->partitions) {
225 CreateLogicalPartitionParams params = {
226 .block_device = fake_super,
227 .metadata = metadata.get(),
228 .partition = &partition,
229 .force_writable = true,
230 .timeout_ms = 10s,
231 .device_name = GetPartitionName(partition) + "-base",
232 };
233 std::string ignore_path;
234 if (!CreateLogicalPartition(params, &ignore_path)) {
235 return false;
236 }
237 }
238 return true;
239 }
240
DeleteSnapshotDevice(const std::string & snapshot)241 AssertionResult DeleteSnapshotDevice(const std::string& snapshot) {
242 AssertionResult res = AssertionSuccess();
243 if (!(res = DeleteDevice(snapshot))) return res;
244 if (!(res = DeleteDevice(snapshot + "-inner"))) return res;
245 if (!(res = DeleteDevice(snapshot + "-cow"))) return res;
246 if (!image_manager_->UnmapImageIfExists(snapshot + "-cow-img")) {
247 return AssertionFailure() << "Cannot unmap image " << snapshot << "-cow-img";
248 }
249 if (!(res = DeleteDevice(snapshot + "-base"))) return res;
250 return AssertionSuccess();
251 }
252
DeleteDevice(const std::string & device)253 AssertionResult DeleteDevice(const std::string& device) {
254 if (!dm_.DeleteDeviceIfExists(device)) {
255 return AssertionFailure() << "Can't delete " << device;
256 }
257 return AssertionSuccess();
258 }
259
CreateCowImage(const std::string & name)260 AssertionResult CreateCowImage(const std::string& name) {
261 if (!sm->CreateCowImage(lock_.get(), name)) {
262 return AssertionFailure() << "Cannot create COW image " << name;
263 }
264 std::string cow_device;
265 auto map_res = MapCowImage(name, 10s, &cow_device);
266 if (!map_res) {
267 return map_res;
268 }
269 if (!InitializeCow(cow_device)) {
270 return AssertionFailure() << "Cannot zero fill " << cow_device;
271 }
272 if (!sm->UnmapCowImage(name)) {
273 return AssertionFailure() << "Cannot unmap " << name << " after zero filling it";
274 }
275 return AssertionSuccess();
276 }
277
MapCowImage(const std::string & name,const std::chrono::milliseconds & timeout_ms,std::string * path)278 AssertionResult MapCowImage(const std::string& name,
279 const std::chrono::milliseconds& timeout_ms, std::string* path) {
280 auto cow_image_path = sm->MapCowImage(name, timeout_ms);
281 if (!cow_image_path.has_value()) {
282 return AssertionFailure() << "Cannot map cow image " << name;
283 }
284 *path = *cow_image_path;
285 return AssertionSuccess();
286 }
287
288 // Prepare A/B slot for a partition named "test_partition".
PrepareOneSnapshot(uint64_t device_size,std::string * out_snap_device=nullptr)289 AssertionResult PrepareOneSnapshot(uint64_t device_size,
290 std::string* out_snap_device = nullptr) {
291 std::string base_device, cow_device, snap_device;
292 if (!CreatePartition("test_partition_a", device_size)) {
293 return AssertionFailure();
294 }
295 if (!MapUpdatePartitions()) {
296 return AssertionFailure();
297 }
298 if (!dm_.GetDmDevicePathByName("test_partition_b-base", &base_device)) {
299 return AssertionFailure();
300 }
301 SnapshotStatus status;
302 status.set_name("test_partition_b");
303 status.set_device_size(device_size);
304 status.set_snapshot_size(device_size);
305 status.set_cow_file_size(device_size);
306 if (!sm->CreateSnapshot(lock_.get(), &status)) {
307 return AssertionFailure();
308 }
309 if (!CreateCowImage("test_partition_b")) {
310 return AssertionFailure();
311 }
312 if (!MapCowImage("test_partition_b", 10s, &cow_device)) {
313 return AssertionFailure();
314 }
315 if (!sm->MapSnapshot(lock_.get(), "test_partition_b", base_device, cow_device, 10s,
316 &snap_device)) {
317 return AssertionFailure();
318 }
319 if (out_snap_device) {
320 *out_snap_device = std::move(snap_device);
321 }
322 return AssertionSuccess();
323 }
324
325 // Simulate a reboot into the new slot.
SimulateReboot()326 AssertionResult SimulateReboot() {
327 lock_ = nullptr;
328 if (!sm->FinishedSnapshotWrites(false)) {
329 return AssertionFailure();
330 }
331 if (!dm_.DeleteDevice("test_partition_b")) {
332 return AssertionFailure();
333 }
334 if (!DestroyLogicalPartition("test_partition_b-base")) {
335 return AssertionFailure();
336 }
337 if (!sm->UnmapCowImage("test_partition_b")) {
338 return AssertionFailure();
339 }
340 return AssertionSuccess();
341 }
342
343 static constexpr std::chrono::milliseconds snapshot_timeout_ = 5s;
344 bool is_virtual_ab_;
345 DeviceMapper& dm_;
346 std::unique_ptr<SnapshotManager::LockedFile> lock_;
347 android::fiemap::IImageManager* image_manager_ = nullptr;
348 std::string fake_super_;
349 };
350
TEST_F(SnapshotTest,CreateSnapshot)351 TEST_F(SnapshotTest, CreateSnapshot) {
352 ASSERT_TRUE(AcquireLock());
353
354 static const uint64_t kDeviceSize = 1024 * 1024;
355 SnapshotStatus status;
356 status.set_name("test-snapshot");
357 status.set_device_size(kDeviceSize);
358 status.set_snapshot_size(kDeviceSize);
359 status.set_cow_file_size(kDeviceSize);
360 ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &status));
361 ASSERT_TRUE(CreateCowImage("test-snapshot"));
362
363 std::vector<std::string> snapshots;
364 ASSERT_TRUE(sm->ListSnapshots(lock_.get(), &snapshots));
365 ASSERT_EQ(snapshots.size(), 1);
366 ASSERT_EQ(snapshots[0], "test-snapshot");
367
368 // Scope so delete can re-acquire the snapshot file lock.
369 {
370 SnapshotStatus status;
371 ASSERT_TRUE(sm->ReadSnapshotStatus(lock_.get(), "test-snapshot", &status));
372 ASSERT_EQ(status.state(), SnapshotState::CREATED);
373 ASSERT_EQ(status.device_size(), kDeviceSize);
374 ASSERT_EQ(status.snapshot_size(), kDeviceSize);
375 }
376
377 ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
378 ASSERT_TRUE(sm->UnmapCowImage("test-snapshot"));
379 ASSERT_TRUE(sm->DeleteSnapshot(lock_.get(), "test-snapshot"));
380 }
381
TEST_F(SnapshotTest,MapSnapshot)382 TEST_F(SnapshotTest, MapSnapshot) {
383 ASSERT_TRUE(AcquireLock());
384
385 static const uint64_t kDeviceSize = 1024 * 1024;
386 SnapshotStatus status;
387 status.set_name("test-snapshot");
388 status.set_device_size(kDeviceSize);
389 status.set_snapshot_size(kDeviceSize);
390 status.set_cow_file_size(kDeviceSize);
391 ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &status));
392 ASSERT_TRUE(CreateCowImage("test-snapshot"));
393
394 std::string base_device;
395 ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
396
397 std::string cow_device;
398 ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
399
400 std::string snap_device;
401 ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
402 &snap_device));
403 ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
404 }
405
TEST_F(SnapshotTest,MapPartialSnapshot)406 TEST_F(SnapshotTest, MapPartialSnapshot) {
407 ASSERT_TRUE(AcquireLock());
408
409 static const uint64_t kSnapshotSize = 1024 * 1024;
410 static const uint64_t kDeviceSize = 1024 * 1024 * 2;
411 SnapshotStatus status;
412 status.set_name("test-snapshot");
413 status.set_device_size(kDeviceSize);
414 status.set_snapshot_size(kSnapshotSize);
415 status.set_cow_file_size(kSnapshotSize);
416 ASSERT_TRUE(sm->CreateSnapshot(lock_.get(), &status));
417 ASSERT_TRUE(CreateCowImage("test-snapshot"));
418
419 std::string base_device;
420 ASSERT_TRUE(CreatePartition("base-device", kDeviceSize, &base_device));
421
422 std::string cow_device;
423 ASSERT_TRUE(MapCowImage("test-snapshot", 10s, &cow_device));
424
425 std::string snap_device;
426 ASSERT_TRUE(sm->MapSnapshot(lock_.get(), "test-snapshot", base_device, cow_device, 10s,
427 &snap_device));
428 ASSERT_TRUE(android::base::StartsWith(snap_device, "/dev/block/dm-"));
429 }
430
TEST_F(SnapshotTest,NoMergeBeforeReboot)431 TEST_F(SnapshotTest, NoMergeBeforeReboot) {
432 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
433
434 // Merge should fail, since the slot hasn't changed.
435 ASSERT_FALSE(sm->InitiateMerge());
436 }
437
TEST_F(SnapshotTest,CleanFirstStageMount)438 TEST_F(SnapshotTest, CleanFirstStageMount) {
439 // If there's no update in progress, there should be no first-stage mount
440 // needed.
441 TestDeviceInfo* info = new TestDeviceInfo(fake_super);
442 auto sm = SnapshotManager::NewForFirstStageMount(info);
443 ASSERT_NE(sm, nullptr);
444 ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
445 }
446
TEST_F(SnapshotTest,FirstStageMountAfterRollback)447 TEST_F(SnapshotTest, FirstStageMountAfterRollback) {
448 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
449
450 // We didn't change the slot, so we shouldn't need snapshots.
451 TestDeviceInfo* info = new TestDeviceInfo(fake_super);
452 auto sm = SnapshotManager::NewForFirstStageMount(info);
453 ASSERT_NE(sm, nullptr);
454 ASSERT_FALSE(sm->NeedSnapshotsInFirstStageMount());
455
456 auto indicator = sm->GetRollbackIndicatorPath();
457 ASSERT_EQ(access(indicator.c_str(), R_OK), 0);
458 }
459
TEST_F(SnapshotTest,Merge)460 TEST_F(SnapshotTest, Merge) {
461 ASSERT_TRUE(AcquireLock());
462
463 static const uint64_t kDeviceSize = 1024 * 1024;
464 std::string snap_device;
465 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize, &snap_device));
466
467 std::string test_string = "This is a test string.";
468 {
469 unique_fd fd(open(snap_device.c_str(), O_RDWR | O_CLOEXEC | O_SYNC));
470 ASSERT_GE(fd, 0);
471 ASSERT_TRUE(android::base::WriteFully(fd, test_string.data(), test_string.size()));
472 }
473
474 // Note: we know there is no inner/outer dm device since we didn't request
475 // a linear segment.
476 DeviceMapper::TargetInfo target;
477 ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
478 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
479
480 // Release the lock.
481 lock_ = nullptr;
482
483 // Done updating.
484 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
485
486 test_device->set_slot_suffix("_b");
487 ASSERT_TRUE(sm->InitiateMerge());
488
489 // The device should have been switched to a snapshot-merge target.
490 ASSERT_TRUE(sm->IsSnapshotDevice("test_partition_b", &target));
491 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot-merge");
492
493 // We should not be able to cancel an update now.
494 ASSERT_FALSE(sm->CancelUpdate());
495
496 ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::MergeCompleted);
497 ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
498
499 // The device should no longer be a snapshot or snapshot-merge.
500 ASSERT_FALSE(sm->IsSnapshotDevice("test_partition_b"));
501
502 // Test that we can read back the string we wrote to the snapshot. Note
503 // that the base device is gone now. |snap_device| contains the correct
504 // partition.
505 unique_fd fd(open(snap_device.c_str(), O_RDONLY | O_CLOEXEC));
506 ASSERT_GE(fd, 0);
507
508 std::string buffer(test_string.size(), '\0');
509 ASSERT_TRUE(android::base::ReadFully(fd, buffer.data(), buffer.size()));
510 ASSERT_EQ(test_string, buffer);
511 }
512
TEST_F(SnapshotTest,FirstStageMountAndMerge)513 TEST_F(SnapshotTest, FirstStageMountAndMerge) {
514 ASSERT_TRUE(AcquireLock());
515
516 static const uint64_t kDeviceSize = 1024 * 1024;
517 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
518 ASSERT_TRUE(SimulateReboot());
519
520 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
521 ASSERT_NE(init, nullptr);
522 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
523 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
524
525 ASSERT_TRUE(AcquireLock());
526
527 // Validate that we have a snapshot device.
528 SnapshotStatus status;
529 ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
530 ASSERT_EQ(status.state(), SnapshotState::CREATED);
531
532 DeviceMapper::TargetInfo target;
533 auto dm_name = init->GetSnapshotDeviceName("test_partition_b", status);
534 ASSERT_TRUE(init->IsSnapshotDevice(dm_name, &target));
535 ASSERT_EQ(DeviceMapper::GetTargetType(target.spec), "snapshot");
536 }
537
TEST_F(SnapshotTest,FlashSuperDuringUpdate)538 TEST_F(SnapshotTest, FlashSuperDuringUpdate) {
539 ASSERT_TRUE(AcquireLock());
540
541 static const uint64_t kDeviceSize = 1024 * 1024;
542 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
543 ASSERT_TRUE(SimulateReboot());
544
545 // Reflash the super partition.
546 FormatFakeSuper();
547 ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
548
549 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
550 ASSERT_NE(init, nullptr);
551 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
552 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
553
554 ASSERT_TRUE(AcquireLock());
555
556 SnapshotStatus status;
557 ASSERT_TRUE(init->ReadSnapshotStatus(lock_.get(), "test_partition_b", &status));
558
559 // We should not get a snapshot device now.
560 DeviceMapper::TargetInfo target;
561 auto dm_name = init->GetSnapshotDeviceName("test_partition_b", status);
562 ASSERT_FALSE(init->IsSnapshotDevice(dm_name, &target));
563
564 // We should see a cancelled update as well.
565 lock_ = nullptr;
566 ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
567 }
568
TEST_F(SnapshotTest,FlashSuperDuringMerge)569 TEST_F(SnapshotTest, FlashSuperDuringMerge) {
570 ASSERT_TRUE(AcquireLock());
571
572 static const uint64_t kDeviceSize = 1024 * 1024;
573 ASSERT_TRUE(PrepareOneSnapshot(kDeviceSize));
574 ASSERT_TRUE(SimulateReboot());
575
576 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
577 ASSERT_NE(init, nullptr);
578 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
579 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
580 ASSERT_TRUE(init->InitiateMerge());
581
582 // Now, reflash super. Note that we haven't called ProcessUpdateState, so the
583 // status is still Merging.
584 ASSERT_TRUE(DeleteSnapshotDevice("test_partition_b"));
585 ASSERT_TRUE(init->image_manager()->UnmapImageIfExists("test_partition_b-cow-img"));
586 FormatFakeSuper();
587 ASSERT_TRUE(CreatePartition("test_partition_b", kDeviceSize));
588 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
589 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
590
591 // Because the status is Merging, we must call ProcessUpdateState, which should
592 // detect a cancelled update.
593 ASSERT_EQ(sm->ProcessUpdateState(), UpdateState::Cancelled);
594 ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
595 }
596
TEST_F(SnapshotTest,UpdateBootControlHal)597 TEST_F(SnapshotTest, UpdateBootControlHal) {
598 ASSERT_TRUE(AcquireLock());
599
600 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
601 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
602
603 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
604 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
605
606 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
607 ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
608
609 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
610 ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
611
612 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
613 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
614
615 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
616 ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
617
618 ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
619 ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
620 }
621
622 enum class Request { UNKNOWN, LOCK_SHARED, LOCK_EXCLUSIVE, UNLOCK, EXIT };
operator <<(std::ostream & os,Request request)623 std::ostream& operator<<(std::ostream& os, Request request) {
624 switch (request) {
625 case Request::LOCK_SHARED:
626 return os << "Shared";
627 case Request::LOCK_EXCLUSIVE:
628 return os << "Exclusive";
629 case Request::UNLOCK:
630 return os << "Unlock";
631 case Request::EXIT:
632 return os << "Exit";
633 case Request::UNKNOWN:
634 [[fallthrough]];
635 default:
636 return os << "Unknown";
637 }
638 }
639
640 class LockTestConsumer {
641 public:
MakeRequest(Request new_request)642 AssertionResult MakeRequest(Request new_request) {
643 {
644 std::unique_lock<std::mutex> ulock(mutex_);
645 requests_.push_back(new_request);
646 }
647 cv_.notify_all();
648 return AssertionSuccess() << "Request " << new_request << " successful";
649 }
650
651 template <typename R, typename P>
WaitFulfill(std::chrono::duration<R,P> timeout)652 AssertionResult WaitFulfill(std::chrono::duration<R, P> timeout) {
653 std::unique_lock<std::mutex> ulock(mutex_);
654 if (cv_.wait_for(ulock, timeout, [this] { return requests_.empty(); })) {
655 return AssertionSuccess() << "All requests_ fulfilled.";
656 }
657 return AssertionFailure() << "Timeout waiting for fulfilling " << requests_.size()
658 << " request(s), first one is "
659 << (requests_.empty() ? Request::UNKNOWN : requests_.front());
660 }
661
StartHandleRequestsInBackground()662 void StartHandleRequestsInBackground() {
663 future_ = std::async(std::launch::async, &LockTestConsumer::HandleRequests, this);
664 }
665
666 private:
HandleRequests()667 void HandleRequests() {
668 static constexpr auto consumer_timeout = 3s;
669
670 auto next_request = Request::UNKNOWN;
671 do {
672 // Peek next request.
673 {
674 std::unique_lock<std::mutex> ulock(mutex_);
675 if (cv_.wait_for(ulock, consumer_timeout, [this] { return !requests_.empty(); })) {
676 next_request = requests_.front();
677 } else {
678 next_request = Request::EXIT;
679 }
680 }
681
682 // Handle next request.
683 switch (next_request) {
684 case Request::LOCK_SHARED: {
685 lock_ = sm->LockShared();
686 } break;
687 case Request::LOCK_EXCLUSIVE: {
688 lock_ = sm->LockExclusive();
689 } break;
690 case Request::EXIT:
691 [[fallthrough]];
692 case Request::UNLOCK: {
693 lock_.reset();
694 } break;
695 case Request::UNKNOWN:
696 [[fallthrough]];
697 default:
698 break;
699 }
700
701 // Pop next request. This thread is the only thread that
702 // pops from the front of the requests_ deque.
703 {
704 std::unique_lock<std::mutex> ulock(mutex_);
705 if (next_request == Request::EXIT) {
706 requests_.clear();
707 } else {
708 requests_.pop_front();
709 }
710 }
711 cv_.notify_all();
712 } while (next_request != Request::EXIT);
713 }
714
715 std::mutex mutex_;
716 std::condition_variable cv_;
717 std::deque<Request> requests_;
718 std::unique_ptr<SnapshotManager::LockedFile> lock_;
719 std::future<void> future_;
720 };
721
722 class LockTest : public ::testing::Test {
723 public:
SetUp()724 void SetUp() {
725 first_consumer.StartHandleRequestsInBackground();
726 second_consumer.StartHandleRequestsInBackground();
727 }
728
TearDown()729 void TearDown() {
730 EXPECT_TRUE(first_consumer.MakeRequest(Request::EXIT));
731 EXPECT_TRUE(second_consumer.MakeRequest(Request::EXIT));
732 }
733
734 static constexpr auto request_timeout = 500ms;
735 LockTestConsumer first_consumer;
736 LockTestConsumer second_consumer;
737 };
738
TEST_F(LockTest,SharedShared)739 TEST_F(LockTest, SharedShared) {
740 ASSERT_TRUE(first_consumer.MakeRequest(Request::LOCK_SHARED));
741 ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
742 ASSERT_TRUE(second_consumer.MakeRequest(Request::LOCK_SHARED));
743 ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout));
744 }
745
746 using LockTestParam = std::pair<Request, Request>;
747 class LockTestP : public LockTest, public ::testing::WithParamInterface<LockTestParam> {};
TEST_P(LockTestP,Test)748 TEST_P(LockTestP, Test) {
749 ASSERT_TRUE(first_consumer.MakeRequest(GetParam().first));
750 ASSERT_TRUE(first_consumer.WaitFulfill(request_timeout));
751 ASSERT_TRUE(second_consumer.MakeRequest(GetParam().second));
752 ASSERT_FALSE(second_consumer.WaitFulfill(request_timeout))
753 << "Should not be able to " << GetParam().second << " while separate thread "
754 << GetParam().first;
755 ASSERT_TRUE(first_consumer.MakeRequest(Request::UNLOCK));
756 ASSERT_TRUE(second_consumer.WaitFulfill(request_timeout))
757 << "Should be able to hold lock that is released by separate thread";
758 }
759 INSTANTIATE_TEST_SUITE_P(
760 LockTest, LockTestP,
761 testing::Values(LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_EXCLUSIVE},
762 LockTestParam{Request::LOCK_EXCLUSIVE, Request::LOCK_SHARED},
763 LockTestParam{Request::LOCK_SHARED, Request::LOCK_EXCLUSIVE}),
__anon4de4482e0302(const testing::TestParamInfo<LockTestP::ParamType>& info) 764 [](const testing::TestParamInfo<LockTestP::ParamType>& info) {
765 std::stringstream ss;
766 ss << info.param.first << info.param.second;
767 return ss.str();
768 });
769
770 class SnapshotUpdateTest : public SnapshotTest {
771 public:
SetUp()772 void SetUp() override {
773 if (!is_virtual_ab_) GTEST_SKIP() << "Test for Virtual A/B devices only";
774
775 SnapshotTest::SetUp();
776 Cleanup();
777
778 // Cleanup() changes slot suffix, so initialize it again.
779 test_device->set_slot_suffix("_a");
780
781 opener_ = std::make_unique<TestPartitionOpener>(fake_super);
782
783 // Create a fake update package metadata.
784 // Not using full name "system", "vendor", "product" because these names collide with the
785 // mapped partitions on the running device.
786 // Each test modifies manifest_ slightly to indicate changes to the partition layout.
787 group_ = manifest_.mutable_dynamic_partition_metadata()->add_groups();
788 group_->set_name("group");
789 group_->set_size(kGroupSize);
790 group_->add_partition_names("sys");
791 group_->add_partition_names("vnd");
792 group_->add_partition_names("prd");
793 sys_ = manifest_.add_partitions();
794 sys_->set_partition_name("sys");
795 SetSize(sys_, 3_MiB);
796 vnd_ = manifest_.add_partitions();
797 vnd_->set_partition_name("vnd");
798 SetSize(vnd_, 3_MiB);
799 prd_ = manifest_.add_partitions();
800 prd_->set_partition_name("prd");
801 SetSize(prd_, 3_MiB);
802
803 // Initialize source partition metadata using |manifest_|.
804 src_ = MetadataBuilder::New(*opener_, "super", 0);
805 ASSERT_NE(src_, nullptr);
806 ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
807 // Add sys_b which is like system_other.
808 ASSERT_TRUE(src_->AddGroup("group_b", kGroupSize));
809 auto partition = src_->AddPartition("sys_b", "group_b", 0);
810 ASSERT_NE(nullptr, partition);
811 ASSERT_TRUE(src_->ResizePartition(partition, 1_MiB));
812 auto metadata = src_->Export();
813 ASSERT_NE(nullptr, metadata);
814 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
815
816 // Map source partitions. Additionally, map sys_b to simulate system_other after flashing.
817 std::string path;
818 for (const auto& name : {"sys_a", "vnd_a", "prd_a", "sys_b"}) {
819 ASSERT_TRUE(CreateLogicalPartition(
820 CreateLogicalPartitionParams{
821 .block_device = fake_super,
822 .metadata_slot = 0,
823 .partition_name = name,
824 .timeout_ms = 1s,
825 .partition_opener = opener_.get(),
826 },
827 &path));
828 ASSERT_TRUE(WriteRandomData(path));
829 auto hash = GetHash(path);
830 ASSERT_TRUE(hash.has_value());
831 hashes_[name] = *hash;
832 }
833 }
TearDown()834 void TearDown() override {
835 if (!is_virtual_ab_) return;
836
837 Cleanup();
838 SnapshotTest::TearDown();
839 }
Cleanup()840 void Cleanup() {
841 if (!image_manager_) {
842 InitializeState();
843 }
844 MountMetadata();
845 for (const auto& suffix : {"_a", "_b"}) {
846 test_device->set_slot_suffix(suffix);
847 EXPECT_TRUE(sm->CancelUpdate()) << suffix;
848 }
849 EXPECT_TRUE(UnmapAll());
850 }
851
IsPartitionUnchanged(const std::string & name)852 AssertionResult IsPartitionUnchanged(const std::string& name) {
853 std::string path;
854 if (!dm_.GetDmDevicePathByName(name, &path)) {
855 return AssertionFailure() << "Path of " << name << " cannot be determined";
856 }
857 auto hash = GetHash(path);
858 if (!hash.has_value()) {
859 return AssertionFailure() << "Cannot read partition " << name << ": " << path;
860 }
861 auto it = hashes_.find(name);
862 if (it == hashes_.end()) {
863 return AssertionFailure() << "No existing hash for " << name << ". Bad test code?";
864 }
865 if (it->second != *hash) {
866 return AssertionFailure() << "Content of " << name << " has changed";
867 }
868 return AssertionSuccess();
869 }
870
GetSnapshotSize(const std::string & name)871 std::optional<uint64_t> GetSnapshotSize(const std::string& name) {
872 if (!AcquireLock()) {
873 return std::nullopt;
874 }
875 auto local_lock = std::move(lock_);
876
877 SnapshotStatus status;
878 if (!sm->ReadSnapshotStatus(local_lock.get(), name, &status)) {
879 return std::nullopt;
880 }
881 return status.snapshot_size();
882 }
883
UnmapAll()884 AssertionResult UnmapAll() {
885 for (const auto& name : {"sys", "vnd", "prd"}) {
886 if (!dm_.DeleteDeviceIfExists(name + "_a"s)) {
887 return AssertionFailure() << "Cannot unmap " << name << "_a";
888 }
889 if (!DeleteSnapshotDevice(name + "_b"s)) {
890 return AssertionFailure() << "Cannot delete snapshot " << name << "_b";
891 }
892 }
893 return AssertionSuccess();
894 }
895
MapUpdateSnapshot(const std::string & name,std::string * path=nullptr)896 AssertionResult MapUpdateSnapshot(const std::string& name, std::string* path = nullptr) {
897 std::string real_path;
898 if (!sm->MapUpdateSnapshot(
899 CreateLogicalPartitionParams{
900 .block_device = fake_super,
901 .metadata_slot = 1,
902 .partition_name = name,
903 .timeout_ms = 10s,
904 .partition_opener = opener_.get(),
905 },
906 &real_path)) {
907 return AssertionFailure() << "Unable to map snapshot " << name;
908 }
909 if (path) {
910 *path = real_path;
911 }
912 return AssertionSuccess() << "Mapped snapshot " << name << " to " << real_path;
913 }
914
WriteSnapshotAndHash(const std::string & name,std::optional<size_t> size=std::nullopt)915 AssertionResult WriteSnapshotAndHash(const std::string& name,
916 std::optional<size_t> size = std::nullopt) {
917 std::string path;
918 auto res = MapUpdateSnapshot(name, &path);
919 if (!res) {
920 return res;
921 }
922
923 std::string size_string = size ? (std::to_string(*size) + " bytes") : "";
924
925 if (!WriteRandomData(path, size, &hashes_[name])) {
926 return AssertionFailure() << "Unable to write " << size_string << " to " << path
927 << " for partition " << name;
928 }
929
930 return AssertionSuccess() << "Written " << size_string << " to " << path
931 << " for snapshot partition " << name
932 << ", hash: " << hashes_[name];
933 }
934
MapUpdateSnapshots(const std::vector<std::string> & names={"sys_b", "vnd_b", "prd_b"})935 AssertionResult MapUpdateSnapshots(const std::vector<std::string>& names = {"sys_b", "vnd_b",
936 "prd_b"}) {
937 for (const auto& name : names) {
938 auto res = MapUpdateSnapshot(name);
939 if (!res) {
940 return res;
941 }
942 }
943 return AssertionSuccess();
944 }
945
946 // Create fake install operations to grow the COW device size.
AddOperation(PartitionUpdate * partition_update,uint64_t size_bytes=0)947 void AddOperation(PartitionUpdate* partition_update, uint64_t size_bytes = 0) {
948 auto e = partition_update->add_operations()->add_dst_extents();
949 e->set_start_block(0);
950 if (size_bytes == 0) {
951 size_bytes = GetSize(partition_update);
952 }
953 e->set_num_blocks(size_bytes / manifest_.block_size());
954 }
955
AddOperationForPartitions(std::vector<PartitionUpdate * > partitions={})956 void AddOperationForPartitions(std::vector<PartitionUpdate*> partitions = {}) {
957 if (partitions.empty()) {
958 partitions = {sys_, vnd_, prd_};
959 }
960 for (auto* partition : partitions) {
961 AddOperation(partition);
962 }
963 }
964
965 std::unique_ptr<TestPartitionOpener> opener_;
966 DeltaArchiveManifest manifest_;
967 std::unique_ptr<MetadataBuilder> src_;
968 std::map<std::string, std::string> hashes_;
969
970 PartitionUpdate* sys_ = nullptr;
971 PartitionUpdate* vnd_ = nullptr;
972 PartitionUpdate* prd_ = nullptr;
973 DynamicPartitionGroup* group_ = nullptr;
974 };
975
976 // Test full update flow executed by update_engine. Some partitions uses super empty space,
977 // some uses images, and some uses both.
978 // Also test UnmapUpdateSnapshot unmaps everything.
979 // Also test first stage mount and merge after this.
TEST_F(SnapshotUpdateTest,FullUpdateFlow)980 TEST_F(SnapshotUpdateTest, FullUpdateFlow) {
981 // OTA client blindly unmaps all partitions that are possibly mapped.
982 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
983 ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
984 }
985
986 // Grow all partitions.
987 constexpr uint64_t partition_size = 3788_KiB;
988 SetSize(sys_, partition_size);
989 SetSize(vnd_, partition_size);
990 SetSize(prd_, partition_size);
991
992 AddOperationForPartitions();
993
994 // Execute the update.
995 ASSERT_TRUE(sm->BeginUpdate());
996 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
997
998 // Test that partitions prioritize using space in super.
999 auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1000 ASSERT_NE(tgt, nullptr);
1001 ASSERT_NE(nullptr, tgt->FindPartition("sys_b-cow"));
1002 ASSERT_NE(nullptr, tgt->FindPartition("vnd_b-cow"));
1003 ASSERT_EQ(nullptr, tgt->FindPartition("prd_b-cow"));
1004
1005 // Write some data to target partitions.
1006 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1007 ASSERT_TRUE(WriteSnapshotAndHash(name, partition_size));
1008 }
1009
1010 // Assert that source partitions aren't affected.
1011 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1012 ASSERT_TRUE(IsPartitionUnchanged(name));
1013 }
1014
1015 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1016
1017 // Simulate shutting down the device.
1018 ASSERT_TRUE(UnmapAll());
1019
1020 // After reboot, init does first stage mount.
1021 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
1022 ASSERT_NE(init, nullptr);
1023 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1024 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1025
1026 auto indicator = sm->GetRollbackIndicatorPath();
1027 ASSERT_NE(access(indicator.c_str(), R_OK), 0);
1028
1029 // Check that the target partitions have the same content.
1030 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1031 ASSERT_TRUE(IsPartitionUnchanged(name));
1032 }
1033
1034 // Initiate the merge and wait for it to be completed.
1035 ASSERT_TRUE(init->InitiateMerge());
1036 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1037
1038 // Check that the target partitions have the same content after the merge.
1039 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1040 ASSERT_TRUE(IsPartitionUnchanged(name))
1041 << "Content of " << name << " changes after the merge";
1042 }
1043 }
1044
1045 // Test that if new system partitions uses empty space in super, that region is not snapshotted.
TEST_F(SnapshotUpdateTest,DirectWriteEmptySpace)1046 TEST_F(SnapshotUpdateTest, DirectWriteEmptySpace) {
1047 GTEST_SKIP() << "b/141889746";
1048 SetSize(sys_, 4_MiB);
1049 // vnd_b and prd_b are unchanged.
1050 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1051 ASSERT_EQ(3_MiB, GetSnapshotSize("sys_b").value_or(0));
1052 }
1053
1054 // Test that if new system partitions uses space of old vendor partition, that region is
1055 // snapshotted.
TEST_F(SnapshotUpdateTest,SnapshotOldPartitions)1056 TEST_F(SnapshotUpdateTest, SnapshotOldPartitions) {
1057 SetSize(sys_, 4_MiB); // grows
1058 SetSize(vnd_, 2_MiB); // shrinks
1059 // prd_b is unchanged
1060 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1061 ASSERT_EQ(4_MiB, GetSnapshotSize("sys_b").value_or(0));
1062 }
1063
1064 // Test that even if there seem to be empty space in target metadata, COW partition won't take
1065 // it because they are used by old partitions.
TEST_F(SnapshotUpdateTest,CowPartitionDoNotTakeOldPartitions)1066 TEST_F(SnapshotUpdateTest, CowPartitionDoNotTakeOldPartitions) {
1067 SetSize(sys_, 2_MiB); // shrinks
1068 // vnd_b and prd_b are unchanged.
1069 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1070
1071 auto tgt = MetadataBuilder::New(*opener_, "super", 1);
1072 ASSERT_NE(nullptr, tgt);
1073 auto metadata = tgt->Export();
1074 ASSERT_NE(nullptr, metadata);
1075 std::vector<std::string> written;
1076 // Write random data to all COW partitions in super
1077 for (auto p : metadata->partitions) {
1078 if (GetPartitionGroupName(metadata->groups[p.group_index]) != kCowGroupName) {
1079 continue;
1080 }
1081 std::string path;
1082 ASSERT_TRUE(CreateLogicalPartition(
1083 CreateLogicalPartitionParams{
1084 .block_device = fake_super,
1085 .metadata = metadata.get(),
1086 .partition = &p,
1087 .timeout_ms = 1s,
1088 .partition_opener = opener_.get(),
1089 },
1090 &path));
1091 ASSERT_TRUE(WriteRandomData(path));
1092 written.push_back(GetPartitionName(p));
1093 }
1094 ASSERT_FALSE(written.empty())
1095 << "No COW partitions are created even if there are empty space in super partition";
1096
1097 // Make sure source partitions aren't affected.
1098 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1099 ASSERT_TRUE(IsPartitionUnchanged(name));
1100 }
1101 }
1102
1103 // Test that it crashes after creating snapshot status file but before creating COW image, then
1104 // calling CreateUpdateSnapshots again works.
TEST_F(SnapshotUpdateTest,SnapshotStatusFileWithoutCow)1105 TEST_F(SnapshotUpdateTest, SnapshotStatusFileWithoutCow) {
1106 // Write some trash snapshot files to simulate leftovers from previous runs.
1107 {
1108 ASSERT_TRUE(AcquireLock());
1109 auto local_lock = std::move(lock_);
1110 SnapshotStatus status;
1111 status.set_name("sys_b");
1112 ASSERT_TRUE(sm->WriteSnapshotStatus(local_lock.get(), status));
1113 ASSERT_TRUE(image_manager_->CreateBackingImage("sys_b-cow-img", 1_MiB,
1114 IImageManager::CREATE_IMAGE_DEFAULT));
1115 }
1116
1117 // Redo the update.
1118 ASSERT_TRUE(sm->BeginUpdate());
1119 ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1120
1121 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1122
1123 // Check that target partitions can be mapped.
1124 EXPECT_TRUE(MapUpdateSnapshots());
1125 }
1126
1127 // Test that the old partitions are not modified.
TEST_F(SnapshotUpdateTest,TestRollback)1128 TEST_F(SnapshotUpdateTest, TestRollback) {
1129 // Execute the update.
1130 ASSERT_TRUE(sm->BeginUpdate());
1131 ASSERT_TRUE(sm->UnmapUpdateSnapshot("sys_b"));
1132
1133 AddOperationForPartitions();
1134
1135 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1136
1137 // Write some data to target partitions.
1138 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1139 ASSERT_TRUE(WriteSnapshotAndHash(name));
1140 }
1141
1142 // Assert that source partitions aren't affected.
1143 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1144 ASSERT_TRUE(IsPartitionUnchanged(name));
1145 }
1146
1147 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1148
1149 // Simulate shutting down the device.
1150 ASSERT_TRUE(UnmapAll());
1151
1152 // After reboot, init does first stage mount.
1153 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
1154 ASSERT_NE(init, nullptr);
1155 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1156 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1157
1158 // Check that the target partitions have the same content.
1159 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1160 ASSERT_TRUE(IsPartitionUnchanged(name));
1161 }
1162
1163 // Simulate shutting down the device again.
1164 ASSERT_TRUE(UnmapAll());
1165 init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_a"));
1166 ASSERT_NE(init, nullptr);
1167 ASSERT_FALSE(init->NeedSnapshotsInFirstStageMount());
1168 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1169
1170 // Assert that the source partitions aren't affected.
1171 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1172 ASSERT_TRUE(IsPartitionUnchanged(name));
1173 }
1174 }
1175
1176 // Test that if an update is applied but not booted into, it can be canceled.
TEST_F(SnapshotUpdateTest,CancelAfterApply)1177 TEST_F(SnapshotUpdateTest, CancelAfterApply) {
1178 ASSERT_TRUE(sm->BeginUpdate());
1179 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1180 ASSERT_TRUE(sm->CancelUpdate());
1181 }
1182
ToIntervals(const std::vector<std::unique_ptr<Extent>> & extents)1183 static std::vector<Interval> ToIntervals(const std::vector<std::unique_ptr<Extent>>& extents) {
1184 std::vector<Interval> ret;
1185 std::transform(extents.begin(), extents.end(), std::back_inserter(ret),
1186 [](const auto& extent) { return extent->AsLinearExtent()->AsInterval(); });
1187 return ret;
1188 }
1189
1190 // Test that at the second update, old COW partition spaces are reclaimed.
TEST_F(SnapshotUpdateTest,ReclaimCow)1191 TEST_F(SnapshotUpdateTest, ReclaimCow) {
1192 // Execute the first update.
1193 ASSERT_TRUE(sm->BeginUpdate());
1194 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1195 ASSERT_TRUE(MapUpdateSnapshots());
1196 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1197
1198 // Simulate shutting down the device.
1199 ASSERT_TRUE(UnmapAll());
1200
1201 // After reboot, init does first stage mount.
1202 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
1203 ASSERT_NE(init, nullptr);
1204 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1205 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1206 init = nullptr;
1207
1208 // Initiate the merge and wait for it to be completed.
1209 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1210 ASSERT_TRUE(new_sm->InitiateMerge());
1211 ASSERT_EQ(UpdateState::MergeCompleted, new_sm->ProcessUpdateState());
1212
1213 // Execute the second update.
1214 ASSERT_TRUE(new_sm->BeginUpdate());
1215 ASSERT_TRUE(new_sm->CreateUpdateSnapshots(manifest_));
1216
1217 // Check that the old COW space is reclaimed and does not occupy space of mapped partitions.
1218 auto src = MetadataBuilder::New(*opener_, "super", 1);
1219 ASSERT_NE(src, nullptr);
1220 auto tgt = MetadataBuilder::New(*opener_, "super", 0);
1221 ASSERT_NE(tgt, nullptr);
1222 for (const auto& cow_part_name : {"sys_a-cow", "vnd_a-cow", "prd_a-cow"}) {
1223 auto* cow_part = tgt->FindPartition(cow_part_name);
1224 ASSERT_NE(nullptr, cow_part) << cow_part_name << " does not exist in target metadata";
1225 auto cow_intervals = ToIntervals(cow_part->extents());
1226 for (const auto& old_part_name : {"sys_b", "vnd_b", "prd_b"}) {
1227 auto* old_part = src->FindPartition(old_part_name);
1228 ASSERT_NE(nullptr, old_part) << old_part_name << " does not exist in source metadata";
1229 auto old_intervals = ToIntervals(old_part->extents());
1230
1231 auto intersect = Interval::Intersect(cow_intervals, old_intervals);
1232 ASSERT_TRUE(intersect.empty()) << "COW uses space of source partitions";
1233 }
1234 }
1235 }
1236
TEST_F(SnapshotUpdateTest,RetrofitAfterRegularAb)1237 TEST_F(SnapshotUpdateTest, RetrofitAfterRegularAb) {
1238 constexpr auto kRetrofitGroupSize = kGroupSize / 2;
1239
1240 // Initialize device-mapper / disk
1241 ASSERT_TRUE(UnmapAll());
1242 FormatFakeSuper();
1243
1244 // Setup source partition metadata to have both _a and _b partitions.
1245 src_ = MetadataBuilder::New(*opener_, "super", 0);
1246 ASSERT_NE(nullptr, src_);
1247 for (const auto& suffix : {"_a"s, "_b"s}) {
1248 ASSERT_TRUE(src_->AddGroup(group_->name() + suffix, kRetrofitGroupSize));
1249 for (const auto& name : {"sys"s, "vnd"s, "prd"s}) {
1250 auto partition = src_->AddPartition(name + suffix, group_->name() + suffix, 0);
1251 ASSERT_NE(nullptr, partition);
1252 ASSERT_TRUE(src_->ResizePartition(partition, 2_MiB));
1253 }
1254 }
1255 auto metadata = src_->Export();
1256 ASSERT_NE(nullptr, metadata);
1257 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1258
1259 // Flash source partitions
1260 std::string path;
1261 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1262 ASSERT_TRUE(CreateLogicalPartition(
1263 CreateLogicalPartitionParams{
1264 .block_device = fake_super,
1265 .metadata_slot = 0,
1266 .partition_name = name,
1267 .timeout_ms = 1s,
1268 .partition_opener = opener_.get(),
1269 },
1270 &path));
1271 ASSERT_TRUE(WriteRandomData(path));
1272 auto hash = GetHash(path);
1273 ASSERT_TRUE(hash.has_value());
1274 hashes_[name] = *hash;
1275 }
1276
1277 // Setup manifest.
1278 group_->set_size(kRetrofitGroupSize);
1279 for (auto* partition : {sys_, vnd_, prd_}) {
1280 SetSize(partition, 2_MiB);
1281 }
1282 AddOperationForPartitions();
1283
1284 ASSERT_TRUE(sm->BeginUpdate());
1285 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1286
1287 // Test that COW image should not be created for retrofit devices; super
1288 // should be big enough.
1289 ASSERT_FALSE(image_manager_->BackingImageExists("sys_b-cow-img"));
1290 ASSERT_FALSE(image_manager_->BackingImageExists("vnd_b-cow-img"));
1291 ASSERT_FALSE(image_manager_->BackingImageExists("prd_b-cow-img"));
1292
1293 // Write some data to target partitions.
1294 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1295 ASSERT_TRUE(WriteSnapshotAndHash(name));
1296 }
1297
1298 // Assert that source partitions aren't affected.
1299 for (const auto& name : {"sys_a", "vnd_a", "prd_a"}) {
1300 ASSERT_TRUE(IsPartitionUnchanged(name));
1301 }
1302
1303 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1304 }
1305
TEST_F(SnapshotUpdateTest,MergeCannotRemoveCow)1306 TEST_F(SnapshotUpdateTest, MergeCannotRemoveCow) {
1307 // Make source partitions as big as possible to force COW image to be created.
1308 SetSize(sys_, 5_MiB);
1309 SetSize(vnd_, 5_MiB);
1310 SetSize(prd_, 5_MiB);
1311 src_ = MetadataBuilder::New(*opener_, "super", 0);
1312 ASSERT_NE(src_, nullptr);
1313 src_->RemoveGroupAndPartitions(group_->name() + "_a");
1314 src_->RemoveGroupAndPartitions(group_->name() + "_b");
1315 ASSERT_TRUE(FillFakeMetadata(src_.get(), manifest_, "_a"));
1316 auto metadata = src_->Export();
1317 ASSERT_NE(nullptr, metadata);
1318 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *metadata.get(), 0));
1319
1320 // OTA client blindly unmaps all partitions that are possibly mapped.
1321 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1322 ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
1323 }
1324
1325 // Add operations for sys. The whole device is written.
1326 AddOperation(sys_);
1327
1328 // Execute the update.
1329 ASSERT_TRUE(sm->BeginUpdate());
1330 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1331 ASSERT_TRUE(MapUpdateSnapshots());
1332 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1333
1334 // Simulate shutting down the device.
1335 ASSERT_TRUE(UnmapAll());
1336
1337 // After reboot, init does first stage mount.
1338 // Normally we should use NewForFirstStageMount, but if so, "gsid.mapped_image.sys_b-cow-img"
1339 // won't be set.
1340 auto init = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1341 ASSERT_NE(init, nullptr);
1342 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1343
1344 // Keep an open handle to the cow device. This should cause the merge to
1345 // be incomplete.
1346 auto cow_path = android::base::GetProperty("gsid.mapped_image.sys_b-cow-img", "");
1347 unique_fd fd(open(cow_path.c_str(), O_RDONLY | O_CLOEXEC));
1348 ASSERT_GE(fd, 0);
1349
1350 // COW cannot be removed due to open fd, so expect a soft failure.
1351 ASSERT_TRUE(init->InitiateMerge());
1352 ASSERT_EQ(UpdateState::MergeNeedsReboot, init->ProcessUpdateState());
1353
1354 // Simulate shutting down the device.
1355 fd.reset();
1356 ASSERT_TRUE(UnmapAll());
1357
1358 // init does first stage mount again.
1359 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1360
1361 // sys_b should be mapped as a dm-linear device directly.
1362 ASSERT_FALSE(sm->IsSnapshotDevice("sys_b", nullptr));
1363
1364 // Merge should be able to complete now.
1365 ASSERT_EQ(UpdateState::MergeCompleted, init->ProcessUpdateState());
1366 }
1367
1368 class MetadataMountedTest : public SnapshotUpdateTest {
1369 public:
SetUp()1370 void SetUp() override {
1371 metadata_dir_ = test_device->GetMetadataDir();
1372 ASSERT_TRUE(ReadDefaultFstab(&fstab_));
1373 }
TearDown()1374 void TearDown() override {
1375 SetUp();
1376 // Remount /metadata
1377 test_device->set_recovery(false);
1378 EXPECT_TRUE(android::fs_mgr::EnsurePathMounted(&fstab_, metadata_dir_));
1379 }
IsMetadataMounted()1380 AssertionResult IsMetadataMounted() {
1381 Fstab mounted_fstab;
1382 if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
1383 ADD_FAILURE() << "Failed to scan mounted volumes";
1384 return AssertionFailure() << "Failed to scan mounted volumes";
1385 }
1386
1387 auto entry = GetEntryForPath(&fstab_, metadata_dir_);
1388 if (entry == nullptr) {
1389 return AssertionFailure() << "No mount point found in fstab for path " << metadata_dir_;
1390 }
1391
1392 auto mv = GetEntryForMountPoint(&mounted_fstab, entry->mount_point);
1393 if (mv == nullptr) {
1394 return AssertionFailure() << metadata_dir_ << " is not mounted";
1395 }
1396 return AssertionSuccess() << metadata_dir_ << " is mounted";
1397 }
1398 std::string metadata_dir_;
1399 Fstab fstab_;
1400 };
1401
MountMetadata()1402 void MountMetadata() {
1403 MetadataMountedTest().TearDown();
1404 }
1405
TEST_F(MetadataMountedTest,Android)1406 TEST_F(MetadataMountedTest, Android) {
1407 auto device = sm->EnsureMetadataMounted();
1408 EXPECT_NE(nullptr, device);
1409 device.reset();
1410
1411 EXPECT_TRUE(IsMetadataMounted());
1412 EXPECT_TRUE(sm->CancelUpdate()) << "Metadata dir should never be unmounted in Android mode";
1413 }
1414
TEST_F(MetadataMountedTest,Recovery)1415 TEST_F(MetadataMountedTest, Recovery) {
1416 test_device->set_recovery(true);
1417 metadata_dir_ = test_device->GetMetadataDir();
1418
1419 EXPECT_TRUE(android::fs_mgr::EnsurePathUnmounted(&fstab_, metadata_dir_));
1420 EXPECT_FALSE(IsMetadataMounted());
1421
1422 auto device = sm->EnsureMetadataMounted();
1423 EXPECT_NE(nullptr, device);
1424 EXPECT_TRUE(IsMetadataMounted());
1425
1426 device.reset();
1427 EXPECT_FALSE(IsMetadataMounted());
1428 }
1429
1430 // Test that during a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,MergeInRecovery)1431 TEST_F(SnapshotUpdateTest, MergeInRecovery) {
1432 // Execute the first update.
1433 ASSERT_TRUE(sm->BeginUpdate());
1434 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1435 ASSERT_TRUE(MapUpdateSnapshots());
1436 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1437
1438 // Simulate shutting down the device.
1439 ASSERT_TRUE(UnmapAll());
1440
1441 // After reboot, init does first stage mount.
1442 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
1443 ASSERT_NE(init, nullptr);
1444 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1445 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1446 init = nullptr;
1447
1448 // Initiate the merge and then immediately stop it to simulate a reboot.
1449 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1450 ASSERT_TRUE(new_sm->InitiateMerge());
1451 ASSERT_TRUE(UnmapAll());
1452
1453 // Simulate a reboot into recovery.
1454 auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1455 test_device->set_recovery(true);
1456 new_sm = SnapshotManager::NewForFirstStageMount(test_device.release());
1457
1458 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1459 ASSERT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1460 }
1461
1462 // Test that a merge does not clear the snapshot state in fastboot.
TEST_F(SnapshotUpdateTest,MergeInFastboot)1463 TEST_F(SnapshotUpdateTest, MergeInFastboot) {
1464 // Execute the first update.
1465 ASSERT_TRUE(sm->BeginUpdate());
1466 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1467 ASSERT_TRUE(MapUpdateSnapshots());
1468 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1469
1470 // Simulate shutting down the device.
1471 ASSERT_TRUE(UnmapAll());
1472
1473 // After reboot, init does first stage mount.
1474 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
1475 ASSERT_NE(init, nullptr);
1476 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1477 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1478 init = nullptr;
1479
1480 // Initiate the merge and then immediately stop it to simulate a reboot.
1481 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, "_b"));
1482 ASSERT_TRUE(new_sm->InitiateMerge());
1483 ASSERT_TRUE(UnmapAll());
1484
1485 // Simulate a reboot into recovery.
1486 auto test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1487 test_device->set_recovery(true);
1488 new_sm = SnapshotManager::NewForFirstStageMount(test_device.release());
1489
1490 ASSERT_TRUE(new_sm->FinishMergeInRecovery());
1491
1492 auto mount = new_sm->EnsureMetadataMounted();
1493 ASSERT_TRUE(mount && mount->HasDevice());
1494 ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
1495
1496 // Finish the merge in a normal boot.
1497 test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1498 init = SnapshotManager::NewForFirstStageMount(test_device.release());
1499 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1500 init = nullptr;
1501
1502 test_device = std::make_unique<TestDeviceInfo>(fake_super, "_b");
1503 new_sm = SnapshotManager::NewForFirstStageMount(test_device.release());
1504 ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::MergeCompleted);
1505 ASSERT_EQ(new_sm->ProcessUpdateState(), UpdateState::None);
1506 }
1507
1508 // Test that after an OTA, before a merge, we can wipe data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeRollbackInRecovery)1509 TEST_F(SnapshotUpdateTest, DataWipeRollbackInRecovery) {
1510 // Execute the first update.
1511 ASSERT_TRUE(sm->BeginUpdate());
1512 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1513 ASSERT_TRUE(MapUpdateSnapshots());
1514 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1515
1516 // Simulate shutting down the device.
1517 ASSERT_TRUE(UnmapAll());
1518
1519 // Simulate a reboot into recovery.
1520 auto test_device = new TestDeviceInfo(fake_super, "_b");
1521 test_device->set_recovery(true);
1522 auto new_sm = SnapshotManager::NewForFirstStageMount(test_device);
1523
1524 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1525 // Manually mount metadata so that we can call GetUpdateState() below.
1526 MountMetadata();
1527 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::Unverified);
1528 EXPECT_TRUE(test_device->IsSlotUnbootable(1));
1529 EXPECT_FALSE(test_device->IsSlotUnbootable(0));
1530 }
1531
1532 // Test that after an OTA and a bootloader rollback with no merge, we can wipe
1533 // data in recovery.
TEST_F(SnapshotUpdateTest,DataWipeAfterRollback)1534 TEST_F(SnapshotUpdateTest, DataWipeAfterRollback) {
1535 // Execute the first update.
1536 ASSERT_TRUE(sm->BeginUpdate());
1537 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1538 ASSERT_TRUE(MapUpdateSnapshots());
1539 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1540
1541 // Simulate shutting down the device.
1542 ASSERT_TRUE(UnmapAll());
1543
1544 // Simulate a rollback, with reboot into recovery.
1545 auto test_device = new TestDeviceInfo(fake_super, "_a");
1546 test_device->set_recovery(true);
1547 auto new_sm = SnapshotManager::NewForFirstStageMount(test_device);
1548
1549 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1550 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1551 EXPECT_FALSE(test_device->IsSlotUnbootable(0));
1552 EXPECT_FALSE(test_device->IsSlotUnbootable(1));
1553 }
1554
1555 // Test update package that requests data wipe.
TEST_F(SnapshotUpdateTest,DataWipeRequiredInPackage)1556 TEST_F(SnapshotUpdateTest, DataWipeRequiredInPackage) {
1557 AddOperationForPartitions();
1558 // Execute the update.
1559 ASSERT_TRUE(sm->BeginUpdate());
1560 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1561
1562 // Write some data to target partitions.
1563 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1564 ASSERT_TRUE(WriteSnapshotAndHash(name)) << name;
1565 }
1566
1567 ASSERT_TRUE(sm->FinishedSnapshotWrites(true /* wipe */));
1568
1569 // Simulate shutting down the device.
1570 ASSERT_TRUE(UnmapAll());
1571
1572 // Simulate a reboot into recovery.
1573 auto test_device = new TestDeviceInfo(fake_super, "_b");
1574 test_device->set_recovery(true);
1575 auto new_sm = SnapshotManager::NewForFirstStageMount(test_device);
1576
1577 ASSERT_TRUE(new_sm->HandleImminentDataWipe());
1578 // Manually mount metadata so that we can call GetUpdateState() below.
1579 MountMetadata();
1580 EXPECT_EQ(new_sm->GetUpdateState(), UpdateState::None);
1581 ASSERT_FALSE(test_device->IsSlotUnbootable(1));
1582 ASSERT_FALSE(test_device->IsSlotUnbootable(0));
1583
1584 // Now reboot into new slot.
1585 test_device = new TestDeviceInfo(fake_super, "_b");
1586 auto init = SnapshotManager::NewForFirstStageMount(test_device);
1587 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1588 // Verify that we are on the downgraded build.
1589 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1590 ASSERT_TRUE(IsPartitionUnchanged(name)) << name;
1591 }
1592 }
1593
TEST_F(SnapshotUpdateTest,Hashtree)1594 TEST_F(SnapshotUpdateTest, Hashtree) {
1595 constexpr auto partition_size = 4_MiB;
1596 constexpr auto data_size = 3_MiB;
1597 constexpr auto hashtree_size = 512_KiB;
1598 constexpr auto fec_size = partition_size - data_size - hashtree_size;
1599
1600 const auto block_size = manifest_.block_size();
1601 SetSize(sys_, partition_size);
1602 AddOperation(sys_, data_size);
1603
1604 // Set hastree extents.
1605 sys_->mutable_hash_tree_data_extent()->set_start_block(0);
1606 sys_->mutable_hash_tree_data_extent()->set_num_blocks(data_size / block_size);
1607
1608 sys_->mutable_hash_tree_extent()->set_start_block(data_size / block_size);
1609 sys_->mutable_hash_tree_extent()->set_num_blocks(hashtree_size / block_size);
1610
1611 // Set FEC extents.
1612 sys_->mutable_fec_data_extent()->set_start_block(0);
1613 sys_->mutable_fec_data_extent()->set_num_blocks((data_size + hashtree_size) / block_size);
1614
1615 sys_->mutable_fec_extent()->set_start_block((data_size + hashtree_size) / block_size);
1616 sys_->mutable_fec_extent()->set_num_blocks(fec_size / block_size);
1617
1618 ASSERT_TRUE(sm->BeginUpdate());
1619 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1620
1621 // Map and write some data to target partition.
1622 ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
1623 ASSERT_TRUE(WriteSnapshotAndHash("sys_b", partition_size));
1624
1625 // Finish update.
1626 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1627
1628 // Simulate shutting down the device.
1629 ASSERT_TRUE(UnmapAll());
1630
1631 // After reboot, init does first stage mount.
1632 auto init = SnapshotManager::NewForFirstStageMount(new TestDeviceInfo(fake_super, "_b"));
1633 ASSERT_NE(init, nullptr);
1634 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1635 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1636
1637 // Check that the target partition have the same content. Hashtree and FEC extents
1638 // should be accounted for.
1639 ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
1640 }
1641
1642 // Test for overflow bit after update
TEST_F(SnapshotUpdateTest,Overflow)1643 TEST_F(SnapshotUpdateTest, Overflow) {
1644 const auto actual_write_size = GetSize(sys_);
1645 const auto declared_write_size = actual_write_size - 1_MiB;
1646
1647 AddOperation(sys_, declared_write_size);
1648
1649 // Execute the update.
1650 ASSERT_TRUE(sm->BeginUpdate());
1651 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1652
1653 // Map and write some data to target partitions.
1654 ASSERT_TRUE(MapUpdateSnapshots({"vnd_b", "prd_b"}));
1655 ASSERT_TRUE(WriteSnapshotAndHash("sys_b", actual_write_size));
1656
1657 std::vector<android::dm::DeviceMapper::TargetInfo> table;
1658 ASSERT_TRUE(DeviceMapper::Instance().GetTableStatus("sys_b", &table));
1659 ASSERT_EQ(1u, table.size());
1660 EXPECT_TRUE(table[0].IsOverflowSnapshot());
1661
1662 ASSERT_FALSE(sm->FinishedSnapshotWrites(false))
1663 << "FinishedSnapshotWrites should detect overflow of CoW device.";
1664 }
1665
TEST_F(SnapshotUpdateTest,LowSpace)1666 TEST_F(SnapshotUpdateTest, LowSpace) {
1667 static constexpr auto kMaxFree = 10_MiB;
1668 auto userdata = std::make_unique<LowSpaceUserdata>();
1669 ASSERT_TRUE(userdata->Init(kMaxFree));
1670
1671 // Grow all partitions to 5_MiB, total 15_MiB. This requires 15 MiB of CoW space. After
1672 // using the empty space in super (< 1 MiB), it uses at least 14 MiB of /userdata space.
1673 constexpr uint64_t partition_size = 5_MiB;
1674 SetSize(sys_, partition_size);
1675 SetSize(vnd_, partition_size);
1676 SetSize(prd_, partition_size);
1677
1678 AddOperationForPartitions();
1679
1680 // Execute the update.
1681 ASSERT_TRUE(sm->BeginUpdate());
1682 auto res = sm->CreateUpdateSnapshots(manifest_);
1683 ASSERT_FALSE(res);
1684 ASSERT_EQ(Return::ErrorCode::NO_SPACE, res.error_code());
1685 ASSERT_GE(res.required_size(), 14_MiB);
1686 ASSERT_LT(res.required_size(), 15_MiB);
1687 }
1688
1689 class FlashAfterUpdateTest : public SnapshotUpdateTest,
1690 public WithParamInterface<std::tuple<uint32_t, bool>> {
1691 public:
InitiateMerge(const std::string & slot_suffix)1692 AssertionResult InitiateMerge(const std::string& slot_suffix) {
1693 auto sm = SnapshotManager::New(new TestDeviceInfo(fake_super, slot_suffix));
1694 if (!sm->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_)) {
1695 return AssertionFailure() << "Cannot CreateLogicalAndSnapshotPartitions";
1696 }
1697 if (!sm->InitiateMerge()) {
1698 return AssertionFailure() << "Cannot initiate merge";
1699 }
1700 return AssertionSuccess();
1701 }
1702 };
1703
TEST_P(FlashAfterUpdateTest,FlashSlotAfterUpdate)1704 TEST_P(FlashAfterUpdateTest, FlashSlotAfterUpdate) {
1705 if (!is_virtual_ab_) GTEST_SKIP() << "Test for Virtual A/B devices only";
1706
1707 // OTA client blindly unmaps all partitions that are possibly mapped.
1708 for (const auto& name : {"sys_b", "vnd_b", "prd_b"}) {
1709 ASSERT_TRUE(sm->UnmapUpdateSnapshot(name));
1710 }
1711
1712 // Execute the update.
1713 ASSERT_TRUE(sm->BeginUpdate());
1714 ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
1715 ASSERT_TRUE(MapUpdateSnapshots());
1716 ASSERT_TRUE(sm->FinishedSnapshotWrites(false));
1717
1718 // Simulate shutting down the device.
1719 ASSERT_TRUE(UnmapAll());
1720
1721 bool after_merge = std::get<1>(GetParam());
1722 if (after_merge) {
1723 ASSERT_TRUE(InitiateMerge("_b"));
1724 // Simulate shutting down the device after merge has initiated.
1725 ASSERT_TRUE(UnmapAll());
1726 }
1727
1728 auto flashed_slot = std::get<0>(GetParam());
1729 auto flashed_slot_suffix = SlotSuffixForSlotNumber(flashed_slot);
1730
1731 // Simulate flashing |flashed_slot|. This clears the UPDATED flag.
1732 auto flashed_builder = MetadataBuilder::New(*opener_, "super", flashed_slot);
1733 ASSERT_NE(flashed_builder, nullptr);
1734 flashed_builder->RemoveGroupAndPartitions(group_->name() + flashed_slot_suffix);
1735 flashed_builder->RemoveGroupAndPartitions(kCowGroupName);
1736 ASSERT_TRUE(FillFakeMetadata(flashed_builder.get(), manifest_, flashed_slot_suffix));
1737
1738 // Deliberately remove a partition from this build so that
1739 // InitiateMerge do not switch state to "merging". This is possible in
1740 // practice because the list of dynamic partitions may change.
1741 ASSERT_NE(nullptr, flashed_builder->FindPartition("prd" + flashed_slot_suffix));
1742 flashed_builder->RemovePartition("prd" + flashed_slot_suffix);
1743
1744 // Note that fastbootd always updates the partition table of both slots.
1745 auto flashed_metadata = flashed_builder->Export();
1746 ASSERT_NE(nullptr, flashed_metadata);
1747 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 0));
1748 ASSERT_TRUE(UpdatePartitionTable(*opener_, "super", *flashed_metadata, 1));
1749
1750 std::string path;
1751 for (const auto& name : {"sys", "vnd"}) {
1752 ASSERT_TRUE(CreateLogicalPartition(
1753 CreateLogicalPartitionParams{
1754 .block_device = fake_super,
1755 .metadata_slot = flashed_slot,
1756 .partition_name = name + flashed_slot_suffix,
1757 .timeout_ms = 1s,
1758 .partition_opener = opener_.get(),
1759 },
1760 &path));
1761 ASSERT_TRUE(WriteRandomData(path));
1762 auto hash = GetHash(path);
1763 ASSERT_TRUE(hash.has_value());
1764 hashes_[name + flashed_slot_suffix] = *hash;
1765 }
1766
1767 // Simulate shutting down the device after flash.
1768 ASSERT_TRUE(UnmapAll());
1769
1770 // Simulate reboot. After reboot, init does first stage mount.
1771 auto init = SnapshotManager::NewForFirstStageMount(
1772 new TestDeviceInfo(fake_super, flashed_slot_suffix));
1773 ASSERT_NE(init, nullptr);
1774
1775 if (flashed_slot && after_merge) {
1776 ASSERT_TRUE(init->NeedSnapshotsInFirstStageMount());
1777 }
1778 ASSERT_TRUE(init->CreateLogicalAndSnapshotPartitions("super", snapshot_timeout_));
1779
1780 // Check that the target partitions have the same content.
1781 for (const auto& name : {"sys", "vnd"}) {
1782 ASSERT_TRUE(IsPartitionUnchanged(name + flashed_slot_suffix));
1783 }
1784
1785 // There should be no snapshot to merge.
1786 auto new_sm = SnapshotManager::New(new TestDeviceInfo(fake_super, flashed_slot_suffix));
1787 // update_enigne calls ProcessUpdateState first -- should see Cancelled.
1788 ASSERT_EQ(UpdateState::Cancelled, new_sm->ProcessUpdateState());
1789
1790 // Next OTA calls CancelUpdate no matter what.
1791 ASSERT_TRUE(new_sm->CancelUpdate());
1792 }
1793
1794 INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), Bool()),
__anon4de4482e0502(const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) 1795 [](const TestParamInfo<FlashAfterUpdateTest::ParamType>& info) {
1796 return "Flash"s + (std::get<0>(info.param) ? "New"s : "Old"s) +
1797 "Slot"s + (std::get<1>(info.param) ? "After"s : "Before"s) +
1798 "Merge"s;
1799 });
1800
1801 // Test behavior of ImageManager::Create on low space scenario. These tests assumes image manager
1802 // uses /data as backup device.
1803 class ImageManagerTest : public SnapshotTest, public WithParamInterface<uint64_t> {
1804 protected:
SetUp()1805 void SetUp() override {
1806 if (!is_virtual_ab_) GTEST_SKIP() << "Test for Virtual A/B devices only";
1807
1808 SnapshotTest::SetUp();
1809 userdata_ = std::make_unique<LowSpaceUserdata>();
1810 ASSERT_TRUE(userdata_->Init(GetParam()));
1811 }
TearDown()1812 void TearDown() override {
1813 if (!is_virtual_ab_) return;
1814 return; // BUG(149738928)
1815
1816 EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) ||
1817 image_manager_->DeleteBackingImage(kImageName));
1818 }
1819 static constexpr const char* kImageName = "my_image";
1820 std::unique_ptr<LowSpaceUserdata> userdata_;
1821 };
1822
TEST_P(ImageManagerTest,CreateImageEnoughAvailSpace)1823 TEST_P(ImageManagerTest, CreateImageEnoughAvailSpace) {
1824 if (userdata_->available_space() == 0) {
1825 GTEST_SKIP() << "/data is full (" << userdata_->available_space()
1826 << " bytes available), skipping";
1827 }
1828 ASSERT_TRUE(image_manager_->CreateBackingImage(kImageName, userdata_->available_space(),
1829 IImageManager::CREATE_IMAGE_DEFAULT))
1830 << "Should be able to create image with size = " << userdata_->available_space()
1831 << " bytes";
1832 ASSERT_TRUE(image_manager_->DeleteBackingImage(kImageName))
1833 << "Should be able to delete created image";
1834 }
1835
TEST_P(ImageManagerTest,CreateImageNoSpace)1836 TEST_P(ImageManagerTest, CreateImageNoSpace) {
1837 uint64_t to_allocate = userdata_->free_space() + userdata_->bsize();
1838 auto res = image_manager_->CreateBackingImage(kImageName, to_allocate,
1839 IImageManager::CREATE_IMAGE_DEFAULT);
1840 ASSERT_FALSE(res) << "Should not be able to create image with size = " << to_allocate
1841 << " bytes because only " << userdata_->free_space() << " bytes are free";
1842 ASSERT_EQ(FiemapStatus::ErrorCode::NO_SPACE, res.error_code()) << res.string();
1843 }
1844
ImageManagerTestParams()1845 std::vector<uint64_t> ImageManagerTestParams() {
1846 std::vector<uint64_t> ret;
1847 for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) {
1848 ret.push_back(size);
1849 }
1850 return ret;
1851 }
1852
1853 INSTANTIATE_TEST_SUITE_P(ImageManagerTest, ImageManagerTest, ValuesIn(ImageManagerTestParams()));
1854
1855 } // namespace snapshot
1856 } // namespace android
1857
1858 using namespace android::snapshot;
1859
Mkdir(const std::string & path)1860 bool Mkdir(const std::string& path) {
1861 if (mkdir(path.c_str(), 0700) && errno != EEXIST) {
1862 std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl;
1863 return false;
1864 }
1865 return true;
1866 }
1867
main(int argc,char ** argv)1868 int main(int argc, char** argv) {
1869 ::testing::InitGoogleTest(&argc, argv);
1870
1871 std::vector<std::string> paths = {
1872 // clang-format off
1873 "/data/gsi/ota/test",
1874 "/data/gsi/ota/test/super",
1875 "/metadata/gsi/ota/test",
1876 "/metadata/gsi/ota/test/super",
1877 "/metadata/ota/test",
1878 "/metadata/ota/test/snapshots",
1879 // clang-format on
1880 };
1881 for (const auto& path : paths) {
1882 if (!Mkdir(path)) {
1883 return 1;
1884 }
1885 }
1886
1887 // Create this once, otherwise, gsid will start/stop between each test.
1888 test_device = new TestDeviceInfo();
1889 sm = SnapshotManager::New(test_device);
1890 if (!sm) {
1891 std::cerr << "Could not create snapshot manager\n";
1892 return 1;
1893 }
1894
1895 // Clean up previous run.
1896 MetadataMountedTest().TearDown();
1897 SnapshotUpdateTest().Cleanup();
1898 SnapshotTest().Cleanup();
1899
1900 // Use a separate image manager for our fake super partition.
1901 auto super_images = IImageManager::Open("ota/test/super", 10s);
1902 if (!super_images) {
1903 std::cerr << "Could not create image manager\n";
1904 return 1;
1905 }
1906
1907 // Clean up any old copy.
1908 DeleteBackingImage(super_images.get(), "fake-super");
1909
1910 // Create and map the fake super partition.
1911 static constexpr int kImageFlags =
1912 IImageManager::CREATE_IMAGE_DEFAULT | IImageManager::CREATE_IMAGE_ZERO_FILL;
1913 if (!super_images->CreateBackingImage("fake-super", kSuperSize, kImageFlags)) {
1914 std::cerr << "Could not create fake super partition\n";
1915 return 1;
1916 }
1917 if (!super_images->MapImageDevice("fake-super", 10s, &fake_super)) {
1918 std::cerr << "Could not map fake super partition\n";
1919 return 1;
1920 }
1921 test_device->set_fake_super(fake_super);
1922
1923 auto result = RUN_ALL_TESTS();
1924
1925 DeleteBackingImage(super_images.get(), "fake-super");
1926
1927 return result;
1928 }
1929