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

Commit 2e007e03 authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge changes I7a9e07a4,I3ddab553,I212bdb0e

* changes:
  remount: Remove the "backing" parameter to fs_mgr_overlayfs_setup.
  remount: Prevent error spam when remounting fails.
  remount: Move more stuff out of do_remount.
parents 693ac06a e9e3f6e0
Loading
Loading
Loading
Loading
+39 −26
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ bool fs_mgr_overlayfs_mount_all(Fstab*) {
    return false;
}

bool fs_mgr_overlayfs_setup(const char*, const char*, bool* change, bool) {
bool fs_mgr_overlayfs_setup(const char*, bool* change, bool) {
    if (change) *change = false;
    return false;
}
@@ -370,28 +370,6 @@ bool fs_mgr_rw_access(const std::string& path) {
    return ret;
}

bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true) {
    Fstab fstab;
    auto save_errno = errno;
    if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
        return false;
    }
    errno = save_errno;
    const auto lowerdir = kLowerdirOption + mount_point;
    for (const auto& entry : fstab) {
        if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
        if (mount_point != entry.mount_point) continue;
        if (!overlay_only) return true;
        const auto options = android::base::Split(entry.fs_options, ",");
        for (const auto& opt : options) {
            if (opt == lowerdir) {
                return true;
            }
        }
    }
    return false;
}

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

bool fs_mgr_overlayfs_setup_dir(const std::string& dir, std::string* overlay, bool* change) {
@@ -1290,8 +1268,23 @@ bool fs_mgr_wants_overlayfs(FstabEntry* entry) {
}

Fstab fs_mgr_overlayfs_candidate_list(const Fstab& fstab) {
    android::fs_mgr::Fstab mounts;
    if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
        PLOG(ERROR) << "Failed to read /proc/mounts";
        return {};
    }

    Fstab candidates;
    for (const auto& entry : fstab) {
        // Filter out partitions whose type doesn't match what's mounted.
        // This avoids spammy behavior on devices which can mount different
        // filesystems for each partition.
        auto proc_mount_point = (entry.mount_point == "/system") ? "/" : entry.mount_point;
        auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
        if (!mounted || mounted->fs_type != entry.fs_type) {
            continue;
        }

        FstabEntry new_entry = entry;
        if (!fs_mgr_overlayfs_already_mounted(entry.mount_point) &&
            !fs_mgr_wants_overlayfs(&new_entry)) {
@@ -1364,8 +1357,7 @@ bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {

// Returns false if setup not permitted, errno set to last error.
// If something is altered, set *change.
bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool* change,
                            bool force) {
bool fs_mgr_overlayfs_setup(const char* mount_point, bool* change, bool force) {
    if (change) *change = false;
    auto ret = false;
    if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return ret;
@@ -1402,7 +1394,6 @@ bool fs_mgr_overlayfs_setup(const char* backing, const char* mount_point, bool*

    std::string dir;
    for (const auto& overlay_mount_point : OverlayMountPoints()) {
        if (backing && backing[0] && (overlay_mount_point != backing)) continue;
        if (overlay_mount_point == kScratchMountPoint) {
            if (!fs_mgr_overlayfs_setup_scratch(fstab, change)) continue;
        } else {
@@ -1698,6 +1689,28 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) {

#endif  // ALLOW_ADBD_DISABLE_VERITY != 0

bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
    Fstab fstab;
    auto save_errno = errno;
    if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
        return false;
    }
    errno = save_errno;
    const auto lowerdir = kLowerdirOption + mount_point;
    for (const auto& entry : fstab) {
        if (overlay_only && "overlay" != entry.fs_type && "overlayfs" != entry.fs_type) continue;
        if (mount_point != entry.mount_point) continue;
        if (!overlay_only) return true;
        const auto options = android::base::Split(entry.fs_options, ",");
        for (const auto& opt : options) {
            if (opt == lowerdir) {
                return true;
            }
        }
    }
    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) ||
+114 −102
Original line number Diff line number Diff line
@@ -91,12 +91,8 @@ void MyLogger(android::base::LogId id, android::base::LogSeverity severity, cons
    logd(id, severity, tag, file, line, message);
}

[[noreturn]] void reboot(bool overlayfs = false) {
    if (overlayfs) {
        LOG(INFO) << "Successfully setup overlayfs\nrebooting device";
    } else {
        LOG(INFO) << "Successfully disabled verity\nrebooting device";
    }
[[noreturn]] void reboot() {
    LOG(INFO) << "Rebooting device for new settings to take effect";
    ::sync();
    android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,remount");
    ::sleep(60);
@@ -136,7 +132,6 @@ enum RemountStatus {
    BINDER_ERROR,
    CHECKPOINTING,
    GSID_ERROR,
    CLEAN_SCRATCH_FILES,
};

static bool ReadFstab(const char* fstab_file, android::fs_mgr::Fstab* fstab) {
@@ -191,8 +186,8 @@ static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
    if (entry.fs_type == "vfat") {
        return false;
    }
    if (GetEntryForMountPoint(&candidates, entry.mount_point)) {
        return true;
    if (auto candidate_entry = GetEntryForMountPoint(&candidates, entry.mount_point)) {
        return candidate_entry->fs_type == entry.fs_type;
    }
    if (GetWrappedEntry(candidates, entry)) {
        return false;
@@ -201,13 +196,22 @@ static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
}

static Fstab::const_iterator FindPartition(const Fstab& fstab, const std::string& partition) {
    Fstab mounts;
    if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts)) {
        LOG(ERROR) << "Failed to read /proc/mounts";
        return fstab.end();
    }

    for (auto iter = fstab.begin(); iter != fstab.end(); iter++) {
        const auto mount_point = system_mount_point(*iter);
        if (partition == mount_point) {
        if (partition == mount_point || partition == android::base::Basename(mount_point)) {
            // In case fstab has multiple entries, pick the one that matches the
            // actual mounted filesystem type.
            auto proc_mount_point = (iter->mount_point == "/system") ? "/" : iter->mount_point;
            auto mounted = GetEntryForMountPoint(&mounts, proc_mount_point);
            if (mounted && mounted->fs_type == iter->fs_type) {
                return iter;
            }
        if (partition == android::base::Basename(mount_point)) {
            return iter;
        }
    }
    return fstab.end();
@@ -248,7 +252,10 @@ static RemountStatus GetRemountList(const Fstab& fstab, const std::vector<std::s
            entry = wrap;
        }

        if (!IsRemountable(candidates, *entry)) {
        // If it's already remounted, include it so it gets gracefully skipped
        // later on.
        if (!fs_mgr_overlayfs_already_mounted(entry->mount_point) &&
            !IsRemountable(candidates, *entry)) {
            LOG(ERROR) << "Invalid partition " << arg;
            return INVALID_PARTITION;
        }
@@ -266,6 +273,7 @@ struct RemountCheckResult {
    bool setup_overlayfs = false;
    bool disabled_verity = false;
    bool verity_error = false;
    bool remounted_anything = false;
};

static RemountStatus CheckVerity(const FstabEntry& entry, RemountCheckResult* result) {
@@ -312,7 +320,7 @@ static RemountStatus CheckVerityAndOverlayfs(Fstab* partitions, RemountCheckResu
        if (fs_mgr_wants_overlayfs(&entry)) {
            bool change = false;
            bool force = result->disabled_verity;
            if (!fs_mgr_overlayfs_setup(nullptr, mount_point.c_str(), &change, force)) {
            if (!fs_mgr_overlayfs_setup(mount_point.c_str(), &change, force)) {
                LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
                status = BAD_OVERLAY;
                it = partitions->erase(it);
@@ -422,7 +430,69 @@ static RemountStatus RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& e
    return REMOUNT_FAILED;
}

static int do_remount(int argc, char* argv[]) {
static int do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
                      RemountCheckResult* check_result) {
    Fstab partitions;
    if (partition_args.empty()) {
        partitions = GetAllRemountablePartitions(fstab);
    } else {
        if (auto rv = GetRemountList(fstab, partition_args, &partitions); rv != REMOUNT_SUCCESS) {
            return rv;
        }
    }

    // Check verity and optionally setup overlayfs backing.
    auto retval = CheckVerityAndOverlayfs(&partitions, check_result);

    if (partitions.empty() || check_result->disabled_verity) {
        if (partitions.empty()) {
            LOG(WARNING) << "No remountable partitions were found.";
        }
        return retval;
    }

    // Mount overlayfs.
    errno = 0;
    if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
        PLOG(ERROR) << "Can not mount overlayfs for partitions";
        return BAD_OVERLAY;
    }

    // Get actual mounts _after_ overlayfs has been added.
    android::fs_mgr::Fstab mounts;
    if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
        PLOG(ERROR) << "Failed to read /proc/mounts";
        return NO_MOUNTS;
    }

    // Remount selected partitions.
    for (auto& entry : partitions) {
        if (auto rv = RemountPartition(fstab, mounts, entry); rv != REMOUNT_SUCCESS) {
            retval = rv;
        } else {
            check_result->remounted_anything = true;
        }
    }
    return retval;
}

static int do_clean_scratch_files() {
    android::fs_mgr::CleanupOldScratchFiles();
    return 0;
}

int main(int argc, char* argv[]) {
    android::base::InitLogging(argv, MyLogger);
    if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
        return do_clean_scratch_files();
    }

    // Make sure we are root.
    if (::getuid() != 0) {
        LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
        return NOT_ROOT;
    }

    // If somehow this executable is delivered on a "user" build, it can
    // not function, so providing a clear message to the caller rather than
    // letting if fall through and provide a lot of confusing failure messages.
@@ -432,7 +502,7 @@ static int do_remount(int argc, char* argv[]) {
    }

    const char* fstab_file = nullptr;
    auto can_reboot = false;
    auto auto_reboot = false;
    std::vector<std::string> partition_args;

    struct option longopts[] = {
@@ -449,7 +519,7 @@ static int do_remount(int argc, char* argv[]) {
                usage(SUCCESS);
                break;
            case 'R':
                can_reboot = true;
                auto_reboot = true;
                break;
            case 'T':
                if (fstab_file) {
@@ -462,7 +532,7 @@ static int do_remount(int argc, char* argv[]) {
                verbose = true;
                break;
            case 'C':
                return CLEAN_SCRATCH_FILES;
                return do_clean_scratch_files();
            default:
                LOG(ERROR) << "Bad Argument -" << char(opt);
                usage(BADARG);
@@ -474,10 +544,9 @@ static int do_remount(int argc, char* argv[]) {
        partition_args.emplace_back(argv[optind]);
    }

    // Make sure we are root.
    if (::getuid() != 0) {
        LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
        return NOT_ROOT;
    // Make sure checkpointing is disabled if necessary.
    if (auto rv = VerifyCheckpointing(); rv != REMOUNT_SUCCESS) {
        return rv;
    }

    // Read the selected fstab.
@@ -487,92 +556,35 @@ static int do_remount(int argc, char* argv[]) {
        return NO_FSTAB;
    }

    if (auto rv = VerifyCheckpointing(); rv != REMOUNT_SUCCESS) {
        return rv;
    }

    Fstab partitions;
    if (partition_args.empty()) {
        partitions = GetAllRemountablePartitions(fstab);
    } else {
        if (auto rv = GetRemountList(fstab, partition_args, &partitions); rv != REMOUNT_SUCCESS) {
            return rv;
        }
    }

    // Check verity and optionally setup overlayfs backing.
    RemountCheckResult check_result;
    auto retval = CheckVerityAndOverlayfs(&partitions, &check_result);
    int result = do_remount(fstab, partition_args, &check_result);

    bool auto_reboot = check_result.reboot_later && can_reboot;
    if (check_result.disabled_verity && check_result.setup_overlayfs) {
        LOG(INFO) << "Verity disabled; overlayfs enabled.";
    } else if (check_result.disabled_verity) {
        LOG(INFO) << "Verity disabled.";
    } else if (check_result.setup_overlayfs) {
        LOG(INFO) << "Overlayfs enabled.";
    }

    if (check_result.reboot_later) {
        if (auto_reboot) {
            // If (1) remount requires a reboot to take effect, (2) system is currently
            // running a DSU guest and (3) DSU is disabled, then enable DSU so that the
            // next reboot would not take us back to the host system but stay within
            // the guest system.
    if (auto_reboot) {
            if (auto rv = EnableDsuIfNeeded(); rv != REMOUNT_SUCCESS) {
                LOG(ERROR) << "Unable to automatically enable DSU";
                return rv;
            }
    }

    if (partitions.empty() || check_result.disabled_verity) {
        if (auto_reboot) {
            reboot(check_result.setup_overlayfs);
        }
        if (check_result.reboot_later) {
            return MUST_REBOOT;
        }
        LOG(WARNING) << "No partitions to remount";
        return retval;
    }

    // Mount overlayfs.
    errno = 0;
    if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
        PLOG(ERROR) << "Can not mount overlayfs for partitions";
        return BAD_OVERLAY;
    }

    // Get actual mounts _after_ overlayfs has been added.
    android::fs_mgr::Fstab mounts;
    if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
        PLOG(ERROR) << "Failed to read /proc/mounts";
        return NO_MOUNTS;
    }

    // Remount selected partitions.
    for (auto& entry : partitions) {
        if (auto rv = RemountPartition(fstab, mounts, entry); rv != REMOUNT_SUCCESS) {
            retval = rv;
        }
    }

    if (auto_reboot) reboot(check_result.setup_overlayfs);
    if (check_result.reboot_later) {
            reboot();
        } else {
            LOG(INFO) << "Now reboot your device for settings to take effect";
        }
    return retval;
}

static int do_clean_scratch_files() {
    android::fs_mgr::CleanupOldScratchFiles();
    return 0;
}

int main(int argc, char* argv[]) {
    android::base::InitLogging(argv, MyLogger);
    if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
        return do_clean_scratch_files();
        return MUST_REBOOT;
    }
    int result = do_remount(argc, argv);
    if (result == MUST_REBOOT) {
        LOG(INFO) << "Now reboot your device for settings to take effect";
        result = 0;
    } else if (result == REMOUNT_SUCCESS) {
    if (result == REMOUNT_SUCCESS) {
        printf("remount succeeded\n");
    } else if (result == CLEAN_SCRATCH_FILES) {
        return do_clean_scratch_files();
    } else {
        printf("remount failed\n");
    }
+3 −2
Original line number Diff line number Diff line
@@ -28,11 +28,12 @@ android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fs

bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
bool fs_mgr_overlayfs_setup(const char* backing = nullptr, const char* mount_point = nullptr,
                            bool* change = nullptr, bool force = true);
bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* change = nullptr,
                            bool force = true);
bool fs_mgr_overlayfs_teardown(const char* mount_point = nullptr, bool* change = nullptr);
bool fs_mgr_overlayfs_is_setup();
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
std::string fs_mgr_get_context(const std::string& mount_point);

enum class OverlayfsValidResult {
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ bool overlayfs_setup(bool enable) {
  auto change = false;
  errno = 0;
  if (enable ? fs_mgr_overlayfs_teardown(nullptr, &change)
             : fs_mgr_overlayfs_setup(nullptr, nullptr, &change)) {
             : fs_mgr_overlayfs_setup(nullptr, &change)) {
    if (change) {
      LOG(INFO) << (enable ? "disabling" : "using") << " overlayfs";
    }