libfstab_fuzzer: fuzz TransformFstabForDsu() and skip mount logic
These functions contain complex logic and parse user input. It shall be
valuable to fuzz these functions to prevent regression.
Bug: 254832225
Test: Build and run the fuzzer
Change-Id: I21099c3fc1c226f95a0f8f996bb751030e0c59bc
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 76ef9e4..7189a71 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -754,10 +754,11 @@
}
#ifdef NO_SKIP_MOUNT
-bool SkipMountingPartitions(Fstab*, bool) {
- return true;
-}
+static constexpr bool kNoSkipMount = true;
#else
+static constexpr bool kNoSkipMount = false;
+#endif
+
// For GSI to skip mounting /product and /system_ext, until there are well-defined interfaces
// between them and /system. Otherwise, the GSI flashed on /system might not be able to work with
// device-specific /product and /system_ext. skip_mount.cfg belongs to system_ext partition because
@@ -765,17 +766,24 @@
// /system/system_ext because GSI is a single system.img that includes the contents of system_ext
// partition and product partition under /system/system_ext and /system/product, respectively.
bool SkipMountingPartitions(Fstab* fstab, bool verbose) {
- static constexpr char kSkipMountConfig[] = "/system/system_ext/etc/init/config/skip_mount.cfg";
-
- std::string skip_config;
- auto save_errno = errno;
- if (!ReadFileToString(kSkipMountConfig, &skip_config)) {
- errno = save_errno; // missing file is expected
+ if (kNoSkipMount) {
return true;
}
+ static constexpr char kSkipMountConfig[] = "/system/system_ext/etc/init/config/skip_mount.cfg";
+
+ std::string skip_mount_config;
+ auto save_errno = errno;
+ if (!ReadFileToString(kSkipMountConfig, &skip_mount_config)) {
+ errno = save_errno; // missing file is expected
+ return true;
+ }
+ return SkipMountWithConfig(skip_mount_config, fstab, verbose);
+}
+
+bool SkipMountWithConfig(const std::string& skip_mount_config, Fstab* fstab, bool verbose) {
std::vector<std::string> skip_mount_patterns;
- for (const auto& line : Split(skip_config, "\n")) {
+ for (const auto& line : Split(skip_mount_config, "\n")) {
if (line.empty() || StartsWith(line, "#")) {
continue;
}
@@ -801,7 +809,6 @@
fstab->erase(remove_from, fstab->end());
return true;
}
-#endif
// Loads the fstab file and combines with fstab entries passed in from device tree.
bool ReadDefaultFstab(Fstab* fstab) {
diff --git a/fs_mgr/fuzz/fs_mgr_fstab_fuzzer.cpp b/fs_mgr/fuzz/fs_mgr_fstab_fuzzer.cpp
index 6a8a191..b5fdad4 100644
--- a/fs_mgr/fuzz/fs_mgr_fstab_fuzzer.cpp
+++ b/fs_mgr/fuzz/fs_mgr_fstab_fuzzer.cpp
@@ -14,13 +14,27 @@
// limitations under the License.
//
-#include <cstdio>
+#include <string>
+#include <vector>
#include <fstab/fstab.h>
+#include <fuzzer/FuzzedDataProvider.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- std::string make_fstab_str(reinterpret_cast<const char*>(data), size);
+ FuzzedDataProvider fdp(data, size);
+
+ std::string make_fstab_str = fdp.ConsumeRandomLengthString();
+ std::string dsu_slot = fdp.ConsumeRandomLengthString(30);
+ std::vector<std::string> dsu_partitions = {
+ fdp.ConsumeRandomLengthString(30),
+ fdp.ConsumeRandomLengthString(30),
+ };
+ std::string skip_mount_config = fdp.ConsumeRemainingBytesAsString();
+
android::fs_mgr::Fstab fstab;
android::fs_mgr::ParseFstabFromString(make_fstab_str, /* proc_mounts = */ false, &fstab);
+ android::fs_mgr::TransformFstabForDsu(&fstab, dsu_slot, dsu_partitions);
+ android::fs_mgr::SkipMountWithConfig(skip_mount_config, &fstab, /* verbose = */ false);
+
return 0;
}
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 689d18b..124f070 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -97,6 +97,8 @@
bool ParseFstabFromString(const std::string& fstab_str, bool proc_mounts, Fstab* fstab_out);
// Exported for testability. Regular users should use ReadDefaultFstab().
std::string GetFstabPath();
+// Exported for testability.
+bool SkipMountWithConfig(const std::string& skip_config, Fstab* fstab, bool verbose);
bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
bool ReadFstabFromDt(Fstab* fstab, bool verbose = true);