Loading init/Android.bp +0 −1 Original line number Original line Diff line number Diff line Loading @@ -130,7 +130,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 +0 −10 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 @@ -701,15 +700,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() << "InitPropertySet: Do not set ctl. properties from init; call the Service " "functions directly"; } if (args[1] == kRestoreconProperty) { return Error() << "InitPropertySet: Do not set '" << kRestoreconProperty << "' from init; use the restorecon builtin directly"; } property_set(args[1], args[2]); property_set(args[1], args[2]); return {}; return {}; } } Loading init/init.cpp +1 −50 Original line number Original line Diff line number Diff line Loading @@ -28,9 +28,6 @@ #include <sys/types.h> #include <sys/types.h> #include <unistd.h> #include <unistd.h> #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> #include <functional> #include <functional> #include <map> #include <map> #include <memory> #include <memory> Loading Loading @@ -64,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 @@ -73,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 @@ -95,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 @@ -619,44 +613,6 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star selinux_start_time_ns)); selinux_start_time_ns)); } } 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 success = HandleControlMessage(control_message.msg(), control_message.name(), control_message.pid()); uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE; if (control_message.has_fd()) { int fd = control_message.fd(); TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0)); close(fd); } 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 @@ -728,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 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,10 @@ 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(); Loading init/property_service.cpp +50 −101 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,13 +85,18 @@ 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 InitPropertySet(const std::string& name, const std::string& value); uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet; void CreateSerializedPropertyInfo(); void CreateSerializedPropertyInfo(); struct PropertyAuditData { struct PropertyAuditData { Loading Loading @@ -163,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 @@ -209,16 +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 sets ro.persistent_properties.ready to true, then it has finished writing persistent property_changed(name, value); // properties, and we should write future persistent properties to disk. if (name == "ro.persistent_properties.ready" && value == "true") { persistent_properties_loaded = true; } // If init hasn't started its main loop, then it won't be handling property changed messages // 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 @@ -258,10 +239,35 @@ class AsyncRestorecon { bool thread_started_ = false; bool thread_started_ = false; }; }; 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; ucred cr = {.pid = 1, .uid = 0, .gid = 0}; std::string error; result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error; } return result; } class SocketConnection { 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 @@ -298,9 +304,6 @@ class SocketConnection { } } bool SendUint32(uint32_t value) { bool SendUint32(uint32_t value) { if (!socket_.ok()) { return false; } int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0)); int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0)); return result == sizeof(value); return result == sizeof(value); } } Loading @@ -315,9 +318,7 @@ class SocketConnection { return true; return true; } } int Release() { return socket_.release(); } int socket() { return socket_; } int socket() { return socket_.get(); } const ucred& cred() { return cred_; } const ucred& cred() { return cred_; } Loading Loading @@ -388,33 +389,11 @@ class SocketConnection { return bytes_left == 0; return bytes_left == 0; } } unique_fd socket_; int socket_; ucred cred_; ucred cred_; }; static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid, SocketConnection* socket, 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 (socket != nullptr) { control_message->set_fd(socket->socket()); } if (auto result = SendMessage(init_socket, property_msg); !result) { DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection); *error = "Failed to send control message: " + result.error().message(); }; return PROP_ERROR_HANDLE_CONTROL_MESSAGE; } if (socket != nullptr) { // We've successfully sent the fd to init, so release it here. socket->Release(); } return PROP_SUCCESS; } 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 @@ -483,14 +462,15 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value, // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. uint32_t HandlePropertySet(const std::string& name, const std::string& value, uint32_t HandlePropertySet(const std::string& name, const std::string& value, const std::string& source_context, const ucred& cr, const std::string& source_context, const ucred& cr, std::string* error) { SocketConnection* socket, std::string* error) { if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) { if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) { return ret; return ret; } } if (StartsWith(name, "ctl.")) { if (StartsWith(name, "ctl.")) { return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, 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 @@ -521,20 +501,6 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, return PropertySet(name, value, error); return PropertySet(name, value, error); } } uint32_t InitPropertySet(const std::string& name, const std::string& value) { uint32_t result = 0; ucred cr = {.pid = 1, .uid = 0, .gid = 0}; std::string error; result = HandlePropertySet(name, value, kInitContext.c_str(), cr, nullptr, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error; } return result; } uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet; static void handle_property_set_fd() { static void handle_property_set_fd() { static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ Loading Loading @@ -583,8 +549,7 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); const auto& cr = socket.cred(); std::string error; std::string error; uint32_t result = uint32_t result = HandlePropertySet(prop_name, prop_value, source_context, cr, &error); HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error); if (result != PROP_SUCCESS) { if (result != PROP_SUCCESS) { LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; Loading Loading @@ -612,12 +577,11 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); const auto& cr = socket.cred(); std::string error; std::string error; uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error); uint32_t result = HandlePropertySet(name, value, source_context, cr, &error); if (result != PROP_SUCCESS) { if (result != PROP_SUCCESS) { 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; } } socket.SendUint32(result); socket.SendUint32(result); break; break; } } Loading Loading @@ -800,6 +764,7 @@ void load_persist_props(void) { for (const auto& persistent_property_record : persistent_properties.properties()) { for (const auto& persistent_property_record : persistent_properties.properties()) { property_set(persistent_property_record.name(), persistent_property_record.value()); property_set(persistent_property_record.name(), persistent_property_record.value()); } } persistent_properties_loaded = true; property_set("ro.persistent_properties.ready", "true"); property_set("ro.persistent_properties.ready", "true"); } } Loading Loading @@ -1020,37 +985,21 @@ void CreateSerializedPropertyInfo() { selinux_android_restorecon(kPropertyInfosPath, 0); selinux_android_restorecon(kPropertyInfosPath, 0); } } static void PropertyServiceThread() { void StartPropertyService(Epoll* epoll) { while (true) { handle_property_set_fd(); } } 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 @@ -130,7 +130,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 +0 −10 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 @@ -701,15 +700,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() << "InitPropertySet: Do not set ctl. properties from init; call the Service " "functions directly"; } if (args[1] == kRestoreconProperty) { return Error() << "InitPropertySet: Do not set '" << kRestoreconProperty << "' from init; use the restorecon builtin directly"; } property_set(args[1], args[2]); property_set(args[1], args[2]); return {}; return {}; } } Loading
init/init.cpp +1 −50 Original line number Original line Diff line number Diff line Loading @@ -28,9 +28,6 @@ #include <sys/types.h> #include <sys/types.h> #include <unistd.h> #include <unistd.h> #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> #include <functional> #include <functional> #include <map> #include <map> #include <memory> #include <memory> Loading Loading @@ -64,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 @@ -73,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 @@ -95,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 @@ -619,44 +613,6 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star selinux_start_time_ns)); selinux_start_time_ns)); } } 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 success = HandleControlMessage(control_message.msg(), control_message.name(), control_message.pid()); uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE; if (control_message.has_fd()) { int fd = control_message.fd(); TEMP_FAILURE_RETRY(send(fd, &response, sizeof(response), 0)); close(fd); } 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 @@ -728,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 −0 Original line number Original line Diff line number Diff line Loading @@ -31,6 +31,10 @@ 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(); Loading
init/property_service.cpp +50 −101 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,13 +85,18 @@ 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 InitPropertySet(const std::string& name, const std::string& value); uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet; void CreateSerializedPropertyInfo(); void CreateSerializedPropertyInfo(); struct PropertyAuditData { struct PropertyAuditData { Loading Loading @@ -163,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 @@ -209,16 +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 sets ro.persistent_properties.ready to true, then it has finished writing persistent property_changed(name, value); // properties, and we should write future persistent properties to disk. if (name == "ro.persistent_properties.ready" && value == "true") { persistent_properties_loaded = true; } // If init hasn't started its main loop, then it won't be handling property changed messages // 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 @@ -258,10 +239,35 @@ class AsyncRestorecon { bool thread_started_ = false; bool thread_started_ = false; }; }; 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; ucred cr = {.pid = 1, .uid = 0, .gid = 0}; std::string error; result = HandlePropertySet(name, value, kInitContext.c_str(), cr, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error; } return result; } class SocketConnection { 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 @@ -298,9 +304,6 @@ class SocketConnection { } } bool SendUint32(uint32_t value) { bool SendUint32(uint32_t value) { if (!socket_.ok()) { return false; } int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0)); int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0)); return result == sizeof(value); return result == sizeof(value); } } Loading @@ -315,9 +318,7 @@ class SocketConnection { return true; return true; } } int Release() { return socket_.release(); } int socket() { return socket_; } int socket() { return socket_.get(); } const ucred& cred() { return cred_; } const ucred& cred() { return cred_; } Loading Loading @@ -388,33 +389,11 @@ class SocketConnection { return bytes_left == 0; return bytes_left == 0; } } unique_fd socket_; int socket_; ucred cred_; ucred cred_; }; static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid, SocketConnection* socket, 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 (socket != nullptr) { control_message->set_fd(socket->socket()); } if (auto result = SendMessage(init_socket, property_msg); !result) { DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection); *error = "Failed to send control message: " + result.error().message(); }; return PROP_ERROR_HANDLE_CONTROL_MESSAGE; } if (socket != nullptr) { // We've successfully sent the fd to init, so release it here. socket->Release(); } return PROP_SUCCESS; } 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 @@ -483,14 +462,15 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value, // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. uint32_t HandlePropertySet(const std::string& name, const std::string& value, uint32_t HandlePropertySet(const std::string& name, const std::string& value, const std::string& source_context, const ucred& cr, const std::string& source_context, const ucred& cr, std::string* error) { SocketConnection* socket, std::string* error) { if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) { if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) { return ret; return ret; } } if (StartsWith(name, "ctl.")) { if (StartsWith(name, "ctl.")) { return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, 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 @@ -521,20 +501,6 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, return PropertySet(name, value, error); return PropertySet(name, value, error); } } uint32_t InitPropertySet(const std::string& name, const std::string& value) { uint32_t result = 0; ucred cr = {.pid = 1, .uid = 0, .gid = 0}; std::string error; result = HandlePropertySet(name, value, kInitContext.c_str(), cr, nullptr, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error; } return result; } uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet; static void handle_property_set_fd() { static void handle_property_set_fd() { static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ Loading Loading @@ -583,8 +549,7 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); const auto& cr = socket.cred(); std::string error; std::string error; uint32_t result = uint32_t result = HandlePropertySet(prop_name, prop_value, source_context, cr, &error); HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error); if (result != PROP_SUCCESS) { if (result != PROP_SUCCESS) { LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; Loading Loading @@ -612,12 +577,11 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); const auto& cr = socket.cred(); std::string error; std::string error; uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error); uint32_t result = HandlePropertySet(name, value, source_context, cr, &error); if (result != PROP_SUCCESS) { if (result != PROP_SUCCESS) { 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; } } socket.SendUint32(result); socket.SendUint32(result); break; break; } } Loading Loading @@ -800,6 +764,7 @@ void load_persist_props(void) { for (const auto& persistent_property_record : persistent_properties.properties()) { for (const auto& persistent_property_record : persistent_properties.properties()) { property_set(persistent_property_record.name(), persistent_property_record.value()); property_set(persistent_property_record.name(), persistent_property_record.value()); } } persistent_properties_loaded = true; property_set("ro.persistent_properties.ready", "true"); property_set("ro.persistent_properties.ready", "true"); } } Loading Loading @@ -1020,37 +985,21 @@ void CreateSerializedPropertyInfo() { selinux_android_restorecon(kPropertyInfosPath, 0); selinux_android_restorecon(kPropertyInfosPath, 0); } } static void PropertyServiceThread() { void StartPropertyService(Epoll* epoll) { while (true) { handle_property_set_fd(); } } 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