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

Commit ad4aa9e1 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "init: Run restorecon_recursive asynchronously"

parents acb64737 62696908
Loading
Loading
Loading
Loading
+81 −7
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <sys/_system_properties.h>

#include <memory>
#include <queue>
#include <vector>

#include <android-base/file.h>
@@ -162,7 +163,7 @@ bool is_legal_property_name(const std::string& name) {
    return true;
}

uint32_t property_set(const std::string& name, const std::string& value) {
static uint32_t PropertySetImpl(const std::string& name, const std::string& value) {
    size_t valuelen = value.size();

    if (!is_legal_property_name(name)) {
@@ -176,12 +177,6 @@ uint32_t property_set(const std::string& name, const std::string& value) {
        return PROP_ERROR_INVALID_VALUE;
    }

    if (name == "selinux.restorecon_recursive" && valuelen > 0) {
        if (selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
            LOG(ERROR) << "Failed to restorecon_recursive " << value;
        }
    }

    prop_info* pi = (prop_info*) __system_property_find(name.c_str());
    if (pi != nullptr) {
        // ro.* properties are actually "write-once".
@@ -210,6 +205,85 @@ uint32_t property_set(const std::string& name, const std::string& value) {
    return PROP_SUCCESS;
}

typedef int (*PropertyAsyncFunc)(const std::string&, const std::string&);

struct PropertyChildInfo {
    pid_t pid;
    PropertyAsyncFunc func;
    std::string name;
    std::string value;
};

static std::queue<PropertyChildInfo> property_children;

static void PropertyChildLaunch() {
    auto& info = property_children.front();
    pid_t pid = fork();
    if (pid < 0) {
        LOG(ERROR) << "Failed to fork for property_set_async";
        while (!property_children.empty()) {
            property_children.pop();
        }
        return;
    }
    if (pid != 0) {
        info.pid = pid;
    } else {
        if (info.func(info.name, info.value) != 0) {
            LOG(ERROR) << "property_set_async(\"" << info.name << "\", \"" << info.value
                       << "\") failed";
        }
        exit(0);
    }
}

bool PropertyChildReap(pid_t pid) {
    if (property_children.empty()) {
        return false;
    }
    auto& info = property_children.front();
    if (info.pid != pid) {
        return false;
    }
    if (PropertySetImpl(info.name, info.value) != PROP_SUCCESS) {
        LOG(ERROR) << "Failed to set async property " << info.name;
    }
    property_children.pop();
    if (!property_children.empty()) {
        PropertyChildLaunch();
    }
    return true;
}

static uint32_t PropertySetAsync(const std::string& name, const std::string& value,
                                 PropertyAsyncFunc func) {
    if (value.empty()) {
        return PropertySetImpl(name, value);
    }

    PropertyChildInfo info;
    info.func = func;
    info.name = name;
    info.value = value;
    property_children.push(info);
    if (property_children.size() == 1) {
        PropertyChildLaunch();
    }
    return PROP_SUCCESS;
}

static int RestoreconRecursiveAsync(const std::string& name, const std::string& value) {
    return selinux_android_restorecon(value.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
}

uint32_t property_set(const std::string& name, const std::string& value) {
    if (name == "selinux.restorecon_recursive") {
        return PropertySetAsync(name, value, RestoreconRecursiveAsync);
    }

    return PropertySetImpl(name, value);
}

class SocketConnection {
 public:
  SocketConnection(int socket, const struct ucred& cred)
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ struct property_audit_data {
    const char* name;
};

extern bool PropertyChildReap(pid_t pid);

void property_init(void);
void property_load_boot_defaults(void);
void load_persist_props(void);
+2 −0
Original line number Diff line number Diff line
@@ -1085,6 +1085,8 @@ bool ServiceManager::ReapOneProcess() {
    } else if (pid == -1) {
        PLOG(ERROR) << "waitpid failed";
        return false;
    } else if (PropertyChildReap(pid)) {
        return true;
    }

    Service* svc = FindServiceByPid(pid);