Loading init/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ cc_library_static { "persistent_properties.cpp", "persistent_properties.proto", "property_service.cpp", "property_service.proto", "property_type.cpp", "reboot.cpp", "reboot_utils.cpp", Loading init/builtins.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ using namespace std::literals::string_literals; using android::base::Basename; using android::base::StartsWith; using android::base::unique_fd; using android::fs_mgr::Fstab; using android::fs_mgr::ReadFstabFromFile; Loading Loading @@ -700,6 +701,15 @@ static Result<void> do_swapon_all(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]); return {}; } Loading init/init.cpp +50 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ #include <sys/types.h> #include <unistd.h> #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> #include <functional> #include <map> #include <memory> Loading Loading @@ -61,6 +64,7 @@ #include "mount_handler.h" #include "mount_namespace.h" #include "property_service.h" #include "proto_utils.h" #include "reboot.h" #include "reboot_utils.h" #include "security.h" Loading @@ -69,6 +73,7 @@ #include "service.h" #include "service_parser.h" #include "sigchld_handler.h" #include "system/core/init/property_service.pb.h" #include "util.h" using namespace std::chrono_literals; Loading @@ -90,6 +95,7 @@ static int property_triggers_enabled = 0; static char qemu[32]; static int signal_fd = -1; static int property_fd = -1; static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::string wait_prop_name; Loading Loading @@ -613,6 +619,44 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star 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) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); Loading Loading @@ -684,7 +728,12 @@ int SecondStageMain(int argc, char** argv) { UmountDebugRamdisk(); fs_mgr_vendor_overlay_mount_all(); 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); set_usb_controller(); Loading init/init.h +0 −4 Original line number Diff line number Diff line Loading @@ -31,10 +31,6 @@ namespace init { Parser CreateParser(ActionManager& action_manager, 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); void DumpState(); Loading init/property_service.cpp +101 −50 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <map> #include <memory> #include <mutex> #include <optional> #include <queue> #include <thread> #include <vector> Loading @@ -63,8 +64,10 @@ #include "init.h" #include "persistent_properties.h" #include "property_type.h" #include "proto_utils.h" #include "selinux.h" #include "subcontext.h" #include "system/core/init/property_service.pb.h" #include "util.h" using namespace std::literals; Loading @@ -76,6 +79,7 @@ using android::base::StartsWith; using android::base::StringPrintf; using android::base::Timer; using android::base::Trim; using android::base::unique_fd; using android::base::WriteStringToFile; using android::properties::BuildTrie; using android::properties::ParsePropertyInfoFile; Loading @@ -85,18 +89,13 @@ using android::properties::PropertyInfoEntry; namespace android { namespace init { static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive"; static bool persistent_properties_loaded = false; static int property_set_fd = -1; static int init_socket = -1; 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(); struct PropertyAuditData { Loading Loading @@ -164,6 +163,17 @@ static bool CheckMacPerms(const std::string& name, const char* target_context, 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) { size_t valuelen = value.size(); Loading Loading @@ -199,7 +209,16 @@ static uint32_t PropertySet(const std::string& name, const std::string& value, s if (persistent_properties_loaded && StartsWith(name, "persist.")) { WritePersistentProperty(name, value); } property_changed(name, value); // If init sets ro.persistent_properties.ready to true, then it has finished writing persistent // 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; } Loading Loading @@ -239,35 +258,10 @@ class AsyncRestorecon { 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 { public: SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {} ~SocketConnection() { close(socket_); } bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) { return RecvFully(value, sizeof(*value), timeout_ms); } Loading Loading @@ -304,6 +298,9 @@ class SocketConnection { } bool SendUint32(uint32_t value) { if (!socket_.ok()) { return false; } int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0)); return result == sizeof(value); } Loading @@ -318,7 +315,9 @@ class SocketConnection { return true; } int socket() { return socket_; } int Release() { return socket_.release(); } int socket() { return socket_.get(); } const ucred& cred() { return cred_; } Loading Loading @@ -389,12 +388,34 @@ class SocketConnection { return bytes_left == 0; } int socket_; unique_fd socket_; ucred cred_; DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection); }; 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) { *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, const std::string& source_context, const ucred& cr) { // We check the legacy method first but these properties are dontaudit, so we only log an audit Loading Loading @@ -462,15 +483,14 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value, // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. uint32_t HandlePropertySet(const std::string& name, const std::string& value, const std::string& source_context, const ucred& cr, std::string* error) { const std::string& source_context, const ucred& cr, SocketConnection* socket, std::string* error) { if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) { return ret; } if (StartsWith(name, "ctl.")) { return HandleControlMessage(name.c_str() + 4, value, cr.pid) ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE; return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error); } // sys.powerctl is a special property that is used to make the device reboot. We want to log Loading Loading @@ -501,6 +521,20 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, 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 constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ Loading Loading @@ -549,7 +583,8 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); std::string error; uint32_t result = HandlePropertySet(prop_name, prop_value, source_context, cr, &error); uint32_t result = HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; Loading Loading @@ -577,11 +612,12 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); std::string error; uint32_t result = HandlePropertySet(name, value, source_context, cr, &error); uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; } socket.SendUint32(result); break; } Loading Loading @@ -764,7 +800,6 @@ void load_persist_props(void) { 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"); } Loading Loading @@ -985,21 +1020,37 @@ void CreateSerializedPropertyInfo() { selinux_android_restorecon(kPropertyInfosPath, 0); } void StartPropertyService(Epoll* epoll) { static void PropertyServiceThread() { while (true) { handle_property_set_fd(); } } void StartPropertyService(int* epoll_socket) { property_set("ro.property_service.version", "2"); if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, false, 0666, 0, 0, {})) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 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; } else { PLOG(FATAL) << "start_property_service socket creation failed: " << result.error(); LOG(FATAL) << "start_property_service socket creation failed: " << result.error(); } listen(property_set_fd, 8); if (auto result = epoll->RegisterHandler(property_set_fd, handle_property_set_fd); !result) { PLOG(FATAL) << result.error(); } std::thread{PropertyServiceThread}.detach(); property_set = [](const std::string& key, const std::string& value) -> uint32_t { android::base::SetProperty(key, value); return 0; }; } } // namespace init Loading Loading
init/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ cc_library_static { "persistent_properties.cpp", "persistent_properties.proto", "property_service.cpp", "property_service.proto", "property_type.cpp", "reboot.cpp", "reboot_utils.cpp", Loading
init/builtins.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ using namespace std::literals::string_literals; using android::base::Basename; using android::base::StartsWith; using android::base::unique_fd; using android::fs_mgr::Fstab; using android::fs_mgr::ReadFstabFromFile; Loading Loading @@ -700,6 +701,15 @@ static Result<void> do_swapon_all(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]); return {}; } Loading
init/init.cpp +50 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ #include <sys/types.h> #include <unistd.h> #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> #include <functional> #include <map> #include <memory> Loading Loading @@ -61,6 +64,7 @@ #include "mount_handler.h" #include "mount_namespace.h" #include "property_service.h" #include "proto_utils.h" #include "reboot.h" #include "reboot_utils.h" #include "security.h" Loading @@ -69,6 +73,7 @@ #include "service.h" #include "service_parser.h" #include "sigchld_handler.h" #include "system/core/init/property_service.pb.h" #include "util.h" using namespace std::chrono_literals; Loading @@ -90,6 +95,7 @@ static int property_triggers_enabled = 0; static char qemu[32]; static int signal_fd = -1; static int property_fd = -1; static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::string wait_prop_name; Loading Loading @@ -613,6 +619,44 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star 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) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); Loading Loading @@ -684,7 +728,12 @@ int SecondStageMain(int argc, char** argv) { UmountDebugRamdisk(); fs_mgr_vendor_overlay_mount_all(); 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); set_usb_controller(); Loading
init/init.h +0 −4 Original line number Diff line number Diff line Loading @@ -31,10 +31,6 @@ namespace init { Parser CreateParser(ActionManager& action_manager, 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); void DumpState(); Loading
init/property_service.cpp +101 −50 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ #include <map> #include <memory> #include <mutex> #include <optional> #include <queue> #include <thread> #include <vector> Loading @@ -63,8 +64,10 @@ #include "init.h" #include "persistent_properties.h" #include "property_type.h" #include "proto_utils.h" #include "selinux.h" #include "subcontext.h" #include "system/core/init/property_service.pb.h" #include "util.h" using namespace std::literals; Loading @@ -76,6 +79,7 @@ using android::base::StartsWith; using android::base::StringPrintf; using android::base::Timer; using android::base::Trim; using android::base::unique_fd; using android::base::WriteStringToFile; using android::properties::BuildTrie; using android::properties::ParsePropertyInfoFile; Loading @@ -85,18 +89,13 @@ using android::properties::PropertyInfoEntry; namespace android { namespace init { static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive"; static bool persistent_properties_loaded = false; static int property_set_fd = -1; static int init_socket = -1; 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(); struct PropertyAuditData { Loading Loading @@ -164,6 +163,17 @@ static bool CheckMacPerms(const std::string& name, const char* target_context, 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) { size_t valuelen = value.size(); Loading Loading @@ -199,7 +209,16 @@ static uint32_t PropertySet(const std::string& name, const std::string& value, s if (persistent_properties_loaded && StartsWith(name, "persist.")) { WritePersistentProperty(name, value); } property_changed(name, value); // If init sets ro.persistent_properties.ready to true, then it has finished writing persistent // 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; } Loading Loading @@ -239,35 +258,10 @@ class AsyncRestorecon { 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 { public: SocketConnection(int socket, const ucred& cred) : socket_(socket), cred_(cred) {} ~SocketConnection() { close(socket_); } bool RecvUint32(uint32_t* value, uint32_t* timeout_ms) { return RecvFully(value, sizeof(*value), timeout_ms); } Loading Loading @@ -304,6 +298,9 @@ class SocketConnection { } bool SendUint32(uint32_t value) { if (!socket_.ok()) { return false; } int result = TEMP_FAILURE_RETRY(send(socket_, &value, sizeof(value), 0)); return result == sizeof(value); } Loading @@ -318,7 +315,9 @@ class SocketConnection { return true; } int socket() { return socket_; } int Release() { return socket_.release(); } int socket() { return socket_.get(); } const ucred& cred() { return cred_; } Loading Loading @@ -389,12 +388,34 @@ class SocketConnection { return bytes_left == 0; } int socket_; unique_fd socket_; ucred cred_; DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection); }; 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) { *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, const std::string& source_context, const ucred& cr) { // We check the legacy method first but these properties are dontaudit, so we only log an audit Loading Loading @@ -462,15 +483,14 @@ uint32_t CheckPermissions(const std::string& name, const std::string& value, // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*. uint32_t HandlePropertySet(const std::string& name, const std::string& value, const std::string& source_context, const ucred& cr, std::string* error) { const std::string& source_context, const ucred& cr, SocketConnection* socket, std::string* error) { if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) { return ret; } if (StartsWith(name, "ctl.")) { return HandleControlMessage(name.c_str() + 4, value, cr.pid) ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE; return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error); } // sys.powerctl is a special property that is used to make the device reboot. We want to log Loading Loading @@ -501,6 +521,20 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, 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 constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */ Loading Loading @@ -549,7 +583,8 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); std::string error; uint32_t result = HandlePropertySet(prop_name, prop_value, source_context, cr, &error); uint32_t result = HandlePropertySet(prop_name, prop_value, source_context, cr, nullptr, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Unable to set property '" << prop_name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; Loading Loading @@ -577,11 +612,12 @@ static void handle_property_set_fd() { const auto& cr = socket.cred(); std::string error; uint32_t result = HandlePropertySet(name, value, source_context, cr, &error); uint32_t result = HandlePropertySet(name, value, source_context, cr, &socket, &error); if (result != PROP_SUCCESS) { LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; } socket.SendUint32(result); break; } Loading Loading @@ -764,7 +800,6 @@ void load_persist_props(void) { 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"); } Loading Loading @@ -985,21 +1020,37 @@ void CreateSerializedPropertyInfo() { selinux_android_restorecon(kPropertyInfosPath, 0); } void StartPropertyService(Epoll* epoll) { static void PropertyServiceThread() { while (true) { handle_property_set_fd(); } } void StartPropertyService(int* epoll_socket) { property_set("ro.property_service.version", "2"); if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, false, 0666, 0, 0, {})) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 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; } else { PLOG(FATAL) << "start_property_service socket creation failed: " << result.error(); LOG(FATAL) << "start_property_service socket creation failed: " << result.error(); } listen(property_set_fd, 8); if (auto result = epoll->RegisterHandler(property_set_fd, handle_property_set_fd); !result) { PLOG(FATAL) << result.error(); } std::thread{PropertyServiceThread}.detach(); property_set = [](const std::string& key, const std::string& value) -> uint32_t { android::base::SetProperty(key, value); return 0; }; } } // namespace init Loading