Loading fs_mgr/fs_mgr_overlayfs.cpp +59 −56 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 {}; } Loading fs_mgr/include/fs_mgr_overlayfs.h +2 −2 Original line number Diff line number Diff line Loading @@ -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); Loading fs_mgr/tests/adb-remount-test.sh +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 Loading Loading @@ -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 Loading Loading @@ -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" Loading Loading @@ -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 Loading Loading
fs_mgr/fs_mgr_overlayfs.cpp +59 −56 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 {}; } Loading
fs_mgr/include/fs_mgr_overlayfs.h +2 −2 Original line number Diff line number Diff line Loading @@ -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); Loading
fs_mgr/tests/adb-remount-test.sh +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 Loading Loading @@ -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 Loading Loading @@ -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" Loading Loading @@ -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 Loading