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

Commit b5402e7e authored by Paul Lawrence's avatar Paul Lawrence Committed by Gerrit Code Review
Browse files

Merge "Replace use of overlayfs' override_creds with overlay_remounter" into main

parents 20e20881 6bb52890
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2335,6 +2335,11 @@ OverlayfsCheckResult CheckOverlayfs() {
    if (!fs_mgr_filesystem_available("overlay")) {
        return {.supported = false};
    }

    if (!use_override_creds) {
        return {.supported = true};
    }

    struct utsname uts;
    if (uname(&uts) == -1) {
        return {.supported = false};
+6 −0
Original line number Diff line number Diff line
@@ -43,5 +43,11 @@ void MapScratchPartitionIfNeeded(Fstab* fstab,
// overlays if any partition is flashed or updated.
void TeardownAllOverlayForMountPoint(const std::string& mount_point = {});

// Are we using overlayfs's non-upstreamed override_creds feature?
// b/388912628 removes the need for override_creds
// Once this bug is fixed and has had enough soak time, remove this variable and hard code to false
// where it used
constexpr bool use_override_creds = true;

}  // namespace fs_mgr
}  // namespace android
+6 −1
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ libinit_cc_defaults {
                "-DWORLD_WRITABLE_KMSG=1",
                "-UDUMP_ON_UMOUNT_FAILURE",
                "-DDUMP_ON_UMOUNT_FAILURE=1",
                "-UALLOW_REMOUNT_OVERLAYS",
                "-DALLOW_REMOUNT_OVERLAYS=1",
            ],
        },
        eng: {
@@ -263,7 +265,10 @@ phony {
    name: "init",
    required: [
        "init_second_stage",
    ],
    ] + select(product_variable("debuggable"), {
        true: ["overlay_remounter"],
        false: [],
    }),
}

cc_defaults {
+1 −1
Original line number Diff line number Diff line
@@ -402,7 +402,7 @@ int FirstStageMain(int argc, char** argv) {

    // /second_stage_resources is used to preserve files from first to second
    // stage init
    CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
    CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOSUID | MS_NODEV,
                    "mode=0755,uid=0,gid=0"));

    if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+65 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
#include <android/avf_cc_flags.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr.h>
#include <fs_mgr_overlayfs.h>
#include <genfslabelsversion.h>
#include <libgsi/libgsi.h>
#include <libsnapshot/snapshot.h>
@@ -77,6 +78,7 @@
#include "block_dev_initializer.h"
#include "debug_ramdisk.h"
#include "reboot_utils.h"
#include "second_stage_resources.h"
#include "snapuserd_transition.h"
#include "util.h"

@@ -698,6 +700,65 @@ void LoadSelinuxPolicyAndroid() {
    }
}

#ifdef ALLOW_REMOUNT_OVERLAYS
void SetupOverlays() {
    if (android::fs_mgr::use_override_creds) return;

    bool has_overlays = false;
    std::string contents;
    auto result = android::base::ReadFileToString("/proc/mounts", &contents, true);

    auto lines = android::base::Split(contents, "\n");
    for (auto const& line : lines)
        if (android::base::StartsWith(line, "overlay")) {
            has_overlays = true;
            break;
        }

    if (!has_overlays) return;

    // After adb remount, we mount all r/o volumes with overlayfs to allow writing.
    // However, since overlayfs performs its file operations in the context of the
    // mounting process, this will not work as is - init is in the kernel domain in
    // first stage, which has very limited permissions.

    // In order to fix this, we need to unmount remount all these volumes from a process
    // with sufficient privileges to be able to perform these operations. The
    // overlay_remounter domain has those privileges on debuggable devices.
    // We will call overlay_remounter which will do the unmounts/mounts.
    // But for that to work, the volumes must not be busy, so we need to copy
    // overlay_remounter from system to a ramdisk and run it from there.

    const char* kOverlayRemounter = "overlay_remounter";
    auto or_src = std::filesystem::path("/system/xbin/") / kOverlayRemounter;
    auto or_dest = std::filesystem::path(kSecondStageRes) / kOverlayRemounter;
    std::error_code ec;
    std::filesystem::copy(or_src, or_dest, ec);
    if (ec) {
        LOG(FATAL) << "Failed to copy " << or_src << " to " << or_dest << " " << ec.message();
    }

    if (selinux_android_restorecon(or_dest.c_str(), 0) == -1) {
        PLOG(FATAL) << "restorecon of " << or_dest << " failed";
    }
    auto dest = unique_fd(open(or_dest.c_str(), O_RDONLY | O_CLOEXEC));
    if (dest.get() == -1) {
        PLOG(FATAL) << "Failed to reopen " << or_dest;
    }
    if (unlink(or_dest.c_str()) == -1) {
        PLOG(FATAL) << "Failed to unlink " << or_dest;
    }
    const char* args[] = {or_dest.c_str(), nullptr};
    fexecve(dest.get(), const_cast<char**>(args), nullptr);

    // execv() only returns if an error happened, in which case we
    // panic and never return from this function.
    PLOG(FATAL) << "execv(\"" << or_dest << "\") failed";
}
#else
void SetupOverlays() {}
#endif

int SetupSelinux(char** argv) {
    SetStdioToDevNull(argv);
    InitKernelLogging(argv);
@@ -738,6 +799,10 @@ int SetupSelinux(char** argv) {

    setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);

    // SetupOverlays does not return if overlays exist, instead it execs overlay_remounter
    // which then execs second stage init
    SetupOverlays();

    const char* path = "/system/bin/init";
    const char* args[] = {path, "second_stage", nullptr};
    execv(path, const_cast<char**>(args));
Loading