Merge "fs_mgr: Refactor mandatory overlayfs kernel patch checks" into main
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e568a9b..d55f8d3 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -2227,8 +2227,8 @@
 }
 
 bool fs_mgr_mount_overlayfs_fstab_entry(const FstabEntry& entry) {
-    auto overlayfs_valid_result = fs_mgr_overlayfs_valid();
-    if (overlayfs_valid_result == OverlayfsValidResult::kNotSupported) {
+    const auto overlayfs_check_result = android::fs_mgr::CheckOverlayfs();
+    if (!overlayfs_check_result.supported) {
         LERROR << __FUNCTION__ << "(): kernel does not support overlayfs";
         return false;
     }
@@ -2280,10 +2280,7 @@
         }
     }
 
-    auto options = "lowerdir=" + lowerdir;
-    if (overlayfs_valid_result == OverlayfsValidResult::kOverrideCredsRequired) {
-        options += ",override_creds=off";
-    }
+    const auto options = "lowerdir=" + lowerdir + overlayfs_check_result.mount_flags;
 
     // Use "overlay-" + entry.blk_device as the mount() source, so that adb-remout-test don't
     // confuse this with adb remount overlay, whose device name is "overlay".
@@ -2339,30 +2336,34 @@
     return context;
 }
 
-OverlayfsValidResult fs_mgr_overlayfs_valid() {
-    // Overlayfs available in the kernel, and patched for override_creds?
-    if (access("/sys/module/overlay/parameters/override_creds", F_OK) == 0) {
-        return OverlayfsValidResult::kOverrideCredsRequired;
-    }
+namespace android {
+namespace fs_mgr {
+
+OverlayfsCheckResult CheckOverlayfs() {
     if (!fs_mgr_filesystem_available("overlay")) {
-        return OverlayfsValidResult::kNotSupported;
+        return {.supported = false};
     }
     struct utsname uts;
     if (uname(&uts) == -1) {
-        return OverlayfsValidResult::kNotSupported;
+        return {.supported = false};
     }
     int major, minor;
     if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
-        return OverlayfsValidResult::kNotSupported;
+        return {.supported = false};
     }
-    if (major < 4) {
-        return OverlayfsValidResult::kOk;
+    // Overlayfs available in the kernel, and patched for override_creds?
+    if (access("/sys/module/overlay/parameters/override_creds", F_OK) == 0) {
+        auto mount_flags = ",override_creds=off"s;
+        if (major > 5 || (major == 5 && minor >= 15)) {
+            mount_flags += ",userxattr"s;
+        }
+        return {.supported = true, .mount_flags = mount_flags};
     }
-    if (major > 4) {
-        return OverlayfsValidResult::kNotSupported;
+    if (major < 4 || (major == 4 && minor <= 3)) {
+        return {.supported = true};
     }
-    if (minor > 3) {
-        return OverlayfsValidResult::kNotSupported;
-    }
-    return OverlayfsValidResult::kOk;
+    return {.supported = false};
 }
+
+}  // namespace fs_mgr
+}  // namespace android
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index 37e3058..8fb63b1 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -23,7 +23,6 @@
 #include <sys/stat.h>
 #include <sys/statvfs.h>
 #include <sys/types.h>
-#include <sys/utsname.h>
 #include <sys/vfs.h>
 #include <unistd.h>
 
@@ -218,17 +217,6 @@
     return "";
 }
 
-static inline bool KernelSupportsUserXattrs() {
-    struct utsname uts;
-    uname(&uts);
-
-    int major, minor;
-    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
-        return false;
-    }
-    return major > 5 || (major == 5 && minor >= 15);
-}
-
 const std::string fs_mgr_mount_point(const std::string& mount_point) {
     if ("/"s != mount_point) return mount_point;
     return "/system";
@@ -240,13 +228,7 @@
     auto candidate = fs_mgr_get_overlayfs_candidate(mount_point);
     if (candidate.empty()) return "";
     auto ret = kLowerdirOption + mount_point + "," + kUpperdirOption + candidate + kUpperName +
-               ",workdir=" + candidate + kWorkName;
-    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
-        ret += ",override_creds=off";
-    }
-    if (KernelSupportsUserXattrs()) {
-        ret += ",userxattr";
-    }
+               ",workdir=" + candidate + kWorkName + android::fs_mgr::CheckOverlayfs().mount_flags;
     for (const auto& flag : android::base::Split(entry.fs_options, ",")) {
         if (android::base::StartsWith(flag, "context=")) {
             ret += "," + flag;
@@ -608,7 +590,7 @@
         return false;
     }
     // Check mandatory kernel patches.
-    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
+    if (!android::fs_mgr::CheckOverlayfs().supported) {
         if (verbose) {
             LOG(ERROR) << "Kernel does not support overlayfs";
         }
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 678dd69..12a4a6d 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -100,18 +100,18 @@
 bool fs_mgr_filesystem_available(const std::string& filesystem);
 std::string fs_mgr_get_context(const std::string& mount_point);
 
-enum class OverlayfsValidResult {
-    kNotSupported = 0,
-    kOk,
-    kOverrideCredsRequired,
-};
-OverlayfsValidResult fs_mgr_overlayfs_valid();
-
 namespace android {
 namespace fs_mgr {
 
 bool UnmapDevice(const std::string& name);
 bool InRecovery();
 
+struct OverlayfsCheckResult {
+    bool supported;
+    std::string mount_flags;
+};
+
+OverlayfsCheckResult CheckOverlayfs();
+
 }  // namespace fs_mgr
 }  // namespace android
diff --git a/fs_mgr/fs_mgr_vendor_overlay.cpp b/fs_mgr/fs_mgr_vendor_overlay.cpp
index 6b32b4d..bacfa4b 100644
--- a/fs_mgr/fs_mgr_vendor_overlay.cpp
+++ b/fs_mgr/fs_mgr_vendor_overlay.cpp
@@ -85,10 +85,8 @@
         return false;
     }
 
-    auto options = kLowerdirOption + source_directory + ":" + vendor_mount_point;
-    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kOverrideCredsRequired) {
-        options += ",override_creds=off";
-    }
+    const auto options = kLowerdirOption + source_directory + ":" + vendor_mount_point +
+                         android::fs_mgr::CheckOverlayfs().mount_flags;
     auto report = "__mount(source=overlay,target="s + vendor_mount_point + ",type=overlay," +
                   options + ")=";
     auto ret = mount("overlay", vendor_mount_point.c_str(), "overlay", MS_RDONLY | MS_NOATIME,
@@ -120,7 +118,7 @@
 
     const auto vendor_overlay_dirs = fs_mgr_get_vendor_overlay_dirs(vndk_version);
     if (vendor_overlay_dirs.empty()) return true;
-    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
+    if (!android::fs_mgr::CheckOverlayfs().supported) {
         LINFO << "vendor overlay: kernel does not support overlayfs";
         return false;
     }