Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad06b405 authored by Yi-Yo Chiang's avatar Yi-Yo Chiang
Browse files

fs_mgr_overlayfs: Cleanup -user build stubs

* Categorize functions in fs_mgr_overlayfs.h into three classes:
  - Type 1: common and non-critical utilities.
  - Type 2: internal routines for facilitating remount.
  - Type 3: external entry points for users of fs_mgr_overlayfs, like
            fs_mgr_overlayfs_mount_all().
* Move type 1 to common utils header fs_mgr_priv.h & fs_mgr.cpp.
* Move type 2 to new private header fs_mgr_priv_overlayfs.h.
* Keep type 3 in fs_mgr_overlayfs.h.
* Move set-verity-state.cpp under fs_mgr so it can include
  fs_mgr_priv_overlayfs.h. File is reformatted as a result. We should
  eventually merge and dedup set-verity-state and fs_mgr_remount.
* Add myself to OWNERS for remount-related maintenance work.

Bug: 241179247
Bug: 241688845
Test: Full build -user and -userdebug build.
Test: Presubmit
Test: Treehugger run v2/android-gki/adb_remount
Change-Id: Id5fd0e2b12c693939d712a586dd553cc4d8bfeb1
parent 0cba7afd
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line Diff line number Diff line
@@ -254,3 +254,39 @@ cc_binary {
        "clean_scratch_files",
        "clean_scratch_files",
    ],
    ],
}
}

cc_binary {
    name: "set-verity-state",
    srcs: ["set-verity-state.cpp"],
    shared_libs: [
        "libbase",
        "libbinder",
        "libcrypto",
        "libcrypto_utils",
        "libfs_mgr_binder",
        "libutils",
    ],
    static_libs: [
        "libavb_user",
    ],
    header_libs: [
        "libcutils_headers",
    ],

    cflags: ["-Werror"],
    cppflags: [
        "-DALLOW_DISABLE_VERITY=0",
    ],
    product_variables: {
        debuggable: {
            cppflags: [
                "-UALLOW_DISABLE_VERITY",
                "-DALLOW_DISABLE_VERITY=1",
            ],
        },
    },
    symlinks: [
        "enable-verity",
        "disable-verity",
    ],
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -2,3 +2,4 @@
bowgotsai@google.com
bowgotsai@google.com
dvander@google.com
dvander@google.com
elsk@google.com
elsk@google.com
yochiang@google.com
+48 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@
#include <fcntl.h>
#include <fcntl.h>
#include <inttypes.h>
#include <inttypes.h>
#include <libgen.h>
#include <libgen.h>
#include <selinux/selinux.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
@@ -30,6 +31,7 @@
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/swap.h>
#include <sys/swap.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <sys/wait.h>
#include <time.h>
#include <time.h>
#include <unistd.h>
#include <unistd.h>
@@ -2359,3 +2361,49 @@ bool fs_mgr_load_verity_state(int* mode) {


    return true;
    return true;
}
}

bool fs_mgr_filesystem_available(const std::string& filesystem) {
    std::string filesystems;
    if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
    return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
}

std::string fs_mgr_get_context(const std::string& mount_point) {
    char* ctx = nullptr;
    if (getfilecon(mount_point.c_str(), &ctx) == -1) {
        PERROR << "getfilecon " << mount_point;
        return "";
    }

    std::string context(ctx);
    free(ctx);
    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;
    }
    if (!fs_mgr_filesystem_available("overlay")) {
        return OverlayfsValidResult::kNotSupported;
    }
    struct utsname uts;
    if (uname(&uts) == -1) {
        return OverlayfsValidResult::kNotSupported;
    }
    int major, minor;
    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
        return OverlayfsValidResult::kNotSupported;
    }
    if (major < 4) {
        return OverlayfsValidResult::kOk;
    }
    if (major > 4) {
        return OverlayfsValidResult::kNotSupported;
    }
    if (minor > 3) {
        return OverlayfsValidResult::kNotSupported;
    }
    return OverlayfsValidResult::kOk;
}
+76 −128
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@
#include <storage_literals/storage_literals.h>
#include <storage_literals/storage_literals.h>


#include "fs_mgr_priv.h"
#include "fs_mgr_priv.h"
#include "fs_mgr_priv_overlayfs.h"
#include "libfiemap/utility.h"
#include "libfiemap/utility.h"


using namespace std::literals;
using namespace std::literals;
@@ -71,62 +72,9 @@ bool fs_mgr_access(const std::string& path) {
    return access(path.c_str(), F_OK) == 0;
    return access(path.c_str(), F_OK) == 0;
}
}


// determine if a filesystem is available
bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
    std::string filesystems;
    if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
    return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
}

const auto kLowerdirOption = "lowerdir="s;
const auto kLowerdirOption = "lowerdir="s;
const auto kUpperdirOption = "upperdir="s;
const auto kUpperdirOption = "upperdir="s;


}  // namespace

#if ALLOW_ADBD_DISABLE_VERITY == 0  // If we are a user build, provide stubs

bool fs_mgr_wants_overlayfs(FstabEntry*) {
    return false;
}

Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
    return {};
}

bool fs_mgr_overlayfs_mount_all(Fstab*) {
    return false;
}

bool fs_mgr_overlayfs_setup(const char*, bool*, bool) {
    LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
    return false;
}

OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char*, bool*) {
    return OverlayfsTeardownResult::Ok;
}

bool fs_mgr_overlayfs_is_setup() {
    return false;
}

namespace android {
namespace fs_mgr {

void MapScratchPartitionIfNeeded(Fstab*, const std::function<bool(const std::set<std::string>&)>&) {
}

void CleanupOldScratchFiles() {}

void TeardownAllOverlayForMountPoint(const std::string&) {}

}  // namespace fs_mgr
}  // namespace android

#else  // ALLOW_ADBD_DISABLE_VERITY == 0

namespace {

bool fs_mgr_in_recovery() {
bool fs_mgr_in_recovery() {
    // Check the existence of recovery binary instead of using the compile time
    // Check the existence of recovery binary instead of using the compile time
    // __ANDROID_RECOVERY__ macro.
    // __ANDROID_RECOVERY__ macro.
@@ -234,6 +182,28 @@ bool fs_mgr_update_blk_device(FstabEntry* entry) {
    return true;
    return true;
}
}


bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
    struct statfs fs;
    if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
        (fs.f_type != EXT4_SUPER_MAGIC)) {
        return false;
    }

    android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
    if (fd < 0) return false;

    struct ext4_super_block sb;
    if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
        (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
        return false;
    }

    struct fs_info info;
    if (ext4_parse_sb(&sb, &info) < 0) return false;

    return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
}

bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
    // readonly filesystem, can not be mount -o remount,rw
    // readonly filesystem, can not be mount -o remount,rw
    // for squashfs, erofs or if free space is (near) zero making such a remount
    // for squashfs, erofs or if free space is (near) zero making such a remount
@@ -886,10 +856,10 @@ const std::string kMkExt4("/system/bin/mke2fs");


// Only a suggestion for _first_ try during mounting
// Only a suggestion for _first_ try during mounting
std::string fs_mgr_overlayfs_scratch_mount_type() {
std::string fs_mgr_overlayfs_scratch_mount_type() {
    if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
    if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) {
        return "f2fs";
        return "f2fs";
    }
    }
    if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
    if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) {
        return "ext4";
        return "ext4";
    }
    }
    return "auto";
    return "auto";
@@ -1233,11 +1203,41 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) {
    return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
    return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
}
}


bool fs_mgr_overlayfs_invalid() {
#if ALLOW_ADBD_DISABLE_VERITY
    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
constexpr bool kAllowOverlayfs = true;
#else
constexpr bool kAllowOverlayfs = false;
#endif


// NOTE: OverlayfsSetupAllowed() must be "stricter" than OverlayfsTeardownAllowed().
// Setup is allowed only if teardown is also allowed.
bool OverlayfsSetupAllowed(bool verbose = false) {
    if (!kAllowOverlayfs) {
        if (verbose) {
            LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
        }
        return false;
    }
    // Check mandatory kernel patches.
    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
        if (verbose) {
            LOG(ERROR) << "Kernel does not support overlayfs";
        }
        return false;
    }
    // in recovery or fastbootd, not allowed!
    // in recovery or fastbootd, not allowed!
    return fs_mgr_in_recovery();
    if (fs_mgr_in_recovery()) {
        if (verbose) {
            LOG(ERROR) << "Unsupported overlayfs setup from recovery";
        }
        return false;
    }
    return true;
}

constexpr bool OverlayfsTeardownAllowed() {
    // Never allow on non-debuggable build.
    return kAllowOverlayfs;
}
}


}  // namespace
}  // namespace
@@ -1331,7 +1331,7 @@ static void TryMountScratch() {
}
}


bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
    if (fs_mgr_overlayfs_invalid()) {
    if (!OverlayfsSetupAllowed()) {
        return false;
        return false;
    }
    }
    auto ret = true;
    auto ret = true;
@@ -1352,8 +1352,7 @@ bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
}
}


bool fs_mgr_overlayfs_setup(const char* mount_point, bool* want_reboot, bool just_disabled_verity) {
bool fs_mgr_overlayfs_setup(const char* mount_point, bool* want_reboot, bool just_disabled_verity) {
    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
    if (!OverlayfsSetupAllowed(/*verbose=*/true)) {
        LOG(ERROR) << "Overlayfs is not supported";
        return false;
        return false;
    }
    }


@@ -1523,7 +1522,8 @@ static bool MapDsuScratchDevice(std::string* device) {
    return true;
    return true;
}
}


OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point, bool* want_reboot) {
static OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point,
                                                        bool* want_reboot) {
    bool should_destroy_scratch = false;
    bool should_destroy_scratch = false;
    auto rv = OverlayfsTeardownResult::Ok;
    auto rv = OverlayfsTeardownResult::Ok;
    for (const auto& overlay_mount_point : OverlayMountPoints()) {
    for (const auto& overlay_mount_point : OverlayMountPoints()) {
@@ -1555,6 +1555,10 @@ OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point, bool*


// Returns false if teardown not permitted. If something is altered, set *want_reboot.
// Returns false if teardown not permitted. If something is altered, set *want_reboot.
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* want_reboot) {
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* want_reboot) {
    if (!OverlayfsTeardownAllowed()) {
        // Nothing to teardown.
        return OverlayfsTeardownResult::Ok;
    }
    // If scratch exists, but is not mounted, lets gain access to clean
    // If scratch exists, but is not mounted, lets gain access to clean
    // specific override entries.
    // specific override entries.
    auto mount_scratch = false;
    auto mount_scratch = false;
@@ -1577,12 +1581,14 @@ OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool*
}
}


bool fs_mgr_overlayfs_is_setup() {
bool fs_mgr_overlayfs_is_setup() {
    if (!OverlayfsSetupAllowed()) {
        return false;
    }
    if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
    if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
    Fstab fstab;
    Fstab fstab;
    if (!ReadDefaultFstab(&fstab)) {
    if (!ReadDefaultFstab(&fstab)) {
        return false;
        return false;
    }
    }
    if (fs_mgr_overlayfs_invalid()) return false;
    for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
    for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
        if (fs_mgr_is_verity_enabled(entry)) continue;
        if (fs_mgr_is_verity_enabled(entry)) continue;
        if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
        if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
@@ -1595,7 +1601,7 @@ namespace fs_mgr {


void MapScratchPartitionIfNeeded(Fstab* fstab,
void MapScratchPartitionIfNeeded(Fstab* fstab,
                                 const std::function<bool(const std::set<std::string>&)>& init) {
                                 const std::function<bool(const std::set<std::string>&)>& init) {
    if (fs_mgr_overlayfs_invalid()) {
    if (!OverlayfsSetupAllowed()) {
        return;
        return;
    }
    }
    if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
    if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
@@ -1632,6 +1638,9 @@ void MapScratchPartitionIfNeeded(Fstab* fstab,
}
}


void CleanupOldScratchFiles() {
void CleanupOldScratchFiles() {
    if (!OverlayfsTeardownAllowed()) {
        return;
    }
    if (!ScratchIsOnData()) {
    if (!ScratchIsOnData()) {
        return;
        return;
    }
    }
@@ -1641,6 +1650,9 @@ void CleanupOldScratchFiles() {
}
}


void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
    if (!OverlayfsTeardownAllowed()) {
        return;
    }
    if (!fs_mgr_in_recovery()) {
    if (!fs_mgr_in_recovery()) {
        LERROR << __FUNCTION__ << "(): must be called within recovery.";
        LERROR << __FUNCTION__ << "(): must be called within recovery.";
        return;
        return;
@@ -1701,8 +1713,6 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
}  // namespace fs_mgr
}  // namespace fs_mgr
}  // namespace android
}  // namespace android


#endif  // ALLOW_ADBD_DISABLE_VERITY != 0

bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
    Fstab fstab;
    Fstab fstab;
    if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
    if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
@@ -1722,65 +1732,3 @@ bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overl
    }
    }
    return false;
    return false;
}
}

bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
    struct statfs fs;
    if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
        (fs.f_type != EXT4_SUPER_MAGIC)) {
        return false;
    }

    android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
    if (fd < 0) return false;

    struct ext4_super_block sb;
    if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
        (TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
        return false;
    }

    struct fs_info info;
    if (ext4_parse_sb(&sb, &info) < 0) return false;

    return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
}

std::string fs_mgr_get_context(const std::string& mount_point) {
    char* ctx = nullptr;
    if (getfilecon(mount_point.c_str(), &ctx) == -1) {
        PLOG(ERROR) << "getfilecon " << mount_point;
        return "";
    }

    std::string context(ctx);
    free(ctx);
    return context;
}

OverlayfsValidResult fs_mgr_overlayfs_valid() {
    // Overlayfs available in the kernel, and patched for override_creds?
    if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
        return OverlayfsValidResult::kOverrideCredsRequired;
    }
    if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
        return OverlayfsValidResult::kNotSupported;
    }
    struct utsname uts;
    if (uname(&uts) == -1) {
        return OverlayfsValidResult::kNotSupported;
    }
    int major, minor;
    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
        return OverlayfsValidResult::kNotSupported;
    }
    if (major < 4) {
        return OverlayfsValidResult::kOk;
    }
    if (major > 4) {
        return OverlayfsValidResult::kNotSupported;
    }
    if (minor > 3) {
        return OverlayfsValidResult::kNotSupported;
    }
    return OverlayfsValidResult::kOk;
}
+10 −0
Original line number Original line Diff line number Diff line
@@ -99,6 +99,16 @@ bool fs_mgr_is_f2fs(const std::string& blk_device);


bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab);
bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab);


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 android {
namespace fs_mgr {
namespace fs_mgr {
bool UnmapDevice(const std::string& name);
bool UnmapDevice(const std::string& name);
Loading