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

Commit 286c1d58 authored by Akilesh Kailash's avatar Akilesh Kailash Committed by Gerrit Code Review
Browse files

Merge "init: Wait for snapuserd before starting second stage"

parents d950242c fd5562b0
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -599,8 +599,13 @@ bool UserSnapshotServer::WaitForSocket() {
        return false;
    }

    // We must re-initialize property service access, since we launched before
    // second-stage init.
    // This initialization of system property is important. When daemon is
    // launched post selinux transition (before init second stage),
    // bionic libc initializes system property as part of __libc_init_common();
    // however that initialization fails silently given that fact that we don't
    // have /dev/__properties__ setup which is created at init second stage.
    //
    // At this point, we have the handlers setup and is safe to setup property.
    __system_properties_init();

    if (!android::base::WaitForProperty("snapuserd.proxy_ready", "true")) {
+58 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/sockets.h>
#include <fs_avb/fs_avb.h>
#include <libsnapshot/snapshot.h>
#include <private/android_filesystem_config.h>
#include <procinfo/process_map.h>
@@ -247,6 +248,56 @@ void SnapuserdSelinuxHelper::FinishTransition() {
    }
}

/*
 * Before starting init second stage, we will wait
 * for snapuserd daemon to be up and running; bionic libc
 * may read /system/etc/selinux/plat_property_contexts file
 * before invoking main() function. This will happen if
 * init initializes property during second stage. Any access
 * to /system without snapuserd daemon will lead to a deadlock.
 *
 * Thus, we do a simple probe by reading system partition. This
 * read will eventually be serviced by daemon confirming that
 * daemon is up and running. Furthermore, we are still in the kernel
 * domain and sepolicy has not been enforced yet. Thus, access
 * to these device mapper block devices are ok even though
 * we may see audit logs.
 */
bool SnapuserdSelinuxHelper::TestSnapuserdIsReady() {
    std::string dev = "/dev/block/mapper/system"s + fs_mgr_get_slot_suffix();
    android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_DIRECT));
    if (fd < 0) {
        PLOG(ERROR) << "open " << dev << " failed";
        return false;
    }

    void* addr;
    ssize_t page_size = getpagesize();
    if (posix_memalign(&addr, page_size, page_size) < 0) {
        PLOG(ERROR) << "posix_memalign with page size " << page_size;
        return false;
    }

    std::unique_ptr<void, decltype(&::free)> buffer(addr, ::free);

    int iter = 0;
    while (iter < 10) {
        ssize_t n = TEMP_FAILURE_RETRY(pread(fd.get(), buffer.get(), page_size, 0));
        if (n < 0) {
            // Wait for sometime before retry
            std::this_thread::sleep_for(100ms);
        } else if (n == page_size) {
            return true;
        } else {
            LOG(ERROR) << "pread returned: " << n << " from: " << dev << " expected: " << page_size;
        }

        iter += 1;
    }

    return false;
}

void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() {
    auto fd = GetRamdiskSnapuserdFd();
    if (!fd) {
@@ -268,6 +319,13 @@ void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() {
        setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1);

        LOG(INFO) << "Relaunched snapuserd with pid: " << pid;

        if (!TestSnapuserdIsReady()) {
            PLOG(FATAL) << "snapuserd daemon failed to launch";
        } else {
            LOG(INFO) << "snapuserd daemon is up and running";
        }

        return;
    }

+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ class SnapuserdSelinuxHelper final {
  private:
    void RelaunchFirstStageSnapuserd();
    void ExecSnapuserd();
    bool TestSnapuserdIsReady();

    std::unique_ptr<SnapshotManager> sm_;
    BlockDevInitializer block_dev_init_;