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

Commit a056eca5 authored by David Anderson's avatar David Anderson
Browse files

snapuserd: Add a no-socket mode.

In first-stage init, during the selinux transition, no socket is needed.
It's even advantageous not to create one, since it greatly reduces the
amount of avc audits. This patch allows starting snapuserd with a preset
list of socket commands that it can run on startup.

Bug: 173476209
Test: manual test
Change-Id: I758d99097372e4dffb252e2836fd859b7fed162a
parent 4e67f589
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -17,23 +17,44 @@
#include "snapuserd_daemon.h"

#include <android-base/logging.h>
#include <android-base/strings.h>
#include <gflags/gflags.h>
#include <libsnapshot/snapuserd_client.h>

#include "snapuserd_server.h"

DEFINE_string(socket, android::snapshot::kSnapuserdSocket, "Named socket or socket path.");
DEFINE_bool(no_socket, false,
            "If true, no socket is used. Each additional argument is an INIT message.");

namespace android {
namespace snapshot {

void Daemon::StartServer() {
    if (!server_.Start(FLAGS_socket)) {
        LOG(ERROR) << "Snapuserd daemon failed to start...";
        exit(EXIT_FAILURE);
bool Daemon::StartServer(int argc, char** argv) {
    int arg_start = gflags::ParseCommandLineFlags(&argc, &argv, true);

    if (!FLAGS_no_socket) {
        return server_.Start(FLAGS_socket);
    }

    for (int i = arg_start; i < argc; i++) {
        auto parts = android::base::Split(argv[i], ",");
        if (parts.size() != 3) {
            LOG(ERROR) << "Malformed message, expected three sub-arguments.";
            return false;
        }
        auto handler = server_.AddHandler(parts[0], parts[1], parts[2]);
        if (!handler || !server_.StartHandler(handler)) {
            return false;
        }
    }

    // Skip the accept() call to avoid spurious log spam. The server will still
    // run until all handlers have completed.
    server_.SetTerminating();
    return true;
}

void Daemon::MaskAllSignalsExceptIntAndTerm() {
    sigset_t signal_mask;
    sigfillset(&signal_mask);
@@ -96,14 +117,15 @@ void Daemon::SignalHandler(int signal) {
}  // namespace snapshot
}  // namespace android

int main([[maybe_unused]] int argc, char** argv) {
int main(int argc, char** argv) {
    android::base::InitLogging(argv, &android::base::KernelLogger);

    android::snapshot::Daemon& daemon = android::snapshot::Daemon::Instance();

    gflags::ParseCommandLineFlags(&argc, &argv, false);

    daemon.StartServer();
    if (!daemon.StartServer(argc, argv)) {
        LOG(ERROR) << "Snapuserd daemon failed to start.";
        exit(EXIT_FAILURE);
    }
    daemon.Run();

    return 0;
+4 −1
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

#include <poll.h>

#include <string>
#include <vector>

#include "snapuserd_server.h"

namespace android {
@@ -32,7 +35,7 @@ class Daemon {
        return instance;
    }

    void StartServer();
    bool StartServer(int argc, char** argv);
    void Run();
    void Interrupt();

+38 −19
Original line number Diff line number Diff line
@@ -116,7 +116,7 @@ bool SnapuserdServer::Receivemsg(android::base::borrowed_fd fd, const std::strin
    switch (op) {
        case DaemonOperations::INIT: {
            // Message format:
            // init,<misc_name>,<cow_device_path>,<control_device>
            // init,<misc_name>,<cow_device_path>,<backing_device>
            //
            // Reads the metadata and send the number of sectors
            if (out.size() != 4) {
@@ -124,24 +124,12 @@ bool SnapuserdServer::Receivemsg(android::base::borrowed_fd fd, const std::strin
                return Sendmsg(fd, "fail");
            }

            auto snapuserd = std::make_unique<Snapuserd>(out[1], out[2], out[3]);
            if (!snapuserd->InitCowDevice()) {
                LOG(ERROR) << "Failed to initialize Snapuserd";
            auto handler = AddHandler(out[1], out[2], out[3]);
            if (!handler) {
                return Sendmsg(fd, "fail");
            }

            std::string retval = "success," + std::to_string(snapuserd->GetNumSectors());

            auto handler = std::make_unique<DmUserHandler>(std::move(snapuserd));
            {
                std::lock_guard<std::mutex> lock(lock_);
                if (FindHandler(&lock, out[1]) != dm_users_.end()) {
                    LOG(ERROR) << "Handler already exists: " << out[1];
                    return Sendmsg(fd, "fail");
                }
                dm_users_.push_back(std::move(handler));
            }

            auto retval = "success," + std::to_string(handler->snapuserd()->GetNumSectors());
            return Sendmsg(fd, retval);
        }
        case DaemonOperations::START: {
@@ -164,11 +152,9 @@ bool SnapuserdServer::Receivemsg(android::base::borrowed_fd fd, const std::strin
                LOG(ERROR) << "Tried to re-attach control device: " << out[1];
                return Sendmsg(fd, "fail");
            }
            if (!((*iter)->snapuserd()->InitBackingAndControlDevice())) {
                LOG(ERROR) << "Failed to initialize control device: " << out[1];
            if (!StartHandler(*iter)) {
                return Sendmsg(fd, "fail");
            }
            (*iter)->thread() = std::thread(std::bind(&SnapuserdServer::RunThread, this, *iter));
            return Sendmsg(fd, "success");
        }
        case DaemonOperations::STOP: {
@@ -340,6 +326,39 @@ void SnapuserdServer::Interrupt() {
    SetTerminating();
}

std::shared_ptr<DmUserHandler> SnapuserdServer::AddHandler(const std::string& misc_name,
                                                           const std::string& cow_device_path,
                                                           const std::string& backing_device) {
    auto snapuserd = std::make_unique<Snapuserd>(misc_name, cow_device_path, backing_device);
    if (!snapuserd->InitCowDevice()) {
        LOG(ERROR) << "Failed to initialize Snapuserd";
        return nullptr;
    }

    auto handler = std::make_shared<DmUserHandler>(std::move(snapuserd));
    {
        std::lock_guard<std::mutex> lock(lock_);
        if (FindHandler(&lock, misc_name) != dm_users_.end()) {
            LOG(ERROR) << "Handler already exists: " << misc_name;
            return nullptr;
        }
        dm_users_.push_back(handler);
    }
    return handler;
}

bool SnapuserdServer::StartHandler(const std::shared_ptr<DmUserHandler>& handler) {
    CHECK(!handler->snapuserd()->IsAttached());

    if (!handler->snapuserd()->InitBackingAndControlDevice()) {
        LOG(ERROR) << "Failed to initialize control device: " << handler->GetMiscName();
        return false;
    }

    handler->thread() = std::thread(std::bind(&SnapuserdServer::RunThread, this, handler));
    return true;
}

auto SnapuserdServer::FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
                                  const std::string& misc_name) -> HandlerList::iterator {
    CHECK(proof_of_lock);
+7 −1
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ class SnapuserdServer : public Stoppable {
    std::string GetDaemonStatus();
    void Parsemsg(std::string const& msg, const char delim, std::vector<std::string>& out);

    void SetTerminating() { terminating_ = true; }
    bool IsTerminating() { return terminating_; }

    void RunThread(std::shared_ptr<DmUserHandler> handler);
@@ -120,6 +119,13 @@ class SnapuserdServer : public Stoppable {
    bool Start(const std::string& socketname);
    bool Run();
    void Interrupt();

    std::shared_ptr<DmUserHandler> AddHandler(const std::string& misc_name,
                                              const std::string& cow_device_path,
                                              const std::string& backing_device);
    bool StartHandler(const std::shared_ptr<DmUserHandler>& handler);

    void SetTerminating() { terminating_ = true; }
};

}  // namespace snapshot