Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba485e7f authored by Xin Li's avatar Xin Li Committed by Gerrit Code Review
Browse files

Merge "Merge Android 14 QPR2 to AOSP main" into main

parents 1140355b 2f5e50cf
Loading
Loading
Loading
Loading
+64 −45
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <fs_mgr.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>
@@ -117,12 +118,13 @@ constexpr auto DIGEST_SIZE_USED = 8;

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::mutex selinux_check_access_lock;
static std::thread property_service_thread;
static std::thread property_service_for_system_thread;

static std::unique_ptr<PersistWriteThread> persist_write_thread;

@@ -167,6 +169,7 @@ bool CanReadProperty(const std::string& source_context, const std::string& name)
    ucred cr = {.pid = 0, .uid = 0, .gid = 0};
    audit_data.cr = &cr;

    auto lock = std::lock_guard{selinux_check_access_lock};
    return selinux_check_access(source_context.c_str(), target_context, "file", "read",
                                &audit_data) == 0;
}
@@ -182,10 +185,9 @@ static bool CheckMacPerms(const std::string& name, const char* target_context,
    audit_data.name = name.c_str();
    audit_data.cr = &cr;

    bool has_access = (selinux_check_access(source_context, target_context, "property_service",
                                            "set", &audit_data) == 0);

    return has_access;
    auto lock = std::lock_guard{selinux_check_access_lock};
    return selinux_check_access(source_context, target_context, "property_service", "set",
                                &audit_data) == 0;
}

void NotifyPropertyChange(const std::string& name, const std::string& value) {
@@ -400,6 +402,11 @@ static std::optional<uint32_t> PropertySet(const std::string& name, const std::s
        return {PROP_ERROR_INVALID_VALUE};
    }

    if (name == "sys.powerctl") {
        // No action here - NotifyPropertyChange will trigger the appropriate action, and since this
        // can come to the second thread, we mustn't call out to the __system_property_* functions
        // which support multiple readers but only one mutator.
    } else {
        prop_info* pi = (prop_info*)__system_property_find(name.c_str());
        if (pi != nullptr) {
            // ro.* properties are actually "write-once".
@@ -417,6 +424,8 @@ static std::optional<uint32_t> PropertySet(const std::string& name, const std::s
            }
        }

        // Don't write properties to disk until after we have read all default
        // properties to prevent them from being overwritten by default values.
        bool need_persist = StartsWith(name, "persist.") || StartsWith(name, "next_boot.");
        if (socket && persistent_properties_loaded && need_persist) {
            if (persist_write_thread) {
@@ -425,6 +434,7 @@ static std::optional<uint32_t> PropertySet(const std::string& name, const std::s
            }
            WritePersistentProperty(name, value);
        }
    }

    NotifyPropertyChange(name, value);
    return {PROP_SUCCESS};
@@ -584,10 +594,10 @@ uint32_t HandlePropertySetNoSocket(const std::string& name, const std::string& v
    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;
    }
@@ -1301,7 +1311,7 @@ void CreateSerializedPropertyInfo() {
    mkdir(APPCOMPAT_OVERRIDE_PROP_FOLDERNAME, S_IRWXU | S_IXGRP | S_IXOTH);
    if (!WriteStringToFile(serialized_contexts, APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0444, 0, 0,
                           false)) {
        PLOG(ERROR) << "Unable to write vendor overrides to file";
        PLOG(ERROR) << "Unable to write appcompat override property infos to file";
    }
    selinux_android_restorecon(APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0);
}
@@ -1438,20 +1448,22 @@ static void HandleInitSocket() {
    }
}

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 (listen_init) {
        if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {
            LOG(FATAL) << result.error();
        }
    }

    while (true) {
        auto epoll_result = epoll.Wait(std::nullopt);
@@ -1499,6 +1511,23 @@ void PersistWriteThread::Write(std::string name, std::string value, SocketConnec
    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");

@@ -1510,19 +1539,9 @@ void StartPropertyService(int* epoll_socket) {
    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);
+25 −4
Original line number Diff line number Diff line
@@ -301,6 +301,12 @@ static int memfd_create_region(const char* name, size_t size) {
        return -1;
    }

    // forbid size changes to match ashmem behaviour
    if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) == -1) {
        ALOGE("memfd_create(%s, %zd) F_ADD_SEALS failed: %m", name, size);
        return -1;
    }

    if (debug_log) {
        ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
    }
@@ -352,14 +358,29 @@ error:
}

static int memfd_set_prot_region(int fd, int prot) {
    /* Only proceed if an fd needs to be write-protected */
    int seals = fcntl(fd, F_GET_SEALS);
    if (seals == -1) {
        ALOGE("memfd_set_prot_region(%d, %d): F_GET_SEALS failed: %s\n", fd, prot, strerror(errno));
        return -1;
    }

    if (prot & PROT_WRITE) {
        /* Now we want the buffer to be read-write, let's check if the buffer
         * has been previously marked as read-only before, if so return error
         */
        if (seals & F_SEAL_FUTURE_WRITE) {
            ALOGE("memfd_set_prot_region(%d, %d): region is write protected\n", fd, prot);
            errno = EINVAL;  // inline with ashmem error code, if already in
                             // read-only mode
            return -1;
        }
        return 0;
    }

    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
              strerror(errno));
    /* We would only allow read-only for any future file operations */
    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE | F_SEAL_SEAL) == -1) {
        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE | F_SEAL_SEAL seal failed: %s\n",
              fd, prot, strerror(errno));
        return -1;
    }