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

Commit f4514262 authored by Tom Cherry's avatar Tom Cherry
Browse files

Revert "init: run property service in a thread"

This reverts commit 26f5e7da.

Reason for revert: bluecross boot stability issue

Bug: 140009641
Change-Id: I7ddb9509dfb2c6f644037129aa9d3fb9ff1740aa
parent 26f5e7da
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -128,7 +128,6 @@ cc_library_static {
        "persistent_properties.cpp",
        "persistent_properties.cpp",
        "persistent_properties.proto",
        "persistent_properties.proto",
        "property_service.cpp",
        "property_service.cpp",
        "property_service.proto",
        "property_type.cpp",
        "property_type.cpp",
        "reboot.cpp",
        "reboot.cpp",
        "reboot_utils.cpp",
        "reboot_utils.cpp",
+1 −24
Original line number Original line Diff line number Diff line
@@ -80,7 +80,6 @@
using namespace std::literals::string_literals;
using namespace std::literals::string_literals;


using android::base::Basename;
using android::base::Basename;
using android::base::StartsWith;
using android::base::unique_fd;
using android::base::unique_fd;
using android::fs_mgr::Fstab;
using android::fs_mgr::Fstab;
using android::fs_mgr::ReadFstabFromFile;
using android::fs_mgr::ReadFstabFromFile;
@@ -688,15 +687,6 @@ static Result<void> do_swapon_all(const BuiltinArguments& args) {
}
}


static Result<void> do_setprop(const BuiltinArguments& args) {
static Result<void> do_setprop(const BuiltinArguments& args) {
    if (StartsWith(args[1], "ctl.")) {
        return Error()
               << "Cannot set ctl. properties from init; call the Service functions directly";
    }
    if (args[1] == kRestoreconProperty) {
        return Error() << "Cannot set '" << kRestoreconProperty
                       << "' from init; use the restorecon builtin directly";
    }

    property_set(args[1], args[2]);
    property_set(args[1], args[2]);
    return {};
    return {};
}
}
@@ -1012,20 +1002,7 @@ static Result<void> do_loglevel(const BuiltinArguments& args) {
}
}


static Result<void> do_load_persist_props(const BuiltinArguments& args) {
static Result<void> do_load_persist_props(const BuiltinArguments& args) {
    // Devices with FDE have load_persist_props called twice; the first time when the temporary
    load_persist_props();
    // /data partition is mounted and then again once /data is truly mounted.  We do not want to
    // read persistent properties from the temporary /data partition or mark persistent properties
    // as having been loaded during the first call, so we return in that case.
    std::string crypto_state = android::base::GetProperty("ro.crypto.state", "");
    std::string crypto_type = android::base::GetProperty("ro.crypto.type", "");
    if (crypto_state == "encrypted" && crypto_type == "block") {
        static size_t num_calls = 0;
        if (++num_calls == 1) return {};
    }

    SendLoadPersistentPropertiesMessage();

    start_waiting_for_property("ro.persistent_properties.ready", "true");
    return {};
    return {};
}
}


+1 −57
Original line number Original line Diff line number Diff line
@@ -61,7 +61,6 @@
#include "mount_handler.h"
#include "mount_handler.h"
#include "mount_namespace.h"
#include "mount_namespace.h"
#include "property_service.h"
#include "property_service.h"
#include "proto_utils.h"
#include "reboot.h"
#include "reboot.h"
#include "reboot_utils.h"
#include "reboot_utils.h"
#include "security.h"
#include "security.h"
@@ -70,7 +69,6 @@
#include "service.h"
#include "service.h"
#include "service_parser.h"
#include "service_parser.h"
#include "sigchld_handler.h"
#include "sigchld_handler.h"
#include "system/core/init/property_service.pb.h"
#include "util.h"
#include "util.h"


using namespace std::chrono_literals;
using namespace std::chrono_literals;
@@ -92,7 +90,6 @@ static int property_triggers_enabled = 0;
static char qemu[32];
static char qemu[32];


static int signal_fd = -1;
static int signal_fd = -1;
static int property_fd = -1;


static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::string wait_prop_name;
static std::string wait_prop_name;
@@ -616,54 +613,6 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star
                                selinux_start_time_ns));
                                selinux_start_time_ns));
}
}


void SendLoadPersistentPropertiesMessage() {
    auto init_message = InitMessage{};
    init_message.set_load_persistent_properties(true);
    if (auto result = SendMessage(property_fd, init_message); !result) {
        LOG(ERROR) << "Failed to send load persistent properties message: " << result.error();
    }
}

static void HandlePropertyFd() {
    auto message = ReadMessage(property_fd);
    if (!message) {
        LOG(ERROR) << "Could not read message from property service: " << message.error();
        return;
    }

    auto property_message = PropertyMessage{};
    if (!property_message.ParseFromString(*message)) {
        LOG(ERROR) << "Could not parse message from property service";
        return;
    }

    switch (property_message.msg_case()) {
        case PropertyMessage::kControlMessage: {
            auto& control_message = property_message.control_message();
            bool response = HandleControlMessage(control_message.msg(), control_message.name(),
                                                 control_message.pid());

            auto init_message = InitMessage{};
            auto* control_response = init_message.mutable_control_response();

            control_response->set_result(response);

            if (auto result = SendMessage(property_fd, init_message); !result) {
                LOG(ERROR) << "Failed to send control response: " << result.error();
            }
            break;
        }
        case PropertyMessage::kChangedMessage: {
            auto& changed_message = property_message.changed_message();
            property_changed(changed_message.name(), changed_message.value());
            break;
        }
        default:
            LOG(ERROR) << "Unknown message type from property service: "
                       << property_message.msg_case();
    }
}

int SecondStageMain(int argc, char** argv) {
int SecondStageMain(int argc, char** argv) {
    if (REBOOT_BOOTLOADER_ON_PANIC) {
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
        InstallRebootSignalHandlers();
@@ -735,12 +684,7 @@ int SecondStageMain(int argc, char** argv) {
    UmountDebugRamdisk();
    UmountDebugRamdisk();
    fs_mgr_vendor_overlay_mount_all();
    fs_mgr_vendor_overlay_mount_all();
    export_oem_lock_status();
    export_oem_lock_status();

    StartPropertyService(&epoll);
    StartPropertyService(&property_fd);
    if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) {
        LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
    }

    MountHandler mount_handler(&epoll);
    MountHandler mount_handler(&epoll);
    set_usb_controller();
    set_usb_controller();


+4 −2
Original line number Original line Diff line number Diff line
@@ -31,14 +31,16 @@ namespace init {
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
Parser CreateServiceOnlyParser(ServiceList& service_list);
Parser CreateServiceOnlyParser(ServiceList& service_list);


bool HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid);

void property_changed(const std::string& name, const std::string& value);

bool start_waiting_for_property(const char *name, const char *value);
bool start_waiting_for_property(const char *name, const char *value);


void DumpState();
void DumpState();


void ResetWaitForProp();
void ResetWaitForProp();


void SendLoadPersistentPropertiesMessage();

int SecondStageMain(int argc, char** argv);
int SecondStageMain(int argc, char** argv);


}  // namespace init
}  // namespace init
+57 −160
Original line number Original line Diff line number Diff line
@@ -42,7 +42,6 @@
#include <map>
#include <map>
#include <memory>
#include <memory>
#include <mutex>
#include <mutex>
#include <optional>
#include <queue>
#include <queue>
#include <thread>
#include <thread>
#include <vector>
#include <vector>
@@ -64,10 +63,8 @@
#include "init.h"
#include "init.h"
#include "persistent_properties.h"
#include "persistent_properties.h"
#include "property_type.h"
#include "property_type.h"
#include "proto_utils.h"
#include "selinux.h"
#include "selinux.h"
#include "subcontext.h"
#include "subcontext.h"
#include "system/core/init/property_service.pb.h"
#include "util.h"
#include "util.h"


using namespace std::literals;
using namespace std::literals;
@@ -79,7 +76,6 @@ using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::StringPrintf;
using android::base::Timer;
using android::base::Timer;
using android::base::Trim;
using android::base::Trim;
using android::base::unique_fd;
using android::base::WriteStringToFile;
using android::base::WriteStringToFile;
using android::properties::BuildTrie;
using android::properties::BuildTrie;
using android::properties::ParsePropertyInfoFile;
using android::properties::ParsePropertyInfoFile;
@@ -89,15 +85,14 @@ using android::properties::PropertyInfoEntry;
namespace android {
namespace android {
namespace init {
namespace init {


static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive";

static bool persistent_properties_loaded = false;
static bool persistent_properties_loaded = false;


static int property_set_fd = -1;
static int property_set_fd = -1;
static int init_socket = -1;


static PropertyInfoAreaFile property_info_area;
static PropertyInfoAreaFile property_info_area;


uint32_t HandlePropertySet(const std::string& name, const std::string& value,
                           const std::string& source_context, const ucred& cr, std::string* error);
uint32_t InitPropertySet(const std::string& name, const std::string& value);
uint32_t InitPropertySet(const std::string& name, const std::string& value);


uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet;
uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet;
@@ -169,17 +164,6 @@ static bool CheckMacPerms(const std::string& name, const char* target_context,
    return has_access;
    return has_access;
}
}


static void SendPropertyChanged(const std::string& name, const std::string& value) {
    auto property_msg = PropertyMessage{};
    auto* changed_message = property_msg.mutable_changed_message();
    changed_message->set_name(name);
    changed_message->set_value(value);

    if (auto result = SendMessage(init_socket, property_msg); !result) {
        LOG(ERROR) << "Failed to send property changed message: " << result.error();
    }
}

static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
    size_t valuelen = value.size();
    size_t valuelen = value.size();


@@ -215,11 +199,7 @@ static uint32_t PropertySet(const std::string& name, const std::string& value, s
    if (persistent_properties_loaded && StartsWith(name, "persist.")) {
    if (persistent_properties_loaded && StartsWith(name, "persist.")) {
        WritePersistentProperty(name, value);
        WritePersistentProperty(name, value);
    }
    }
    // If init hasn't started its main loop, then it won't be handling property changed messages
    property_changed(name, value);
    // anyway, so there's no need to try to send them.
    if (init_socket != -1) {
        SendPropertyChanged(name, value);
    }
    return PROP_SUCCESS;
    return PROP_SUCCESS;
}
}


@@ -260,6 +240,17 @@ class AsyncRestorecon {
};
};


uint32_t InitPropertySet(const std::string& name, const std::string& value) {
uint32_t InitPropertySet(const std::string& name, const std::string& value) {
    if (StartsWith(name, "ctl.")) {
        LOG(ERROR) << "InitPropertySet: Do not set ctl. properties from init; call the Service "
                      "functions directly";
        return PROP_ERROR_INVALID_NAME;
    }
    if (name == kRestoreconProperty) {
        LOG(ERROR) << "InitPropertySet: Do not set '" << kRestoreconProperty
                   << "' from init; use the restorecon builtin directly";
        return PROP_ERROR_INVALID_NAME;
    }

    uint32_t result = 0;
    uint32_t result = 0;
    ucred cr = {.pid = 1, .uid = 0, .gid = 0};
    ucred cr = {.pid = 1, .uid = 0, .gid = 0};
    std::string error;
    std::string error;
@@ -275,6 +266,8 @@ class SocketConnection {
  public:
  public:
    SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {}
    SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {}


    ~SocketConnection() { close(socket_); }

    bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) {
    bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) {
        return RecvFully(value, sizeof(*value), timeout_ms);
        return RecvFully(value, sizeof(*value), timeout_ms);
    }
    }
@@ -396,61 +389,11 @@ class SocketConnection {
        return bytes_left == 0;
        return bytes_left == 0;
    }
    }


    unique_fd socket_;
    int socket_;
    ucred cred_;
    ucred cred_;
};

// Init responds with whether or not the control message was successful.  However, init may set
// properties in the process of handling the control message, particularly when starting services.
// Therefore we cannot block in SendControlMessage() to wait for init's response.  Instead, we store
// the SocketConnection for the socket that sent the control message.  We then return to the main
// poll loop and handle messages until we get the response from init.
//
// Note that this is a queue, since it is possible for more control messages to come while init is
// handling the first.  Both init and property service will handle these in order.
//
// Also note that the 1st version of the property service does not expect a result to be sent, so
// we have a nullopt as a placeholder in the queue to keep track of which control messages have been
// responded to.
static std::queue<std::optional<SocketConnection>> pending_control_message_results;

static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
                                   std::string* error) {
    auto property_msg = PropertyMessage{};
    auto* control_message = property_msg.mutable_control_message();
    control_message->set_msg(msg);
    control_message->set_name(name);
    control_message->set_pid(pid);

    if (auto result = SendMessage(init_socket, property_msg); !result) {
        *error = "Failed to send control message: " + result.error().message();
        return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
    }

    return PROP_SUCCESS;
}


void HandleControlResponse(const InitMessage& init_message) {
    DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection);
    if (pending_control_message_results.empty()) {
};
        LOG(ERROR) << "Got a control response without pending control messages";
        return;
    }

    if (!pending_control_message_results.front().has_value()) {
        pending_control_message_results.pop();
        return;
    }

    if (!pending_control_message_results.front().has_value()) {
        return;
    }

    auto& control_response = init_message.control_response();
    uint32_t response =
            control_response.result() ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
    pending_control_message_results.front()->SendUint32(response);
    pending_control_message_results.pop();
}


bool CheckControlPropertyPerms(const std::string& name, const std::string& value,
bool CheckControlPropertyPerms(const std::string& name, const std::string& value,
                               const std::string& source_context, const ucred& cr) {
                               const std::string& source_context, const ucred& cr) {
@@ -525,7 +468,9 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
    }
    }


    if (StartsWith(name, "ctl.")) {
    if (StartsWith(name, "ctl.")) {
        return SendControlMessage(name.c_str() + 4, value, cr.pid, error);
        return HandleControlMessage(name.c_str() + 4, value, cr.pid)
                       ? PROP_SUCCESS
                       : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
    }
    }


    // sys.powerctl is a special property that is used to make the device reboot.  We want to log
    // sys.powerctl is a special property that is used to make the device reboot.  We want to log
@@ -610,10 +555,6 @@ static void handle_property_set_fd() {
                       << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
                       << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
        }
        }


        if (result == PROP_SUCCESS && StartsWith(prop_name, "ctl.")) {
            pending_control_message_results.emplace(std::nullopt);
        }

        break;
        break;
      }
      }


@@ -641,12 +582,7 @@ static void handle_property_set_fd() {
            LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid
            LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid
                       << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
                       << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error;
        }
        }

        if (result == PROP_SUCCESS && StartsWith(name, "ctl.")) {
            pending_control_message_results.emplace(std::move(socket));
        } else {
        socket.SendUint32(result);
        socket.SendUint32(result);
        }
        break;
        break;
      }
      }


@@ -805,6 +741,33 @@ static void load_override_properties() {
    }
    }
}
}


/* When booting an encrypted system, /data is not mounted when the
 * property service is started, so any properties stored there are
 * not loaded.  Vold triggers init to load these properties once it
 * has mounted /data.
 */
void load_persist_props(void) {
    // Devices with FDE have load_persist_props called twice; the first time when the temporary
    // /data partition is mounted and then again once /data is truly mounted.  We do not want to
    // read persistent properties from the temporary /data partition or mark persistent properties
    // as having been loaded during the first call, so we return in that case.
    std::string crypto_state = android::base::GetProperty("ro.crypto.state", "");
    std::string crypto_type = android::base::GetProperty("ro.crypto.type", "");
    if (crypto_state == "encrypted" && crypto_type == "block") {
        static size_t num_calls = 0;
        if (++num_calls == 1) return;
    }

    load_override_properties();
    /* Read persistent properties after all default values have been loaded. */
    auto persistent_properties = LoadPersistentProperties();
    for (const auto& persistent_property_record : persistent_properties.properties()) {
        property_set(persistent_property_record.name(), persistent_property_record.value());
    }
    persistent_properties_loaded = true;
    property_set("ro.persistent_properties.ready", "true");
}

// If the ro.product.[brand|device|manufacturer|model|name] properties have not been explicitly
// If the ro.product.[brand|device|manufacturer|model|name] properties have not been explicitly
// set, derive them from ro.product.${partition}.* properties
// set, derive them from ro.product.${partition}.* properties
static void property_initialize_ro_product_props() {
static void property_initialize_ro_product_props() {
@@ -1022,87 +985,21 @@ void CreateSerializedPropertyInfo() {
    selinux_android_restorecon(kPropertyInfosPath, 0);
    selinux_android_restorecon(kPropertyInfosPath, 0);
}
}


static void HandleInitSocket() {
void StartPropertyService(Epoll* epoll) {
    auto message = ReadMessage(init_socket);
    if (!message) {
        LOG(ERROR) << "Could not read message from init_dedicated_recv_socket: " << message.error();
        return;
    }

    auto init_message = InitMessage{};
    if (!init_message.ParseFromString(*message)) {
        LOG(ERROR) << "Could not parse message from init";
        return;
    }

    switch (init_message.msg_case()) {
        case InitMessage::kControlResponse: {
            HandleControlResponse(init_message);
            break;
        }
        case InitMessage::kLoadPersistentProperties: {
            load_override_properties();
            // Read persistent properties after all default values have been loaded.
            auto persistent_properties = LoadPersistentProperties();
            for (const auto& persistent_property_record : persistent_properties.properties()) {
                InitPropertySet(persistent_property_record.name(),
                                persistent_property_record.value());
            }
            InitPropertySet("ro.persistent_properties.ready", "true");
            persistent_properties_loaded = true;
            break;
        }
        default:
            LOG(ERROR) << "Unknown message type from init: " << init_message.msg_case();
    }
}

static void PropertyServiceThread() {
    Epoll epoll;
    if (auto result = epoll.Open(); !result) {
        LOG(FATAL) << result.error();
    }

    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
        LOG(FATAL) << result.error();
    }

    if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result) {
        LOG(FATAL) << result.error();
    }

    while (true) {
        if (auto result = epoll.Wait(std::nullopt); !result) {
            LOG(ERROR) << result.error();
        }
    }
}

void StartPropertyService(int* epoll_socket) {
    property_set("ro.property_service.version", "2");
    property_set("ro.property_service.version", "2");


    int sockets[2];
    if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
    if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
                                   false, 0666, 0, 0, {})) {
        PLOG(FATAL) << "Failed to socketpair() between property_service and init";
    }
    *epoll_socket = sockets[0];
    init_socket = sockets[1];

    if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC, false, 0666, 0, 0,
                                   {})) {
        property_set_fd = *result;
        property_set_fd = *result;
    } else {
    } else {
        LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
        PLOG(FATAL) << "start_property_service socket creation failed: " << result.error();
    }
    }


    listen(property_set_fd, 8);
    listen(property_set_fd, 8);


    std::thread{PropertyServiceThread}.detach();
    if (auto result = epoll->RegisterHandler(property_set_fd, handle_property_set_fd); !result) {

        PLOG(FATAL) << result.error();
    property_set = [](const std::string& key, const std::string& value) -> uint32_t {
    }
        android::base::SetProperty(key, value);
        return 0;
    };
}
}


}  // namespace init
}  // namespace init
Loading