Loading init/Android.bp +0 −1 Original line number Original line Diff line number Diff line Loading @@ -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", Loading init/builtins.cpp +1 −24 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 {}; } } Loading Loading @@ -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 {}; } } Loading init/init.cpp +1 −57 Original line number Original line Diff line number Diff line Loading @@ -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" Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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(); Loading init/init.h +4 −2 Original line number Original line Diff line number Diff line Loading @@ -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 Loading init/property_service.cpp +57 −160 Original line number Original line Diff line number Diff line Loading @@ -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> Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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; } } Loading Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -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; } } Loading Loading @@ -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; } } Loading Loading @@ -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() { Loading Loading @@ -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 Loading
init/Android.bp +0 −1 Original line number Original line Diff line number Diff line Loading @@ -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", Loading
init/builtins.cpp +1 −24 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 {}; } } Loading Loading @@ -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 {}; } } Loading
init/init.cpp +1 −57 Original line number Original line Diff line number Diff line Loading @@ -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" Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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(); Loading
init/init.h +4 −2 Original line number Original line Diff line number Diff line Loading @@ -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 Loading
init/property_service.cpp +57 −160 Original line number Original line Diff line number Diff line Loading @@ -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> Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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; } } Loading Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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) { Loading Loading @@ -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 Loading Loading @@ -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; } } Loading Loading @@ -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; } } Loading Loading @@ -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() { Loading Loading @@ -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