diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-11-02 22:47:09 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-11-02 22:47:09 +0000 |
commit | d1f43a7a05999f24d3c9fb018bc602fc68449e05 (patch) | |
tree | 671fe7b1342730aa93614125c670bcbdfa4041c4 | |
parent | 86832d684cb867e45d9ffdd954eee4989d8b30d5 (diff) | |
parent | 4d51991a5852a4374cb34ea27ae8e624133f87b4 (diff) | |
download | core-android14-mainline-wifi-release.tar.gz |
Snap for 11041982 from 4d51991a5852a4374cb34ea27ae8e624133f87b4 to mainline-wifi-releaseaml_wif_341510000aml_wif_341410080aml_wif_341310010android14-mainline-wifi-release
Change-Id: I075c9f305e5d78b0ac592d3d8382bf8d62e89099
-rw-r--r-- | fs_mgr/fs_mgr.cpp | 25 | ||||
-rw-r--r-- | fs_mgr/libfiemap/Android.bp | 3 | ||||
-rw-r--r-- | fs_mgr/libfiemap/fiemap_writer_test.cpp | 118 | ||||
-rw-r--r-- | fs_mgr/libsnapshot/snapshot_test.cpp | 70 | ||||
-rw-r--r-- | fs_mgr/libstorage_literals/storage_literals/storage_literals.h | 6 | ||||
-rw-r--r-- | fs_mgr/tests/vts_fs_test.cpp | 21 | ||||
-rw-r--r-- | libcutils/ashmem-dev.cpp | 29 |
7 files changed, 156 insertions, 116 deletions
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 742cdfab0..8b9bce1db 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -700,6 +700,29 @@ static void SetReadAheadSize(const std::string& entry_block_device, off64_t size } // +// Mechanism to allow fsck to be triggered by setting ro.preventative_fsck +// Introduced to address b/305658663 +// If the property value is not equal to the flag file contents, trigger +// fsck and store the property value in the flag file +// If we want to trigger again, simply change the property value +// +static bool check_if_preventative_fsck_needed(const FstabEntry& entry) { + const char* flag_file = "/metadata/vold/preventative_fsck"; + if (entry.mount_point != "/data") return false; + + // Don't error check - both default to empty string, which is OK + std::string prop = android::base::GetProperty("ro.preventative_fsck", ""); + std::string flag; + android::base::ReadFileToString(flag_file, &flag); + if (prop == flag) return false; + // fsck is run immediately, so assume it runs or there is some deeper problem + if (!android::base::WriteStringToFile(prop, flag_file)) + PERROR << "Failed to write file " << flag_file; + LINFO << "Run preventative fsck on /data"; + return true; +} + +// // Prepare the filesystem on the given block device to be mounted. // // If the "check" option was given in the fstab record, or it seems that the @@ -749,7 +772,7 @@ static int prepare_fs_for_mount(const std::string& blk_device, const FstabEntry& } } - if (entry.fs_mgr_flags.check || + if (check_if_preventative_fsck_needed(entry) || entry.fs_mgr_flags.check || (fs_stat & (FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED))) { check_fs(blk_device, entry.fs_type, mount_point, &fs_stat); } diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp index 5deba659d..ddda648d8 100644 --- a/fs_mgr/libfiemap/Android.bp +++ b/fs_mgr/libfiemap/Android.bp @@ -93,6 +93,9 @@ cc_test { test_options: { min_shipping_api_level: 29, }, + header_libs: [ + "libstorage_literals_headers", + ], require_root: true, } diff --git a/fs_mgr/libfiemap/fiemap_writer_test.cpp b/fs_mgr/libfiemap/fiemap_writer_test.cpp index c65481b78..bd97a78ae 100644 --- a/fs_mgr/libfiemap/fiemap_writer_test.cpp +++ b/fs_mgr/libfiemap/fiemap_writer_test.cpp @@ -22,21 +22,25 @@ #include <string.h> #include <sys/mount.h> #include <sys/stat.h> +#include <sys/statvfs.h> #include <sys/types.h> #include <sys/vfs.h> #include <unistd.h> #include <string> +#include <utility> #include <android-base/file.h> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> +#include <fstab/fstab.h> #include <gtest/gtest.h> #include <libdm/loop_control.h> #include <libfiemap/fiemap_writer.h> #include <libfiemap/split_fiemap_writer.h> #include <libgsi/libgsi.h> +#include <storage_literals/storage_literals.h> #include "utility.h" @@ -46,6 +50,7 @@ namespace fiemap { using namespace std; using namespace std::string_literals; using namespace android::fiemap; +using namespace android::storage_literals; using unique_fd = android::base::unique_fd; using LoopDevice = android::dm::LoopDevice; @@ -427,90 +432,123 @@ TEST_F(SplitFiemapTest, WritePastEnd) { ASSERT_FALSE(ptr->Write(buffer.get(), kSize)); } -class VerifyBlockWritesExt4 : public ::testing::Test { +// Get max file size and free space. +std::pair<uint64_t, uint64_t> GetBigFileLimit(const std::string& mount_point) { + struct statvfs fs; + if (statvfs(mount_point.c_str(), &fs) < 0) { + PLOG(ERROR) << "statfs failed"; + return {0, 0}; + } + + auto fs_limit = static_cast<uint64_t>(fs.f_blocks) * (fs.f_bsize - 1); + auto fs_free = static_cast<uint64_t>(fs.f_bfree) * fs.f_bsize; + + LOG(INFO) << "Big file limit: " << fs_limit << ", free space: " << fs_free; + + return {fs_limit, fs_free}; +} + +class FsTest : public ::testing::Test { + protected: // 2GB Filesystem and 4k block size by default static constexpr uint64_t block_size = 4096; - static constexpr uint64_t fs_size = 2147483648; + static constexpr uint64_t fs_size = 64 * 1024 * 1024; + + void SetUp() { + android::fs_mgr::Fstab fstab; + ASSERT_TRUE(android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab)); + + ASSERT_EQ(access(tmpdir_.path, F_OK), 0); + fs_path_ = tmpdir_.path + "/fs_image"s; + mntpoint_ = tmpdir_.path + "/mnt_point"s; + + auto entry = android::fs_mgr::GetEntryForMountPoint(&fstab, "/data"); + ASSERT_NE(entry, nullptr); + if (entry->fs_type == "ext4") { + SetUpExt4(); + } else if (entry->fs_type == "f2fs") { + SetUpF2fs(); + } else { + FAIL() << "Unrecognized fs_type: " << entry->fs_type; + } + } - protected: - void SetUp() override { - fs_path = std::string(getenv("TMPDIR")) + "/ext4_2G.img"; + void SetUpExt4() { uint64_t count = fs_size / block_size; std::string dd_cmd = ::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64 " count=%" PRIu64 " > /dev/null 2>&1", - fs_path.c_str(), block_size, count); + fs_path_.c_str(), block_size, count); std::string mkfs_cmd = - ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path.c_str()); + ::android::base::StringPrintf("/system/bin/mkfs.ext4 -q %s", fs_path_.c_str()); // create mount point - mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt"; - ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0); + ASSERT_EQ(mkdir(mntpoint_.c_str(), S_IRWXU), 0); // create file for the file system int ret = system(dd_cmd.c_str()); ASSERT_EQ(ret, 0); // Get and attach a loop device to the filesystem we created - LoopDevice loop_dev(fs_path, 10s); + LoopDevice loop_dev(fs_path_, 10s); ASSERT_TRUE(loop_dev.valid()); // create file system ret = system(mkfs_cmd.c_str()); ASSERT_EQ(ret, 0); // mount the file system - ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "ext4", 0, nullptr), 0); - } - - void TearDown() override { - umount(mntpoint.c_str()); - rmdir(mntpoint.c_str()); - unlink(fs_path.c_str()); + ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint_.c_str(), "ext4", 0, nullptr), 0); } - std::string mntpoint; - std::string fs_path; -}; - -class VerifyBlockWritesF2fs : public ::testing::Test { - // 2GB Filesystem and 4k block size by default - static constexpr uint64_t block_size = 4096; - static constexpr uint64_t fs_size = 2147483648; - - protected: - void SetUp() override { - fs_path = std::string(getenv("TMPDIR")) + "/f2fs_2G.img"; + void SetUpF2fs() { uint64_t count = fs_size / block_size; std::string dd_cmd = ::android::base::StringPrintf("/system/bin/dd if=/dev/zero of=%s bs=%" PRIu64 " count=%" PRIu64 " > /dev/null 2>&1", - fs_path.c_str(), block_size, count); + fs_path_.c_str(), block_size, count); std::string mkfs_cmd = - ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path.c_str()); + ::android::base::StringPrintf("/system/bin/make_f2fs -q %s", fs_path_.c_str()); // create mount point - mntpoint = std::string(getenv("TMPDIR")) + "/fiemap_mnt"; - ASSERT_EQ(mkdir(mntpoint.c_str(), S_IRWXU), 0); + ASSERT_EQ(mkdir(mntpoint_.c_str(), S_IRWXU), 0); // create file for the file system int ret = system(dd_cmd.c_str()); ASSERT_EQ(ret, 0); // Get and attach a loop device to the filesystem we created - LoopDevice loop_dev(fs_path, 10s); + LoopDevice loop_dev(fs_path_, 10s); ASSERT_TRUE(loop_dev.valid()); // create file system ret = system(mkfs_cmd.c_str()); ASSERT_EQ(ret, 0); // mount the file system - ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint.c_str(), "f2fs", 0, nullptr), 0); + ASSERT_EQ(mount(loop_dev.device().c_str(), mntpoint_.c_str(), "f2fs", 0, nullptr), 0); } void TearDown() override { - umount(mntpoint.c_str()); - rmdir(mntpoint.c_str()); - unlink(fs_path.c_str()); + umount(mntpoint_.c_str()); + rmdir(mntpoint_.c_str()); + unlink(fs_path_.c_str()); } - std::string mntpoint; - std::string fs_path; + TemporaryDir tmpdir_; + std::string mntpoint_; + std::string fs_path_; }; +TEST_F(FsTest, LowSpaceError) { + auto limits = GetBigFileLimit(mntpoint_); + ASSERT_GE(limits.first, 0); + + FiemapUniquePtr ptr; + + auto test_file = mntpoint_ + "/big_file"; + auto status = FiemapWriter::Open(test_file, limits.first, &ptr); + ASSERT_FALSE(status.is_ok()); + ASSERT_EQ(status.error_code(), FiemapStatus::ErrorCode::NO_SPACE); + + // Also test for EFBIG. + status = FiemapWriter::Open(test_file, 16_TiB, &ptr); + ASSERT_FALSE(status.is_ok()); + ASSERT_NE(status.error_code(), FiemapStatus::ErrorCode::NO_SPACE); +} + bool DetermineBlockSize() { struct statfs s; if (statfs(gTestDir.c_str(), &s)) { diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp index 460d49db2..ce75a5416 100644 --- a/fs_mgr/libsnapshot/snapshot_test.cpp +++ b/fs_mgr/libsnapshot/snapshot_test.cpp @@ -2312,32 +2312,6 @@ TEST_F(SnapshotUpdateTest, Overflow) { << "FinishedSnapshotWrites should detect overflow of CoW device."; } -TEST_F(SnapshotUpdateTest, LowSpace) { - static constexpr auto kMaxFree = 10_MiB; - auto userdata = std::make_unique<LowSpaceUserdata>(); - ASSERT_TRUE(userdata->Init(kMaxFree)); - - // Grow all partitions to 10_MiB, total 30_MiB. This requires 30 MiB of CoW space. After - // using the empty space in super (< 1 MiB), it uses 30 MiB of /userdata space. - constexpr uint64_t partition_size = 10_MiB; - SetSize(sys_, partition_size); - SetSize(vnd_, partition_size); - SetSize(prd_, partition_size); - sys_->set_estimate_cow_size(partition_size); - vnd_->set_estimate_cow_size(partition_size); - prd_->set_estimate_cow_size(partition_size); - - AddOperationForPartitions(); - - // Execute the update. - ASSERT_TRUE(sm->BeginUpdate()); - auto res = sm->CreateUpdateSnapshots(manifest_); - ASSERT_FALSE(res); - ASSERT_EQ(Return::ErrorCode::NO_SPACE, res.error_code()); - ASSERT_GE(res.required_size(), 14_MiB); - ASSERT_LT(res.required_size(), 40_MiB); -} - TEST_F(SnapshotUpdateTest, AddPartition) { group_->add_partition_names("dlkm"); @@ -2699,50 +2673,6 @@ INSTANTIATE_TEST_SUITE_P(Snapshot, FlashAfterUpdateTest, Combine(Values(0, 1), B "Merge"s; }); -class ImageManagerTest : public SnapshotTest { - protected: - void SetUp() override { - SKIP_IF_NON_VIRTUAL_AB(); - SnapshotTest::SetUp(); - } - void TearDown() override { - RETURN_IF_NON_VIRTUAL_AB(); - CleanUp(); - } - void CleanUp() { - if (!image_manager_) { - return; - } - EXPECT_TRUE(!image_manager_->BackingImageExists(kImageName) || - image_manager_->DeleteBackingImage(kImageName)); - } - - static constexpr const char* kImageName = "my_image"; -}; - -TEST_F(ImageManagerTest, CreateImageNoSpace) { - bool at_least_one_failure = false; - for (uint64_t size = 1_MiB; size <= 512_MiB; size *= 2) { - auto userdata = std::make_unique<LowSpaceUserdata>(); - ASSERT_TRUE(userdata->Init(size)); - - uint64_t to_allocate = userdata->free_space() + userdata->bsize(); - - auto res = image_manager_->CreateBackingImage(kImageName, to_allocate, - IImageManager::CREATE_IMAGE_DEFAULT); - if (!res) { - at_least_one_failure = true; - } else { - ASSERT_EQ(res.error_code(), FiemapStatus::ErrorCode::NO_SPACE) << res.string(); - } - - CleanUp(); - } - - ASSERT_TRUE(at_least_one_failure) - << "We should have failed to allocate at least one over-sized image"; -} - bool Mkdir(const std::string& path) { if (mkdir(path.c_str(), 0700) && errno != EEXIST) { std::cerr << "Could not mkdir " << path << ": " << strerror(errno) << std::endl; diff --git a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h index ac0dfbdb7..bbeabd5c9 100644 --- a/fs_mgr/libstorage_literals/storage_literals/storage_literals.h +++ b/fs_mgr/libstorage_literals/storage_literals/storage_literals.h @@ -37,6 +37,7 @@ using B = Size<0>; using KiB = Size<10>; using MiB = Size<20>; using GiB = Size<30>; +using TiB = Size<40>; constexpr B operator""_B(unsigned long long v) { // NOLINT return B{v}; @@ -54,6 +55,10 @@ constexpr GiB operator""_GiB(unsigned long long v) { // NOLINT return GiB{v}; } +constexpr TiB operator""_TiB(unsigned long long v) { // NOLINT + return TiB{v}; +} + template <typename Dest, typename Src> constexpr Dest size_cast(Src src) { if (Src::power < Dest::power) { @@ -69,6 +74,7 @@ static_assert(1_B == 1); static_assert(1_KiB == 1 << 10); static_assert(1_MiB == 1 << 20); static_assert(1_GiB == 1 << 30); +static_assert(1_TiB == 1ULL << 40); static_assert(size_cast<KiB>(1_B).count() == 0); static_assert(size_cast<KiB>(1024_B).count() == 1); static_assert(size_cast<KiB>(1_MiB).count() == 1024); diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp index 4d771fa04..bf003eef7 100644 --- a/fs_mgr/tests/vts_fs_test.cpp +++ b/fs_mgr/tests/vts_fs_test.cpp @@ -30,6 +30,24 @@ static int GetVsrLevel() { return android::base::GetIntProperty("ro.vendor.api_level", -1); } +// Returns true iff the device has the specified feature. +bool DeviceSupportsFeature(const char* feature) { + bool device_supports_feature = false; + FILE* p = popen("pm list features", "re"); + if (p) { + char* line = NULL; + size_t len = 0; + while (getline(&line, &len, p) > 0) { + if (strstr(line, feature)) { + device_supports_feature = true; + break; + } + } + pclose(p); + } + return device_supports_feature; +} + TEST(fs, ErofsSupported) { // T-launch GKI kernels and higher must support EROFS. if (GetVsrLevel() < __ANDROID_API_T__) { @@ -80,7 +98,8 @@ TEST(fs, PartitionTypes) { ASSERT_TRUE(android::base::Readlink("/dev/block/by-name/userdata", &userdata_bdev)); std::vector<std::string> must_be_f2fs = {"/data"}; - if (vsr_level >= __ANDROID_API_U__) { + if (vsr_level >= __ANDROID_API_U__ && + !DeviceSupportsFeature("android.hardware.type.automotive")) { must_be_f2fs.emplace_back("/metadata"); } diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp index 6a27f9a20..56d68759f 100644 --- a/libcutils/ashmem-dev.cpp +++ b/libcutils/ashmem-dev.cpp @@ -349,6 +349,12 @@ static int memfd_create_region(const char* name, size_t size) { return -1; } + // forbid size changes to match ashmem behaviour + if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) == -1) { + ALOGE("memfd_create(%s, %zd) F_ADD_SEALS failed: %m", name, size); + return -1; + } + if (debug_log) { ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get()); } @@ -400,14 +406,29 @@ error: } static int memfd_set_prot_region(int fd, int prot) { - /* Only proceed if an fd needs to be write-protected */ + int seals = fcntl(fd, F_GET_SEALS); + if (seals == -1) { + ALOGE("memfd_set_prot_region(%d, %d): F_GET_SEALS failed: %s\n", fd, prot, strerror(errno)); + return -1; + } + if (prot & PROT_WRITE) { + /* Now we want the buffer to be read-write, let's check if the buffer + * has been previously marked as read-only before, if so return error + */ + if (seals & F_SEAL_FUTURE_WRITE) { + ALOGE("memfd_set_prot_region(%d, %d): region is write protected\n", fd, prot); + errno = EINVAL; // inline with ashmem error code, if already in + // read-only mode + return -1; + } return 0; } - if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) { - ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot, - strerror(errno)); + /* We would only allow read-only for any future file operations */ + if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE | F_SEAL_SEAL) == -1) { + ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE | F_SEAL_SEAL seal failed: %s\n", + fd, prot, strerror(errno)); return -1; } |