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

Commit 8106c8e0 authored by Suren Baghdasaryan's avatar Suren Baghdasaryan Committed by Gerrit Code Review
Browse files

Merge changes from topic "native process registration"

* changes:
  init: Add support for native service registration with lmkd
  lmkd: Support process types when registering a process
  lmkd: Add library function to unregister a process
  lmkd: Prepare lmkd to support connection from init process
  lmkd: Restrict process record modifications to the client that created it
parents be49555b c29c2baa
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ cc_defaults {
        "libavb",
        "libc++fs",
        "libcgrouprc_format",
        "liblmkd_utils",
        "libmodprobe",
        "libprotobuf-cpp-lite",
        "libpropertyinfoserializer",
@@ -118,6 +119,7 @@ cc_library_static {
        "init.cpp",
        "interface_utils.cpp",
        "keychords.cpp",
        "lmkd_service.cpp",
        "modalias_handler.cpp",
        "mount_handler.cpp",
        "mount_namespace.cpp",
+9 −2
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@
#include "first_stage_mount.h"
#include "import_parser.h"
#include "keychords.h"
#include "lmkd_service.h"
#include "mount_handler.h"
#include "mount_namespace.h"
#include "property_service.h"
@@ -684,9 +685,15 @@ int SecondStageMain(int argc, char** argv) {
    InitKernelLogging(argv);
    LOG(INFO) << "init second stage started!";

    // Will handle EPIPE at the time of write by checking the errno
    signal(SIGPIPE, SIG_IGN);

    // Set init and its forked children's oom_adj.
    if (auto result = WriteFile("/proc/1/oom_score_adj", "-1000"); !result) {
        LOG(ERROR) << "Unable to write -1000 to /proc/1/oom_score_adj: " << result.error();
    if (auto result =
                WriteFile("/proc/1/oom_score_adj", StringPrintf("%d", DEFAULT_OOM_SCORE_ADJUST));
        !result) {
        LOG(ERROR) << "Unable to write " << DEFAULT_OOM_SCORE_ADJUST
                   << " to /proc/1/oom_score_adj: " << result.error();
    }

    // Set up a session keyring that all processes will have access to. It

init/lmkd_service.cpp

0 → 100644
+131 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#include "lmkd_service.h"

#include <errno.h>

#include <android-base/logging.h>
#include <liblmkd_utils.h>

#include "service_list.h"

namespace android {
namespace init {

enum LmkdRegistrationResult {
    LMKD_REG_SUCCESS,
    LMKD_CONN_FAILED,
    LMKD_REG_FAILED,
};

static int lmkd_socket = -1;

static LmkdRegistrationResult RegisterProcess(uid_t uid, pid_t pid, int oom_score_adjust) {
    // connect to lmkd if not already connected
    if (lmkd_socket < 0) {
        lmkd_socket = lmkd_connect();
        if (lmkd_socket < 0) {
            return LMKD_CONN_FAILED;
        }
    }

    // register service with lmkd
    struct lmk_procprio params;
    params.pid = pid;
    params.uid = uid;
    params.oomadj = oom_score_adjust;
    params.ptype = PROC_TYPE_SERVICE;
    if (lmkd_register_proc(lmkd_socket, &params) != 0) {
        // data transfer failed, reset the connection
        close(lmkd_socket);
        lmkd_socket = -1;
        return LMKD_REG_FAILED;
    }

    return LMKD_REG_SUCCESS;
}

static bool UnregisterProcess(pid_t pid) {
    if (lmkd_socket < 0) {
        // no connection or it was lost, no need to unregister
        return false;
    }

    // unregister service
    struct lmk_procremove params;
    params.pid = pid;
    if (lmkd_unregister_proc(lmkd_socket, &params) != 0) {
        // data transfer failed, reset the connection
        close(lmkd_socket);
        lmkd_socket = -1;
        return false;
    }

    return true;
}

static void RegisterServices(pid_t exclude_pid) {
    for (const auto& service : ServiceList::GetInstance().services()) {
        auto svc = service.get();
        if (svc->oom_score_adjust() != DEFAULT_OOM_SCORE_ADJUST) {
            // skip if process is excluded or not yet forked (pid==0)
            if (svc->pid() == exclude_pid || svc->pid() == 0) {
                continue;
            }
            if (RegisterProcess(svc->uid(), svc->pid(), svc->oom_score_adjust()) !=
                LMKD_REG_SUCCESS) {
                // a failure here resets the connection, will retry during next registration
                break;
            }
        }
    }
}

void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust) {
    bool new_connection = lmkd_socket == -1;
    LmkdRegistrationResult result;

    result = RegisterProcess(uid, pid, oom_score_adjust);
    if (result == LMKD_REG_FAILED) {
        // retry one time if connection to lmkd was lost
        result = RegisterProcess(uid, pid, oom_score_adjust);
        new_connection = result == LMKD_REG_SUCCESS;
    }
    switch (result) {
        case LMKD_REG_SUCCESS:
            // register existing services once new connection is established
            if (new_connection) {
                RegisterServices(pid);
            }
            break;
        case LMKD_CONN_FAILED:
            PLOG(ERROR) << "lmkd connection failed when " << name << " process got started";
            break;
        case LMKD_REG_FAILED:
            PLOG(ERROR) << "lmkd failed to register " << name << " process";
            break;
    }
}

void LmkdUnregister(const std::string& name, pid_t pid) {
    if (!UnregisterProcess(pid)) {
        PLOG(ERROR) << "lmkd failed to unregister " << name << " process";
    }
}

}  // namespace init
}  // namespace android

init/lmkd_service.h

0 → 100644
+44 −0
Original line number Diff line number Diff line
/*
 * 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/types.h>

#include <string>

namespace android {
namespace init {

static const int MIN_OOM_SCORE_ADJUST = -1000;
static const int MAX_OOM_SCORE_ADJUST = 1000;
// service with default score is unkillable
static const int DEFAULT_OOM_SCORE_ADJUST = MIN_OOM_SCORE_ADJUST;

#if defined(__ANDROID__)

void LmkdRegister(const std::string& name, uid_t uid, pid_t pid, int oom_score_adjust);
void LmkdUnregister(const std::string& name, pid_t pid);

#else  // defined(__ANDROID__)

static inline void LmkdRegister(const std::string&, uid_t, pid_t, int) {}
static inline void LmkdUnregister(const std::string&, pid_t) {}

#endif  // defined(__ANDROID__)

}  // namespace init
}  // namespace android
+11 −2
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@
#include <processgroup/processgroup.h>
#include <selinux/selinux.h>

#include "lmkd_service.h"
#include "service_list.h"
#include "util.h"

@@ -151,7 +152,7 @@ Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
      seclabel_(seclabel),
      onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
                 "onrestart", {}),
      oom_score_adjust_(-1000),
      oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
      start_order_(0),
      args_(args) {}

@@ -199,6 +200,10 @@ void Service::KillProcessGroup(int signal) {

        if (r == 0) process_cgroup_empty_ = true;
    }

    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
        LmkdUnregister(name_, pid_);
    }
}

void Service::SetProcessAttributesAndCaps() {
@@ -502,7 +507,7 @@ Result<void> Service::Start() {
        return ErrnoError() << "Failed to fork";
    }

    if (oom_score_adjust_ != -1000) {
    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
        std::string oom_str = std::to_string(oom_score_adjust_);
        std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
        if (!WriteStringToFile(oom_str, oom_file)) {
@@ -563,6 +568,10 @@ Result<void> Service::Start() {
        }
    }

    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
        LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
    }

    NotifyStateChange("running");
    reboot_on_failure.Disable();
    return {};
Loading