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

Commit 1b066c31 authored by Mark Salyzyn's avatar Mark Salyzyn
Browse files

fs_mgr: fs_mgr_has_shared_blocks() needs logical blk_device

For logical partitions, the fstab supplied during
fs_mgr_overlayfs_setup() does not have the correct blk_device and
thus check in fs_mgr_has_shared_blocks() inside
fs_mgr_overlayfs_enabled() will fail to provide the correct status.

Call fs_mgr_update_logical_partition() to fix this up.  Side effect
is an API change where fstab can no longer be considered const when
passed into fs_mgr_overlayfs_mount_all() and
fs_mgr_overlayfs_required_devices().

Some additional minor cleanup as well.  Move fs_mgr_rm_all() higher
up as-is in the file as it has no dependencies, which will complicate
future changes.  Add --help to adb-remount-test.sh unit test script,
improve error handling and checking.

Test: adb-remount-test.sh
Bug: 109821005
Bug: 117605276
Change-Id: I548d3797d49661529490d1a0bf96b63e57491704
parent 55d31ecd
Loading
Loading
Loading
Loading
+59 −56
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <ext4_utils/ext4_utils.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <fs_mgr_overlayfs.h>
#include <fstab/fstab.h>
@@ -127,13 +128,63 @@ bool fs_mgr_filesystem_has_space(const char* mount_point) {
    return (vst.f_bfree >= (vst.f_blocks * kPercentThreshold / 100));
}

bool fs_mgr_overlayfs_enabled(const struct fstab_rec* fsrec) {
bool fs_mgr_overlayfs_enabled(struct fstab_rec* fsrec) {
    // readonly filesystem, can not be mount -o remount,rw
    // if squashfs or if free space is (near) zero making such a remount
    // virtually useless, or if there are shared blocks that prevent remount,rw
    return ("squashfs"s == fsrec->fs_type) ||
           fs_mgr_has_shared_blocks(fsrec->mount_point, fsrec->blk_device) ||
           !fs_mgr_filesystem_has_space(fsrec->mount_point);
    if (("squashfs"s == fsrec->fs_type) || !fs_mgr_filesystem_has_space(fsrec->mount_point)) {
        return true;
    }
    if (fs_mgr_is_logical(fsrec)) {
        fs_mgr_update_logical_partition(fsrec);
    }
    return fs_mgr_has_shared_blocks(fsrec->mount_point, fsrec->blk_device);
}

bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
    auto save_errno = errno;
    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
    if (!dir) {
        if (errno == ENOENT) {
            errno = save_errno;
            return true;
        }
        PERROR << "opendir " << path << " depth=" << level;
        if ((errno == EPERM) && (level != 0)) {
            errno = save_errno;
            return true;
        }
        return false;
    }
    dirent* entry;
    auto ret = true;
    while ((entry = readdir(dir.get()))) {
        if (("."s == entry->d_name) || (".."s == entry->d_name)) continue;
        auto file = path + "/" + entry->d_name;
        if (entry->d_type == DT_UNKNOWN) {
            struct stat st;
            save_errno = errno;
            if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
            errno = save_errno;
        }
        if (entry->d_type == DT_DIR) {
            ret &= fs_mgr_rm_all(file, change, level + 1);
            if (!rmdir(file.c_str())) {
                if (change) *change = true;
            } else {
                if (errno != ENOENT) ret = false;
                PERROR << "rmdir " << file << " depth=" << level;
            }
            continue;
        }
        if (!unlink(file.c_str())) {
            if (change) *change = true;
        } else {
            if (errno != ENOENT) ret = false;
            PERROR << "rm " << file << " depth=" << level;
        }
    }
    return ret;
}

const auto kUpperName = "upper"s;
@@ -235,7 +286,7 @@ std::vector<std::string> fs_mgr_overlayfs_verity_enabled_list() {
    return ret;
}

bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) {
bool fs_mgr_wants_overlayfs(fstab_rec* fsrec) {
    if (!fsrec) return false;

    auto fsrec_mount_point = fsrec->mount_point;
@@ -260,53 +311,6 @@ bool fs_mgr_wants_overlayfs(const fstab_rec* fsrec) {

    return true;
}

bool fs_mgr_rm_all(const std::string& path, bool* change = nullptr, int level = 0) {
    auto save_errno = errno;
    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
    if (!dir) {
        if (errno == ENOENT) {
            errno = save_errno;
            return true;
        }
        PERROR << "opendir " << path << " depth=" << level;
        if ((errno == EPERM) && (level != 0)) {
            errno = save_errno;
            return true;
        }
        return false;
    }
    dirent* entry;
    auto ret = true;
    while ((entry = readdir(dir.get()))) {
        if (("."s == entry->d_name) || (".."s == entry->d_name)) continue;
        auto file = path + "/" + entry->d_name;
        if (entry->d_type == DT_UNKNOWN) {
            struct stat st;
            save_errno = errno;
            if (!lstat(file.c_str(), &st) && (st.st_mode & S_IFDIR)) entry->d_type = DT_DIR;
            errno = save_errno;
        }
        if (entry->d_type == DT_DIR) {
            ret &= fs_mgr_rm_all(file, change, level + 1);
            if (!rmdir(file.c_str())) {
                if (change) *change = true;
            } else {
                if (errno != ENOENT) ret = false;
                PERROR << "rmdir " << file << " depth=" << level;
            }
            continue;
        }
        if (!unlink(file.c_str())) {
            if (change) *change = true;
        } else {
            if (errno != ENOENT) ret = false;
            PERROR << "rm " << file << " depth=" << level;
        }
    }
    return ret;
}

constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";

bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
@@ -532,8 +536,7 @@ bool fs_mgr_overlayfs_mount(const std::string& mount_point) {
    }
}

std::vector<std::string> fs_mgr_candidate_list(const fstab* fstab,
                                               const char* mount_point = nullptr) {
std::vector<std::string> fs_mgr_candidate_list(fstab* fstab, const char* mount_point = nullptr) {
    std::vector<std::string> mounts;
    if (!fstab) return mounts;

@@ -734,7 +737,7 @@ bool fs_mgr_overlayfs_scratch_can_be_mounted(const std::string& scratch_device)

}  // namespace

bool fs_mgr_overlayfs_mount_all(const fstab* fstab) {
bool fs_mgr_overlayfs_mount_all(fstab* fstab) {
    auto ret = false;

    if (!fs_mgr_wants_overlayfs()) return ret;
@@ -761,7 +764,7 @@ bool fs_mgr_overlayfs_mount_all(const fstab* fstab) {
    return ret;
}

std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab* fstab) {
std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab) {
    if (fs_mgr_get_entry_for_mount_point(const_cast<struct fstab*>(fstab), kScratchMountPoint)) {
        return {};
    }
+2 −2
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@
#include <string>
#include <vector>

bool fs_mgr_overlayfs_mount_all(const fstab* fstab);
std::vector<std::string> fs_mgr_overlayfs_required_devices(const fstab* fstab);
bool fs_mgr_overlayfs_mount_all(fstab* fstab);
std::vector<std::string> fs_mgr_overlayfs_required_devices(fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
                            bool* change = nullptr);
bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
+31 −15
Original line number Diff line number Diff line
#! /bin/bash
#
# adb remount tests (overlayfs focus)
#
# Conditions:
#  - Must be a userdebug build.
#  - Must be in adb mode.
#  - Kernel must have overlayfs enabled and patched to support override_creds.
#  - Must have either squashfs, ext4-dedupe or right-sized partitions.
#  - Minimum expectation system and vender are overlayfs covered partitions.
#

USAGE="USAGE: `basename ${0}` [-s <SerialNumber>]

adb remount tests (overlayfs focus)

Conditions:
 - Must be a userdebug build.
 - Must be in adb mode.
 - Kernel must have overlayfs enabled and patched to support override_creds.
 - Must have either squashfs, ext4-dedupe or right-sized partitions.
 - Minimum expectation system and vender are overlayfs covered partitions.
"

if [ X"${1}" = X"--help" -o X"${1}" = X"-h" -o X"${1}" = X"-?" ]; then
  echo "${USAGE}" >&2
  exit 0
fi

# Helper Variables

@@ -86,11 +93,15 @@ adb_reboot() {
  adb reboot remount-test
}

[ "USAGE: adb_wait
[ "USAGE: adb_wait [timeout]

Returns: waits until the device has returned" ]
Returns: waits until the device has returned or the optional timeout" ]
adb_wait() {
  if [ -n "${1}" ]; then
    timeout --preserve-status --signal=KILL ${1} adb wait-for-device
  else
    adb wait-for-device
  fi
}

[ "USAGE: adb_root
@@ -178,6 +189,10 @@ if [ X"-s" = X"${1}" -a -n "${2}" ]; then
fi

inFastboot && die "device in fastboot mode"
if ! inAdb; then
  echo "${ORANGE}[  WARNING ]${NORMAL} device not in adb mode ... waiting 2 minutes"
  adb_wait 2m
fi
inAdb || die "device not in adb mode"
isDebuggable || die "device not a debug build"

@@ -205,7 +220,8 @@ adb_sh ls -d /cache/overlay </dev/null >/dev/null 2>&1 ||
adb_reboot &&
  adb_wait &&
  adb_sh df -k </dev/null | head -1 &&
  adb_sh df -k </dev/null | grep "^overlay " &&
  adb_sh df -k </dev/null | grep "^overlay " ||
  die "overlay takeover failed"
adb_sh df -k </dev/null | grep "^overlay .* /system\$" >/dev/null ||
  echo "${ORANGE}[  WARNING ]${NORMAL} overlay takeover before remount not complete" >&2