Listen on property_service_for_system socket
It is easy to dos the property_service socket, since it will wait for a
complete data packet from one command before moving on to the next one.
To prevent low privilege apps interfering with system and root apps,
add a second property_service socket that only they can use
Bug: 262237198
Test: Run POC in one shell, set properties as root and system in another
Ignore-AOSP-First: Security fix
Change-Id: I1d6fec833fc24352546bb90f770d3c4b675f5716
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 87ffdb9..14e55b3 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -57,12 +57,12 @@
#include <android-base/result.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <private/android_filesystem_config.h>
#include <property_info_parser/property_info_parser.h>
#include <property_info_serializer/property_info_serializer.h>
#include <selinux/android.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
-
#include "debug_ramdisk.h"
#include "epoll.h"
#include "init.h"
@@ -111,12 +111,13 @@
static bool persistent_properties_loaded = false;
-static int property_set_fd = -1;
static int from_init_socket = -1;
static int init_socket = -1;
static bool accept_messages = false;
static std::mutex accept_messages_lock;
static std::thread property_service_thread;
+static std::thread property_service_for_system_thread;
+static std::mutex set_property_lock;
static std::unique_ptr<PersistWriteThread> persist_write_thread;
@@ -394,6 +395,7 @@
return {PROP_ERROR_INVALID_VALUE};
}
+ auto lock = std::lock_guard{set_property_lock};
prop_info* pi = (prop_info*)__system_property_find(name.c_str());
if (pi != nullptr) {
// ro.* properties are actually "write-once".
@@ -582,10 +584,10 @@
return *ret;
}
-static void handle_property_set_fd() {
+static void handle_property_set_fd(int fd) {
static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */
- int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);
+ int s = accept4(fd, nullptr, nullptr, SOCK_CLOEXEC);
if (s == -1) {
return;
}
@@ -1422,19 +1424,21 @@
}
}
-static void PropertyServiceThread() {
+static void PropertyServiceThread(int fd, bool listen_init) {
Epoll epoll;
if (auto result = epoll.Open(); !result.ok()) {
LOG(FATAL) << result.error();
}
- if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd);
+ if (auto result = epoll.RegisterHandler(fd, std::bind(handle_property_set_fd, fd));
!result.ok()) {
LOG(FATAL) << result.error();
}
- if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {
- LOG(FATAL) << result.error();
+ if (listen_init) {
+ if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {
+ LOG(FATAL) << result.error();
+ }
}
while (true) {
@@ -1485,6 +1489,23 @@
cv_.notify_all();
}
+void StartThread(const char* name, int mode, int gid, std::thread& t, bool listen_init) {
+ int fd = -1;
+ if (auto result = CreateSocket(name, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
+ /*passcred=*/false, /*should_listen=*/false, mode, /*uid=*/0,
+ /*gid=*/gid, /*socketcon=*/{});
+ result.ok()) {
+ fd = *result;
+ } else {
+ LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
+ }
+
+ listen(fd, 8);
+
+ auto new_thread = std::thread(PropertyServiceThread, fd, listen_init);
+ t.swap(new_thread);
+}
+
void StartPropertyService(int* epoll_socket) {
InitPropertySet("ro.property_service.version", "2");
@@ -1496,19 +1517,9 @@
init_socket = sockets[1];
StartSendingMessages();
- if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
- /*passcred=*/false, /*should_listen=*/false, 0666, /*uid=*/0,
- /*gid=*/0, /*socketcon=*/{});
- result.ok()) {
- property_set_fd = *result;
- } else {
- LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
- }
-
- listen(property_set_fd, 8);
-
- auto new_thread = std::thread{PropertyServiceThread};
- property_service_thread.swap(new_thread);
+ StartThread(PROP_SERVICE_FOR_SYSTEM_NAME, 0660, AID_SYSTEM, property_service_for_system_thread,
+ true);
+ StartThread(PROP_SERVICE_NAME, 0666, 0, property_service_thread, false);
auto async_persist_writes =
android::base::GetBoolProperty("ro.property_service.async_persist_writes", false);