diff --git a/init/Android.bp b/init/Android.bp index 38d495f4b..1e38bf04f 100644 --- a/init/Android.bp +++ b/init/Android.bp @@ -128,6 +128,7 @@ cc_library_static { "persistent_properties.cpp", "persistent_properties.proto", "property_service.cpp", + "property_service.proto", "property_type.cpp", "reboot.cpp", "reboot_utils.cpp", diff --git a/init/builtins.cpp b/init/builtins.cpp index a2d782bc2..707692644 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -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; @@ -640,12 +641,7 @@ static Result do_mount_all(const BuiltinArguments& args) { if (!ReadFstabFromFile(fstab_file, &fstab)) { return Error() << "Could not read fstab"; } - - auto mount_fstab_return_code = - CallFunctionAndHandleProperties(fs_mgr_mount_all, &fstab, mount_mode); - if (!mount_fstab_return_code) { - return Error() << "Could not call fs_mgr_mount_all(): " << mount_fstab_return_code.error(); - } + auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode); property_set(prop_name, std::to_string(t.duration().count())); if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) { @@ -656,7 +652,7 @@ static Result do_mount_all(const BuiltinArguments& args) { if (queue_event) { /* queue_fs_event will queue event based on mount_fstab return code * and return processed return code*/ - auto queue_fs_result = queue_fs_event(*mount_fstab_return_code); + auto queue_fs_result = queue_fs_event(mount_fstab_return_code); if (!queue_fs_result) { return Error() << "queue_fs_event() failed: " << queue_fs_result.error(); } @@ -672,13 +668,8 @@ static Result do_umount_all(const BuiltinArguments& args) { return Error() << "Could not read fstab"; } - auto result = CallFunctionAndHandleProperties(fs_mgr_umount_all, &fstab); - if (!result) { - return Error() << "Could not call fs_mgr_mount_all() " << result.error(); - } - - if (*result != 0) { - return Error() << "fs_mgr_mount_all() failed: " << *result; + if (auto result = fs_mgr_umount_all(&fstab); result != 0) { + return Error() << "umount_fstab() failed " << result; } return {}; } @@ -689,19 +680,23 @@ static Result do_swapon_all(const BuiltinArguments& args) { return Error() << "Could not read fstab '" << args[1] << "'"; } - auto result = CallFunctionAndHandleProperties(fs_mgr_swapon_all, fstab); - if (!result) { - return Error() << "Could not call fs_mgr_swapon_all() " << result.error(); - } - - if (*result == 0) { - return Error() << "fs_mgr_swapon_all() failed."; + if (!fs_mgr_swapon_all(fstab)) { + return Error() << "fs_mgr_swapon_all() failed"; } return {}; } static Result 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]); return {}; } @@ -1017,7 +1012,20 @@ static Result do_loglevel(const BuiltinArguments& args) { } static Result do_load_persist_props(const BuiltinArguments& args) { - load_persist_props(); + // 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 {}; + } + + SendLoadPersistentPropertiesMessage(); + + start_waiting_for_property("ro.persistent_properties.ready", "true"); return {}; } diff --git a/init/init.cpp b/init/init.cpp index 18fb0c3ee..e8eb571b8 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -61,6 +61,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" @@ -69,6 +70,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; @@ -90,6 +92,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 waiting_for_prop(nullptr); static std::string wait_prop_name; @@ -613,6 +616,54 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star 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) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); @@ -684,7 +735,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(); diff --git a/init/init.h b/init/init.h index cfc28f1be..832ce3f0b 100644 --- a/init/init.h +++ b/init/init.h @@ -31,16 +31,14 @@ 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(); void ResetWaitForProp(); +void SendLoadPersistentPropertiesMessage(); + int SecondStageMain(int argc, char** argv); } // namespace init diff --git a/init/property_service.cpp b/init/property_service.cpp index 17622a32b..b7d5743f9 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -39,10 +39,10 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include -#include #include #include #include +#include #include #include #include @@ -53,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -61,11 +60,14 @@ #include #include "debug_ramdisk.h" +#include "epoll.h" #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; @@ -87,14 +89,15 @@ 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 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 (*property_set)(const std::string& name, const std::string& value) = InitPropertySet; @@ -166,6 +169,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(); @@ -201,7 +215,11 @@ 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 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; } @@ -242,17 +260,6 @@ class AsyncRestorecon { }; 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; @@ -268,8 +275,6 @@ 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); } @@ -391,12 +396,62 @@ class SocketConnection { return bytes_left == 0; } - int socket_; + unique_fd socket_; ucred cred_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(SocketConnection); }; +// 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> 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) { + 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, 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 @@ -470,9 +525,7 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value, } 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, error); } // sys.powerctl is a special property that is used to make the device reboot. We want to log @@ -557,6 +610,10 @@ static void handle_property_set_fd() { << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; } + if (result == PROP_SUCCESS && StartsWith(prop_name, "ctl.")) { + pending_control_message_results.emplace(std::nullopt); + } + break; } @@ -584,7 +641,12 @@ static void handle_property_set_fd() { LOG(ERROR) << "Unable to set property '" << name << "' from uid:" << cr.uid << " gid:" << cr.gid << " pid:" << cr.pid << ": " << error; } - socket.SendUint32(result); + + if (result == PROP_SUCCESS && StartsWith(name, "ctl.")) { + pending_control_message_results.emplace(std::move(socket)); + } else { + socket.SendUint32(result); + } break; } @@ -743,33 +805,6 @@ 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 // set, derive them from ro.product.${partition}.* properties static void property_initialize_ro_product_props() { @@ -987,58 +1022,87 @@ void CreateSerializedPropertyInfo() { selinux_android_restorecon(kPropertyInfosPath, 0); } -void StartPropertyService(Epoll* epoll) { +static void HandleInitSocket() { + 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"); - 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(); -Result CallFunctionAndHandlePropertiesImpl(const std::function& f) { - unique_fd reader; - unique_fd writer; - if (!Socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, &reader, &writer)) { - return ErrnoError() << "Could not create socket pair"; - } - - int result = 0; - std::atomic end = false; - auto thread = std::thread{[&f, &result, &end, &writer] { - result = f(); - end = true; - send(writer, "1", 1, 0); - }}; - - Epoll epoll; - if (auto result = epoll.Open(); !result) { - return Error() << "Could not create epoll: " << result.error(); - } - if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd); !result) { - return Error() << "Could not register epoll handler for property fd: " << result.error(); - } - - // No-op function, just used to break from loop. - if (auto result = epoll.RegisterHandler(reader, [] {}); !result) { - return Error() << "Could not register epoll handler for ending thread:" << result.error(); - } - - while (!end) { - epoll.Wait({}); - } - - thread.join(); - - return result; + property_set = [](const std::string& key, const std::string& value) -> uint32_t { + android::base::SetProperty(key, value); + return 0; + }; } } // namespace init diff --git a/init/property_service.h b/init/property_service.h index dc47b4db8..8f7d8d96e 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -18,34 +18,22 @@ #include -#include #include #include "epoll.h" -#include "result.h" namespace android { namespace init { +static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursive"; + bool CanReadProperty(const std::string& source_context, const std::string& name); extern uint32_t (*property_set)(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, std::string* error); - void property_init(); void property_load_boot_defaults(bool load_debug_prop); -void load_persist_props(); -void StartPropertyService(Epoll* epoll); - -template -Result CallFunctionAndHandleProperties(F&& f, Args&&... args) { - Result CallFunctionAndHandlePropertiesImpl(const std::function& f); - - auto func = [&] { return f(args...); }; - return CallFunctionAndHandlePropertiesImpl(func); -} +void StartPropertyService(int* epoll_socket); } // namespace init } // namespace android diff --git a/init/property_service.proto b/init/property_service.proto new file mode 100644 index 000000000..894fa137c --- /dev/null +++ b/init/property_service.proto @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; + +message PropertyMessage { + message ControlMessage { + optional string msg = 1; + optional string name = 2; + optional int32 pid = 3; + } + + message ChangedMessage { + optional string name = 1; + optional string value = 2; + } + + oneof msg { + ControlMessage control_message = 1; + ChangedMessage changed_message = 2; + }; +} + +message InitMessage { + message ControlResponse { optional bool result = 1; } + + oneof msg { + ControlResponse control_response = 1; + bool load_persistent_properties = 2; + }; +} diff --git a/init/proto_utils.h b/init/proto_utils.h new file mode 100644 index 000000000..93a7d57a8 --- /dev/null +++ b/init/proto_utils.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +#include "result.h" + +namespace android { +namespace init { + +constexpr size_t kBufferSize = 4096; + +inline Result ReadMessage(int socket) { + char buffer[kBufferSize] = {}; + auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0)); + if (result == 0) { + return Error(); + } else if (result < 0) { + return ErrnoError(); + } + return std::string(buffer, result); +} + +template +Result SendMessage(int socket, const T& message) { + std::string message_string; + if (!message.SerializeToString(&message_string)) { + return Error() << "Unable to serialize message"; + } + + if (message_string.size() > kBufferSize) { + return Error() << "Serialized message too long to send"; + } + + if (auto result = + TEMP_FAILURE_RETRY(send(socket, message_string.c_str(), message_string.size(), 0)); + result != static_cast(message_string.size())) { + return ErrnoError() << "send() failed to send message contents"; + } + return {}; +} + +} // namespace init +} // namespace android diff --git a/init/subcontext.cpp b/init/subcontext.cpp index 00f91d830..ec93b5837 100644 --- a/init/subcontext.cpp +++ b/init/subcontext.cpp @@ -18,16 +18,17 @@ #include #include -#include #include #include #include +#include #include #include #include "action.h" #include "builtins.h" +#include "proto_utils.h" #include "util.h" #if defined(__ANDROID__) @@ -59,45 +60,6 @@ const char* const paths_and_secontexts[2][2] = { namespace { -constexpr size_t kBufferSize = 4096; - -Result ReadMessage(int socket) { - char buffer[kBufferSize] = {}; - auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0)); - if (result == 0) { - return Error(); - } else if (result < 0) { - return ErrnoError(); - } - return std::string(buffer, result); -} - -template -Result SendMessage(int socket, const T& message) { - std::string message_string; - if (!message.SerializeToString(&message_string)) { - return Error() << "Unable to serialize message"; - } - - if (message_string.size() > kBufferSize) { - return Error() << "Serialized message too long to send"; - } - - if (auto result = - TEMP_FAILURE_RETRY(send(socket, message_string.c_str(), message_string.size(), 0)); - result != static_cast(message_string.size())) { - return ErrnoError() << "send() failed to send message contents"; - } - return {}; -} - -std::vector> properties_to_set; - -uint32_t SubcontextPropertySet(const std::string& name, const std::string& value) { - properties_to_set.emplace_back(name, value); - return 0; -} - class SubcontextProcess { public: SubcontextProcess(const BuiltinFunctionMap* function_map, std::string context, int init_fd) @@ -131,14 +93,6 @@ void SubcontextProcess::RunCommand(const SubcontextCommand::ExecuteCommand& exec result = RunBuiltinFunction(map_result->function, args, context_); } - for (const auto& [name, value] : properties_to_set) { - auto property = reply->add_properties_to_set(); - property->set_name(name); - property->set_value(value); - } - - properties_to_set.clear(); - if (result) { reply->set_success(true); } else { @@ -224,7 +178,10 @@ int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map SelabelInitialize(); - property_set = SubcontextPropertySet; + property_set = [](const std::string& key, const std::string& value) -> uint32_t { + android::base::SetProperty(key, value); + return 0; + }; auto subcontext_process = SubcontextProcess(function_map, context, init_fd); subcontext_process.MainLoop(); @@ -311,15 +268,6 @@ Result Subcontext::Execute(const std::vector& args) { return subcontext_reply.error(); } - for (const auto& property : subcontext_reply->properties_to_set()) { - ucred cr = {.pid = pid_, .uid = 0, .gid = 0}; - std::string error; - if (HandlePropertySet(property.name(), property.value(), context_, cr, &error) != 0) { - LOG(ERROR) << "Subcontext init could not set '" << property.name() << "' to '" - << property.value() << "': " << error; - } - } - if (subcontext_reply->reply_case() == SubcontextReply::kFailure) { auto& failure = subcontext_reply->failure(); return ResultError(failure.error_string(), failure.error_errno()); diff --git a/init/subcontext.proto b/init/subcontext.proto index c31f4fb68..e68115e0e 100644 --- a/init/subcontext.proto +++ b/init/subcontext.proto @@ -38,10 +38,4 @@ message SubcontextReply { Failure failure = 2; ExpandArgsReply expand_args_reply = 3; } - - message PropertyToSet { - optional string name = 1; - optional string value = 2; - } - repeated PropertyToSet properties_to_set = 4; } \ No newline at end of file