Merge changes Id9534a59,I3ee81536

* changes:
  init: run property service in a thread
  Revert "init: Handle properties in the background of calling fs_mgr"
This commit is contained in:
Tom Cherry 2019-08-22 17:24:18 +00:00 committed by Gerrit Code Review
commit afe45ab5f2
10 changed files with 365 additions and 201 deletions

View file

@ -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",

View file

@ -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<void> 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<void> 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<void> 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<void> 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<void> do_setprop(const BuiltinArguments& args) {
if (StartsWith(args[1], "ctl.")) {
return Error()
<< "Cannot set ctl. properties from init; call the Service functions directly";
}
if (args[1] == kRestoreconProperty) {
return Error() << "Cannot set '" << kRestoreconProperty
<< "' from init; use the restorecon builtin directly";
}
property_set(args[1], args[2]);
return {};
}
@ -1017,7 +1012,20 @@ static Result<void> do_loglevel(const BuiltinArguments& args) {
}
static Result<void> 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 {};
}

View file

@ -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<Timer> 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();

View file

@ -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

View file

@ -39,10 +39,10 @@
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>
#include <atomic>
#include <map>
#include <memory>
#include <mutex>
#include <optional>
#include <queue>
#include <thread>
#include <vector>
@ -53,7 +53,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <property_info_parser/property_info_parser.h>
#include <property_info_serializer/property_info_serializer.h>
#include <selinux/android.h>
@ -61,11 +60,14 @@
#include <selinux/selinux.h>
#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<std::optional<SocketConnection>> pending_control_message_results;
static uint32_t SendControlMessage(const std::string& msg, const std::string& name, pid_t pid,
std::string* error) {
auto property_msg = PropertyMessage{};
auto* control_message = property_msg.mutable_control_message();
control_message->set_msg(msg);
control_message->set_name(name);
control_message->set_pid(pid);
if (auto result = SendMessage(init_socket, property_msg); !result) {
*error = "Failed to send control message: " + result.error().message();
return PROP_ERROR_HANDLE_CONTROL_MESSAGE;
}
return PROP_SUCCESS;
}
void HandleControlResponse(const InitMessage& init_message) {
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<int> CallFunctionAndHandlePropertiesImpl(const std::function<int()>& 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<bool> 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

View file

@ -18,34 +18,22 @@
#include <sys/socket.h>
#include <functional>
#include <string>
#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 <typename F, typename... Args>
Result<int> CallFunctionAndHandleProperties(F&& f, Args&&... args) {
Result<int> CallFunctionAndHandlePropertiesImpl(const std::function<int()>& f);
auto func = [&] { return f(args...); };
return CallFunctionAndHandlePropertiesImpl(func);
}
void StartPropertyService(int* epoll_socket);
} // namespace init
} // namespace android

View file

@ -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;
};
}

62
init/proto_utils.h Normal file
View file

@ -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 <sys/socket.h>
#include <unistd.h>
#include <string>
#include "result.h"
namespace android {
namespace init {
constexpr size_t kBufferSize = 4096;
inline Result<std::string> 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 <typename T>
Result<void> 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<long>(message_string.size())) {
return ErrnoError() << "send() failed to send message contents";
}
return {};
}
} // namespace init
} // namespace android

View file

@ -18,16 +18,17 @@
#include <fcntl.h>
#include <poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <selinux/android.h>
#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<std::string> 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 <typename T>
Result<void> 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<long>(message_string.size())) {
return ErrnoError() << "send() failed to send message contents";
}
return {};
}
std::vector<std::pair<std::string, std::string>> 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<void> Subcontext::Execute(const std::vector<std::string>& 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());

View file

@ -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;
}