1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <fcntl.h>
18 #include <linux/memfd.h>
19 #include <stdio.h>
20 #include <sys/syscall.h>
21 
22 #include <android-base/file.h>
23 #include <android-base/properties.h>
24 #include <android-base/unique_fd.h>
25 #include <fs_mgr.h>
26 #include <fstab/fstab.h>
27 #include <gmock/gmock.h>
28 #include <gtest/gtest.h>
29 #include <liblp/builder.h>
30 
31 #include "images.h"
32 #include "liblp_test.h"
33 #include "reader.h"
34 #include "test_partition_opener.h"
35 #include "utility.h"
36 #include "writer.h"
37 
38 using namespace std;
39 using namespace android::fs_mgr;
40 using namespace android::fs_mgr::testing;
41 using ::testing::_;
42 using ::testing::Return;
43 using unique_fd = android::base::unique_fd;
44 using android::base::GetProperty;
45 
46 // Our tests assume a 128KiB disk with two 512 byte metadata slots.
47 static const size_t kDiskSize = 131072;
48 static const size_t kMetadataSize = 512;
49 static const size_t kMetadataSlots = 2;
50 static const BlockDeviceInfo kSuperInfo{"super", kDiskSize, 0, 0, 4096};
51 
52 // Helper function for creating an in-memory file descriptor. This lets us
53 // simulate read/writing logical partition metadata as if we had a block device
54 // for a physical partition.
CreateFakeDisk(off_t size)55 static unique_fd CreateFakeDisk(off_t size) {
56     unique_fd fd(syscall(__NR_memfd_create, "fake_disk", MFD_ALLOW_SEALING));
57     if (fd < 0) {
58         perror("memfd_create");
59         return {};
60     }
61     if (ftruncate(fd, size) < 0) {
62         perror("ftruncate");
63         return {};
64     }
65     // Prevent anything from accidentally growing/shrinking the file, as it
66     // would not be allowed on an actual partition.
67     if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) < 0) {
68         perror("fcntl");
69         return {};
70     }
71     // Write garbage to the "disk" so we can tell what has been zeroed or not.
72     unique_ptr<uint8_t[]> buffer = make_unique<uint8_t[]>(size);
73     memset(buffer.get(), 0xcc, size);
74     if (!android::base::WriteFully(fd, buffer.get(), size)) {
75         return {};
76     }
77     return fd;
78 }
79 
80 // Create a disk of the default size.
CreateFakeDisk()81 static unique_fd CreateFakeDisk() {
82     return CreateFakeDisk(kDiskSize);
83 }
84 
85 // Create a MetadataBuilder around some default sizes.
CreateDefaultBuilder()86 static unique_ptr<MetadataBuilder> CreateDefaultBuilder() {
87     unique_ptr<MetadataBuilder> builder =
88             MetadataBuilder::New(kDiskSize, kMetadataSize, kMetadataSlots);
89     return builder;
90 }
91 
92 class DefaultPartitionOpener final : public TestPartitionOpener {
93   public:
DefaultPartitionOpener(int fd)94     explicit DefaultPartitionOpener(int fd)
95         : TestPartitionOpener({{"super", fd}}, {{"super", kSuperInfo}}) {}
96 };
97 
AddDefaultPartitions(MetadataBuilder * builder)98 static bool AddDefaultPartitions(MetadataBuilder* builder) {
99     Partition* system = builder->AddPartition("system", LP_PARTITION_ATTR_NONE);
100     if (!system) {
101         return false;
102     }
103     return builder->ResizePartition(system, 24 * 1024);
104 }
105 
106 // Create a temporary disk and flash it with the default partition setup.
CreateFlashedDisk()107 static unique_fd CreateFlashedDisk() {
108     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
109     if (!builder || !AddDefaultPartitions(builder.get())) {
110         return {};
111     }
112     unique_fd fd = CreateFakeDisk();
113     if (fd < 0) {
114         return {};
115     }
116     // Export and flash.
117     unique_ptr<LpMetadata> exported = builder->Export();
118     if (!exported) {
119         return {};
120     }
121 
122     DefaultPartitionOpener opener(fd);
123     if (!FlashPartitionTable(opener, "super", *exported.get())) {
124         return {};
125     }
126     return fd;
127 }
128 
129 // Test that our CreateFakeDisk() function works.
TEST_F(LiblpTest,CreateFakeDisk)130 TEST_F(LiblpTest, CreateFakeDisk) {
131     unique_fd fd = CreateFakeDisk();
132     ASSERT_GE(fd, 0);
133 
134     uint64_t size;
135     ASSERT_TRUE(GetDescriptorSize(fd, &size));
136     ASSERT_EQ(size, kDiskSize);
137 
138     DefaultPartitionOpener opener(fd);
139 
140     // Verify that we can't read unwritten metadata.
141     ASSERT_EQ(ReadMetadata(opener, "super", 1), nullptr);
142 }
143 
144 // Flashing metadata should not work if the metadata was created for a larger
145 // disk than the destination disk.
TEST_F(LiblpTest,ExportDiskTooSmall)146 TEST_F(LiblpTest, ExportDiskTooSmall) {
147     unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(kDiskSize + 4096, 512, 2);
148     ASSERT_NE(builder, nullptr);
149     unique_ptr<LpMetadata> exported = builder->Export();
150     ASSERT_NE(exported, nullptr);
151 
152     // A larger geometry should fail to flash, since there won't be enough
153     // space to store the logical partition range that was specified.
154     unique_fd fd = CreateFakeDisk();
155     ASSERT_GE(fd, 0);
156 
157     DefaultPartitionOpener opener(fd);
158 
159     EXPECT_FALSE(FlashPartitionTable(opener, "super", *exported.get()));
160 }
161 
162 // Test the basics of flashing a partition and reading it back.
TEST_F(LiblpTest,FlashAndReadback)163 TEST_F(LiblpTest, FlashAndReadback) {
164     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
165     ASSERT_NE(builder, nullptr);
166     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
167 
168     unique_fd fd = CreateFakeDisk();
169     ASSERT_GE(fd, 0);
170 
171     DefaultPartitionOpener opener(fd);
172 
173     // Export and flash.
174     unique_ptr<LpMetadata> exported = builder->Export();
175     ASSERT_NE(exported, nullptr);
176     ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
177 
178     // Read back. Note that some fields are only filled in during
179     // serialization, so exported and imported will not be identical. For
180     // example, table sizes and checksums are computed in WritePartitionTable.
181     // Therefore we check on a field-by-field basis.
182     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
183     ASSERT_NE(imported, nullptr);
184 
185     // Check geometry and header.
186     EXPECT_EQ(exported->geometry.metadata_max_size, imported->geometry.metadata_max_size);
187     EXPECT_EQ(exported->geometry.metadata_slot_count, imported->geometry.metadata_slot_count);
188     EXPECT_EQ(exported->header.major_version, imported->header.major_version);
189     EXPECT_EQ(exported->header.minor_version, imported->header.minor_version);
190     EXPECT_EQ(exported->header.header_size, imported->header.header_size);
191 
192     // Check partition tables.
193     ASSERT_EQ(exported->partitions.size(), imported->partitions.size());
194     EXPECT_EQ(GetPartitionName(exported->partitions[0]), GetPartitionName(imported->partitions[0]));
195     EXPECT_EQ(exported->partitions[0].attributes, imported->partitions[0].attributes);
196     EXPECT_EQ(exported->partitions[0].first_extent_index,
197               imported->partitions[0].first_extent_index);
198     EXPECT_EQ(exported->partitions[0].num_extents, imported->partitions[0].num_extents);
199 
200     // Check extent tables.
201     ASSERT_EQ(exported->extents.size(), imported->extents.size());
202     EXPECT_EQ(exported->extents[0].num_sectors, imported->extents[0].num_sectors);
203     EXPECT_EQ(exported->extents[0].target_type, imported->extents[0].target_type);
204     EXPECT_EQ(exported->extents[0].target_data, imported->extents[0].target_data);
205 
206     // Check block devices table.
207     ASSERT_EQ(exported->block_devices.size(), imported->block_devices.size());
208     EXPECT_EQ(exported->block_devices[0].first_logical_sector,
209               imported->block_devices[0].first_logical_sector);
210 }
211 
212 // Test that we can update metadata slots without disturbing others.
TEST_F(LiblpTest,UpdateAnyMetadataSlot)213 TEST_F(LiblpTest, UpdateAnyMetadataSlot) {
214     unique_fd fd = CreateFlashedDisk();
215     ASSERT_GE(fd, 0);
216 
217     DefaultPartitionOpener opener(fd);
218 
219     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
220     ASSERT_NE(imported, nullptr);
221     ASSERT_EQ(imported->partitions.size(), 1);
222     EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system");
223 
224     // Change the name before writing to the next slot.
225     strncpy(imported->partitions[0].name, "vendor", sizeof(imported->partitions[0].name));
226     ASSERT_TRUE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
227 
228     // Read back the original slot, make sure it hasn't changed.
229     imported = ReadMetadata(opener, "super", 0);
230     ASSERT_NE(imported, nullptr);
231     ASSERT_EQ(imported->partitions.size(), 1);
232     EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system");
233 
234     // Now read back the new slot, and verify that it has a different name.
235     imported = ReadMetadata(opener, "super", 1);
236     ASSERT_NE(imported, nullptr);
237     ASSERT_EQ(imported->partitions.size(), 1);
238     EXPECT_EQ(GetPartitionName(imported->partitions[0]), "vendor");
239 
240     auto super_device = GetMetadataSuperBlockDevice(*imported.get());
241     ASSERT_NE(super_device, nullptr);
242 
243     uint64_t last_sector = super_device->size / LP_SECTOR_SIZE;
244 
245     // Verify that we didn't overwrite anything in the logical paritition area.
246     // We expect the disk to be filled with 0xcc on creation so we can read
247     // this back and compare it.
248     char expected[LP_SECTOR_SIZE];
249     memset(expected, 0xcc, sizeof(expected));
250     for (uint64_t i = super_device->first_logical_sector; i < last_sector; i++) {
251         char buffer[LP_SECTOR_SIZE];
252         ASSERT_GE(lseek(fd, i * LP_SECTOR_SIZE, SEEK_SET), 0);
253         ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
254         ASSERT_EQ(memcmp(expected, buffer, LP_SECTOR_SIZE), 0);
255     }
256 }
257 
TEST_F(LiblpTest,InvalidMetadataSlot)258 TEST_F(LiblpTest, InvalidMetadataSlot) {
259     unique_fd fd = CreateFlashedDisk();
260     ASSERT_GE(fd, 0);
261 
262     DefaultPartitionOpener opener(fd);
263 
264     // Make sure all slots are filled.
265     unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
266     ASSERT_NE(metadata, nullptr);
267     for (uint32_t i = 1; i < kMetadataSlots; i++) {
268         ASSERT_TRUE(UpdatePartitionTable(opener, "super", *metadata.get(), i));
269     }
270 
271     // Verify that we can't read unavailable slots.
272     EXPECT_EQ(ReadMetadata(opener, "super", kMetadataSlots), nullptr);
273 }
274 
275 // Test that updating a metadata slot does not allow it to be computed based
276 // on mismatching geometry.
TEST_F(LiblpTest,NoChangingGeometry)277 TEST_F(LiblpTest, NoChangingGeometry) {
278     unique_fd fd = CreateFlashedDisk();
279     ASSERT_GE(fd, 0);
280 
281     DefaultPartitionOpener opener(fd);
282 
283     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
284     ASSERT_NE(imported, nullptr);
285     ASSERT_TRUE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
286 
287     imported->geometry.metadata_max_size += LP_SECTOR_SIZE;
288     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
289 
290     imported = ReadMetadata(opener, "super", 0);
291     ASSERT_NE(imported, nullptr);
292     imported->geometry.metadata_slot_count++;
293     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
294 
295     imported = ReadMetadata(opener, "super", 0);
296     ASSERT_NE(imported, nullptr);
297     ASSERT_EQ(imported->block_devices.size(), 1);
298     imported->block_devices[0].first_logical_sector++;
299     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
300 
301     imported = ReadMetadata(opener, "super", 0);
302     ASSERT_NE(imported, nullptr);
303 }
304 
305 // Test that changing one bit of metadata is enough to break the checksum.
TEST_F(LiblpTest,BitFlipGeometry)306 TEST_F(LiblpTest, BitFlipGeometry) {
307     unique_fd fd = CreateFlashedDisk();
308     ASSERT_GE(fd, 0);
309 
310     DefaultPartitionOpener opener(fd);
311 
312     LpMetadataGeometry geometry;
313     ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
314     ASSERT_TRUE(android::base::ReadFully(fd, &geometry, sizeof(geometry)));
315 
316     LpMetadataGeometry bad_geometry = geometry;
317     bad_geometry.metadata_slot_count++;
318     ASSERT_TRUE(android::base::WriteFully(fd, &bad_geometry, sizeof(bad_geometry)));
319 
320     unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
321     ASSERT_NE(metadata, nullptr);
322     EXPECT_EQ(metadata->geometry.metadata_slot_count, 2);
323 }
324 
TEST_F(LiblpTest,ReadBackupGeometry)325 TEST_F(LiblpTest, ReadBackupGeometry) {
326     unique_fd fd = CreateFlashedDisk();
327     ASSERT_GE(fd, 0);
328 
329     DefaultPartitionOpener opener(fd);
330 
331     char corruption[LP_METADATA_GEOMETRY_SIZE];
332     memset(corruption, 0xff, sizeof(corruption));
333 
334     // Corrupt the primary geometry.
335     ASSERT_GE(lseek(fd, GetPrimaryGeometryOffset(), SEEK_SET), 0);
336     ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
337     EXPECT_NE(ReadMetadata(opener, "super", 0), nullptr);
338 
339     // Corrupt the backup geometry.
340     ASSERT_GE(lseek(fd, GetBackupGeometryOffset(), SEEK_SET), 0);
341     ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
342     EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
343 }
344 
TEST_F(LiblpTest,ReadBackupMetadata)345 TEST_F(LiblpTest, ReadBackupMetadata) {
346     unique_fd fd = CreateFlashedDisk();
347     ASSERT_GE(fd, 0);
348 
349     DefaultPartitionOpener opener(fd);
350 
351     unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
352 
353     char corruption[kMetadataSize];
354     memset(corruption, 0xff, sizeof(corruption));
355 
356     off_t offset = GetPrimaryMetadataOffset(metadata->geometry, 0);
357 
358     ASSERT_GE(lseek(fd, offset, SEEK_SET), 0);
359     ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
360     EXPECT_NE(ReadMetadata(opener, "super", 0), nullptr);
361 
362     offset = GetBackupMetadataOffset(metadata->geometry, 0);
363 
364     // Corrupt the backup metadata.
365     ASSERT_GE(lseek(fd, offset, SEEK_SET), 0);
366     ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
367     EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
368 }
369 
370 // Test that we don't attempt to write metadata if it would overflow its
371 // reserved space.
TEST_F(LiblpTest,TooManyPartitions)372 TEST_F(LiblpTest, TooManyPartitions) {
373     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
374     ASSERT_NE(builder, nullptr);
375 
376     // Compute the maximum number of partitions we can fit in 512 bytes of
377     // metadata. By default there is the header, one partition group, and a
378     // block device entry.
379     static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeaderV1_0) -
380                                                  sizeof(LpMetadataPartitionGroup) -
381                                                  sizeof(LpMetadataBlockDevice);
382     size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition);
383 
384     // Add this number of partitions.
385     Partition* partition = nullptr;
386     for (size_t i = 0; i < max_partitions; i++) {
387         partition = builder->AddPartition(to_string(i), LP_PARTITION_ATTR_NONE);
388         ASSERT_NE(partition, nullptr);
389     }
390 
391     unique_ptr<LpMetadata> exported = builder->Export();
392     ASSERT_NE(exported, nullptr);
393 
394     unique_fd fd = CreateFakeDisk();
395     ASSERT_GE(fd, 0);
396 
397     DefaultPartitionOpener opener(fd);
398 
399     // Check that we are able to write our table.
400     ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
401 
402     // Check that adding one more partition overflows the metadata allotment.
403     partition = builder->AddPartition("final", LP_PARTITION_ATTR_NONE);
404     EXPECT_NE(partition, nullptr);
405 
406     exported = builder->Export();
407     ASSERT_NE(exported, nullptr);
408 
409     // The new table should be too large to be written.
410     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *exported.get(), 1));
411 
412     auto super_device = GetMetadataSuperBlockDevice(*exported.get());
413     ASSERT_NE(super_device, nullptr);
414 
415     // Check that the first and last logical sectors weren't touched when we
416     // wrote this almost-full metadata.
417     char expected[LP_SECTOR_SIZE];
418     memset(expected, 0xcc, sizeof(expected));
419     char buffer[LP_SECTOR_SIZE];
420     ASSERT_GE(lseek(fd, super_device->first_logical_sector * LP_SECTOR_SIZE, SEEK_SET), 0);
421     ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
422     EXPECT_EQ(memcmp(expected, buffer, LP_SECTOR_SIZE), 0);
423 }
424 
425 // Test that we can read and write image files.
TEST_F(LiblpTest,ImageFiles)426 TEST_F(LiblpTest, ImageFiles) {
427     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
428     ASSERT_NE(builder, nullptr);
429     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
430     unique_ptr<LpMetadata> exported = builder->Export();
431     ASSERT_NE(exported, nullptr);
432 
433     unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
434     ASSERT_GE(fd, 0);
435     ASSERT_TRUE(WriteToImageFile(fd, *exported.get()));
436 
437     unique_ptr<LpMetadata> imported = ReadFromImageFile(fd);
438     ASSERT_NE(imported, nullptr);
439 }
440 
441 // Test that we can read images from buffers.
TEST_F(LiblpTest,ImageFilesInMemory)442 TEST_F(LiblpTest, ImageFilesInMemory) {
443     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
444     ASSERT_NE(builder, nullptr);
445     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
446     unique_ptr<LpMetadata> exported = builder->Export();
447 
448     unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
449     ASSERT_GE(fd, 0);
450     ASSERT_TRUE(WriteToImageFile(fd, *exported.get()));
451 
452     int64_t offset = SeekFile64(fd, 0, SEEK_CUR);
453     ASSERT_GE(offset, 0);
454     ASSERT_EQ(SeekFile64(fd, 0, SEEK_SET), 0);
455 
456     size_t bytes = static_cast<size_t>(offset);
457     std::unique_ptr<char[]> buffer = std::make_unique<char[]>(bytes);
458     ASSERT_TRUE(android::base::ReadFully(fd, buffer.get(), bytes));
459     ASSERT_NE(ReadFromImageBlob(buffer.get(), bytes), nullptr);
460 }
461 
462 class BadWriter {
463   public:
464     // When requested, write garbage instead of the requested bytes, then
465     // return false.
operator ()(int fd,const std::string & blob)466     bool operator()(int fd, const std::string& blob) {
467         write_count_++;
468         if (write_count_ == fail_on_write_) {
469             std::unique_ptr<char[]> new_data = std::make_unique<char[]>(blob.size());
470             memset(new_data.get(), 0xe5, blob.size());
471             EXPECT_TRUE(android::base::WriteFully(fd, new_data.get(), blob.size()));
472             return false;
473         } else {
474             if (!android::base::WriteFully(fd, blob.data(), blob.size())) {
475                 return false;
476             }
477             return fail_after_write_ != write_count_;
478         }
479     }
Reset()480     void Reset() {
481         fail_on_write_ = 0;
482         fail_after_write_ = 0;
483         write_count_ = 0;
484     }
FailOnWrite(int number)485     void FailOnWrite(int number) {
486         Reset();
487         fail_on_write_ = number;
488     }
FailAfterWrite(int number)489     void FailAfterWrite(int number) {
490         Reset();
491         fail_after_write_ = number;
492     }
493 
494   private:
495     int fail_on_write_ = 0;
496     int fail_after_write_ = 0;
497     int write_count_ = 0;
498 };
499 
500 // Test that an interrupted flash operation on the "primary" copy of metadata
501 // is not fatal.
TEST_F(LiblpTest,UpdatePrimaryMetadataFailure)502 TEST_F(LiblpTest, UpdatePrimaryMetadataFailure) {
503     unique_fd fd = CreateFlashedDisk();
504     ASSERT_GE(fd, 0);
505 
506     DefaultPartitionOpener opener(fd);
507 
508     BadWriter writer;
509 
510     // Read and write it back.
511     writer.FailOnWrite(1);
512     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
513     ASSERT_NE(imported, nullptr);
514     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
515 
516     // We should still be able to read the backup copy.
517     imported = ReadMetadata(opener, "super", 0);
518     ASSERT_NE(imported, nullptr);
519 
520     // Flash again, this time fail the backup copy. We should still be able
521     // to read the primary.
522     writer.FailOnWrite(3);
523     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
524     imported = ReadMetadata(opener, "super", 0);
525     ASSERT_NE(imported, nullptr);
526 }
527 
528 // Test that an interrupted flash operation on the "backup" copy of metadata
529 // is not fatal.
TEST_F(LiblpTest,UpdateBackupMetadataFailure)530 TEST_F(LiblpTest, UpdateBackupMetadataFailure) {
531     unique_fd fd = CreateFlashedDisk();
532     ASSERT_GE(fd, 0);
533 
534     DefaultPartitionOpener opener(fd);
535 
536     BadWriter writer;
537 
538     // Read and write it back.
539     writer.FailOnWrite(2);
540     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
541     ASSERT_NE(imported, nullptr);
542     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
543 
544     // We should still be able to read the primary copy.
545     imported = ReadMetadata(opener, "super", 0);
546     ASSERT_NE(imported, nullptr);
547 
548     // Flash again, this time fail the primary copy. We should still be able
549     // to read the primary.
550     writer.FailOnWrite(2);
551     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
552     imported = ReadMetadata(opener, "super", 0);
553     ASSERT_NE(imported, nullptr);
554 }
555 
556 // Test that an interrupted write *in between* writing metadata will read
557 // the correct metadata copy. The primary is always considered newer than
558 // the backup.
TEST_F(LiblpTest,UpdateMetadataCleanFailure)559 TEST_F(LiblpTest, UpdateMetadataCleanFailure) {
560     unique_fd fd = CreateFlashedDisk();
561     ASSERT_GE(fd, 0);
562 
563     DefaultPartitionOpener opener(fd);
564 
565     BadWriter writer;
566 
567     // Change the name of the existing partition.
568     unique_ptr<LpMetadata> new_table = ReadMetadata(opener, "super", 0);
569     ASSERT_NE(new_table, nullptr);
570     ASSERT_GE(new_table->partitions.size(), 1);
571     new_table->partitions[0].name[0]++;
572 
573     // Flash it, but fail to write the backup copy.
574     writer.FailAfterWrite(2);
575     ASSERT_FALSE(UpdatePartitionTable(opener, "super", *new_table.get(), 0, writer));
576 
577     // When we read back, we should get the updated primary copy.
578     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
579     ASSERT_NE(imported, nullptr);
580     ASSERT_GE(new_table->partitions.size(), 1);
581     ASSERT_EQ(GetPartitionName(new_table->partitions[0]), GetPartitionName(imported->partitions[0]));
582 
583     // Flash again. After, the backup and primary copy should be coherent.
584     // Note that the sync step should have used the primary to sync, not
585     // the backup.
586     writer.Reset();
587     ASSERT_TRUE(UpdatePartitionTable(opener, "super", *new_table.get(), 0, writer));
588 
589     imported = ReadMetadata(opener, "super", 0);
590     ASSERT_NE(imported, nullptr);
591     ASSERT_GE(new_table->partitions.size(), 1);
592     ASSERT_EQ(GetPartitionName(new_table->partitions[0]), GetPartitionName(imported->partitions[0]));
593 }
594 
595 // Test that writing a sparse image can be read back.
TEST_F(LiblpTest,FlashSparseImage)596 TEST_F(LiblpTest, FlashSparseImage) {
597     unique_fd fd = CreateFakeDisk();
598     ASSERT_GE(fd, 0);
599 
600     BlockDeviceInfo device_info("super", kDiskSize, 0, 0, 512);
601     unique_ptr<MetadataBuilder> builder =
602             MetadataBuilder::New(device_info, kMetadataSize, kMetadataSlots);
603     ASSERT_NE(builder, nullptr);
604     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
605 
606     unique_ptr<LpMetadata> exported = builder->Export();
607     ASSERT_NE(exported, nullptr);
608 
609     // Build the sparse file.
610     ImageBuilder sparse(*exported.get(), 512, {}, true /* sparsify */);
611     ASSERT_TRUE(sparse.IsValid());
612     ASSERT_TRUE(sparse.Build());
613 
614     const auto& images = sparse.device_images();
615     ASSERT_EQ(images.size(), static_cast<size_t>(1));
616 
617     // Write it to the fake disk.
618     ASSERT_NE(lseek(fd.get(), 0, SEEK_SET), -1);
619     int ret = sparse_file_write(images[0].get(), fd.get(), false, false, false);
620     ASSERT_EQ(ret, 0);
621 
622     // Verify that we can read both sets of metadata.
623     LpMetadataGeometry geometry;
624     ASSERT_TRUE(ReadPrimaryGeometry(fd.get(), &geometry));
625     ASSERT_TRUE(ReadBackupGeometry(fd.get(), &geometry));
626     ASSERT_NE(ReadPrimaryMetadata(fd.get(), geometry, 0), nullptr);
627     ASSERT_NE(ReadBackupMetadata(fd.get(), geometry, 0), nullptr);
628 }
629 
TEST_F(LiblpTest,AutoSlotSuffixing)630 TEST_F(LiblpTest, AutoSlotSuffixing) {
631     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
632     ASSERT_NE(builder, nullptr);
633     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
634     ASSERT_TRUE(builder->AddGroup("example", 0));
635     builder->SetAutoSlotSuffixing();
636 
637     auto fd = CreateFakeDisk();
638     ASSERT_GE(fd, 0);
639 
640     // Note: we bind the same fd to both names, since we want to make sure the
641     // exact same bits are getting read back in each test.
642     TestPartitionOpener opener({{"super_a", fd}, {"super_b", fd}},
643                                {{"super_a", kSuperInfo}, {"super_b", kSuperInfo}});
644     auto exported = builder->Export();
645     ASSERT_NE(exported, nullptr);
646     ASSERT_TRUE(FlashPartitionTable(opener, "super_a", *exported.get()));
647 
648     auto metadata = ReadMetadata(opener, "super_b", 1);
649     ASSERT_NE(metadata, nullptr);
650     ASSERT_EQ(metadata->partitions.size(), static_cast<size_t>(1));
651     EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_b");
652     ASSERT_EQ(metadata->block_devices.size(), static_cast<size_t>(1));
653     EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_b");
654     ASSERT_EQ(metadata->groups.size(), static_cast<size_t>(2));
655     EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default");
656     EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_b");
657     EXPECT_EQ(metadata->groups[0].flags, 0);
658     EXPECT_EQ(metadata->groups[1].flags, 0);
659 
660     metadata = ReadMetadata(opener, "super_a", 0);
661     ASSERT_NE(metadata, nullptr);
662     ASSERT_EQ(metadata->partitions.size(), static_cast<size_t>(1));
663     EXPECT_EQ(GetPartitionName(metadata->partitions[0]), "system_a");
664     ASSERT_EQ(metadata->block_devices.size(), static_cast<size_t>(1));
665     EXPECT_EQ(GetBlockDevicePartitionName(metadata->block_devices[0]), "super_a");
666     ASSERT_EQ(metadata->groups.size(), static_cast<size_t>(2));
667     EXPECT_EQ(GetPartitionGroupName(metadata->groups[0]), "default");
668     EXPECT_EQ(GetPartitionGroupName(metadata->groups[1]), "example_a");
669     EXPECT_EQ(metadata->groups[0].flags, 0);
670     EXPECT_EQ(metadata->groups[1].flags, 0);
671 }
672 
TEST_F(LiblpTest,UpdateRetrofit)673 TEST_F(LiblpTest, UpdateRetrofit) {
674     ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
675             .WillByDefault(Return(true));
676 
677     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
678     ASSERT_NE(builder, nullptr);
679     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
680     ASSERT_TRUE(builder->AddGroup("example", 0));
681     builder->SetAutoSlotSuffixing();
682 
683     auto fd = CreateFakeDisk();
684     ASSERT_GE(fd, 0);
685 
686     // Note: we bind the same fd to both names, since we want to make sure the
687     // exact same bits are getting read back in each test.
688     TestPartitionOpener opener({{"super_a", fd}, {"super_b", fd}},
689                                {{"super_a", kSuperInfo}, {"super_b", kSuperInfo}});
690     auto exported = builder->Export();
691     ASSERT_NE(exported, nullptr);
692     ASSERT_TRUE(FlashPartitionTable(opener, "super_a", *exported.get()));
693 
694     builder = MetadataBuilder::NewForUpdate(opener, "super_a", 0, 1);
695     ASSERT_NE(builder, nullptr);
696     auto updated = builder->Export();
697     ASSERT_NE(updated, nullptr);
698     ASSERT_EQ(updated->block_devices.size(), static_cast<size_t>(1));
699     EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super_b");
700     ASSERT_TRUE(updated->groups.empty());
701     ASSERT_TRUE(updated->partitions.empty());
702     ASSERT_TRUE(updated->extents.empty());
703 }
704 
TEST_F(LiblpTest,UpdateNonRetrofit)705 TEST_F(LiblpTest, UpdateNonRetrofit) {
706     ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
707             .WillByDefault(Return(false));
708 
709     unique_fd fd = CreateFlashedDisk();
710     ASSERT_GE(fd, 0);
711 
712     DefaultPartitionOpener opener(fd);
713     auto builder = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
714     ASSERT_NE(builder, nullptr);
715     auto updated = builder->Export();
716     ASSERT_NE(updated, nullptr);
717     ASSERT_EQ(updated->block_devices.size(), static_cast<size_t>(1));
718     EXPECT_EQ(GetBlockDevicePartitionName(updated->block_devices[0]), "super");
719 }
720 
TEST_F(LiblpTest,UpdateVirtualAB)721 TEST_F(LiblpTest, UpdateVirtualAB) {
722     ON_CALL(*GetMockedPropertyFetcher(), GetBoolProperty("ro.virtual_ab.enabled", _))
723             .WillByDefault(Return(true));
724 
725     unique_fd fd = CreateFlashedDisk();
726     ASSERT_GE(fd, 0);
727 
728     DefaultPartitionOpener opener(fd);
729     auto builder = MetadataBuilder::NewForUpdate(opener, "super", 0, 1);
730     ASSERT_NE(builder, nullptr);
731     auto updated = builder->Export();
732     ASSERT_NE(updated, nullptr);
733     ASSERT_TRUE(UpdatePartitionTable(opener, "super", *updated.get(), 1));
734 
735     // Validate old slot.
736     auto metadata = ReadMetadata(opener, "super", 0);
737     ASSERT_NE(metadata, nullptr);
738     ASSERT_EQ(metadata->header.minor_version, 0);
739     ASSERT_GE(metadata->partitions.size(), 1);
740     ASSERT_EQ(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0);
741 
742     // Validate new slot.
743     metadata = ReadMetadata(opener, "super", 1);
744     ASSERT_NE(metadata, nullptr);
745     ASSERT_EQ(metadata->header.minor_version, 1);
746     ASSERT_GE(metadata->partitions.size(), 1);
747     ASSERT_NE(metadata->partitions[0].attributes & LP_PARTITION_ATTR_UPDATED, 0);
748 }
749 
TEST_F(LiblpTest,ReadExpandedHeader)750 TEST_F(LiblpTest, ReadExpandedHeader) {
751     unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
752     ASSERT_NE(builder, nullptr);
753     ASSERT_TRUE(AddDefaultPartitions(builder.get()));
754 
755     builder->RequireExpandedMetadataHeader();
756 
757     unique_fd fd = CreateFakeDisk();
758     ASSERT_GE(fd, 0);
759 
760     DefaultPartitionOpener opener(fd);
761 
762     // Export and flash.
763     unique_ptr<LpMetadata> exported = builder->Export();
764     ASSERT_NE(exported, nullptr);
765     exported->header.flags = 0x5e5e5e5e;
766     ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
767 
768     unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
769     ASSERT_NE(imported, nullptr);
770     EXPECT_EQ(imported->header.header_size, sizeof(LpMetadataHeaderV1_2));
771     EXPECT_EQ(imported->header.header_size, exported->header.header_size);
772     EXPECT_EQ(imported->header.flags, exported->header.flags);
773 }
774