diff options
-rw-r--r-- | fs_mgr/fs_mgr.cpp | 25 | ||||
-rw-r--r-- | fs_mgr/tests/vts_fs_test.cpp | 21 | ||||
-rw-r--r-- | libcutils/ashmem-dev.cpp | 29 |
3 files changed, 69 insertions, 6 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/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; } |