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

Commit 0d061b25 authored by Daniel Norman's avatar Daniel Norman Committed by Gerrit Code Review
Browse files

Merge "Adds check_interface_{restart,start,stop} check_builtins."

parents f9d53272 d2533c33
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ cc_defaults {
        "libfscrypt",
        "libgsi",
        "libhidl-gen-utils",
        "libjsoncpp",
        "libkeyutils",
        "liblog",
        "liblogwrap",
@@ -118,6 +119,7 @@ cc_library_static {
        "first_stage_mount.cpp",
        "import_parser.cpp",
        "init.cpp",
        "interface_utils.cpp",
        "keychords.cpp",
        "modalias_handler.cpp",
        "mount_handler.cpp",
@@ -242,7 +244,10 @@ genrule {
    name: "generated_stub_builtin_function_map",
    tool_files: ["host_builtin_map.py"],
    out: ["generated_stub_builtin_function_map.h"],
    srcs: ["builtins.cpp", "check_builtins.cpp"],
    srcs: [
        "builtins.cpp",
        "check_builtins.cpp",
    ],
    cmd: "$(location host_builtin_map.py) --builtins $(location builtins.cpp) --check_builtins $(location check_builtins.cpp) > $(out)",
}

@@ -278,6 +283,7 @@ cc_binary {
        "epoll.cpp",
        "keychords.cpp",
        "import_parser.cpp",
        "interface_utils.cpp",
        "host_import_parser.cpp",
        "host_init_verifier.cpp",
        "parser.cpp",
+16 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <android-base/strings.h>

#include "builtin_arguments.h"
#include "interface_utils.h"
#include "rlimit_parser.h"
#include "service.h"
#include "util.h"
@@ -80,6 +81,21 @@ Result<void> check_exec_background(const BuiltinArguments& args) {
    return check_exec(std::move(args));
}

Result<void> check_interface_restart(const BuiltinArguments& args) {
    if (auto result = IsKnownInterface(args[1]); !result) {
        return result.error();
    }
    return {};
}

Result<void> check_interface_start(const BuiltinArguments& args) {
    return check_interface_restart(std::move(args));
}

Result<void> check_interface_stop(const BuiltinArguments& args) {
    return check_interface_restart(std::move(args));
}

Result<void> check_load_system_props(const BuiltinArguments& args) {
    return Error() << "'load_system_props' is deprecated";
}
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ namespace init {
Result<void> check_chown(const BuiltinArguments& args);
Result<void> check_exec(const BuiltinArguments& args);
Result<void> check_exec_background(const BuiltinArguments& args);
Result<void> check_interface_restart(const BuiltinArguments& args);
Result<void> check_interface_start(const BuiltinArguments& args);
Result<void> check_interface_stop(const BuiltinArguments& args);
Result<void> check_load_system_props(const BuiltinArguments& args);
Result<void> check_loglevel(const BuiltinArguments& args);
Result<void> check_mkdir(const BuiltinArguments& args);
+11 −35
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/strings.h>
#include <json/json.h>

#include "action.h"
#include "action_manager.h"
@@ -38,6 +37,7 @@
#include "check_builtins.h"
#include "host_import_parser.h"
#include "host_init_stubs.h"
#include "interface_utils.h"
#include "parser.h"
#include "result.h"
#include "service.h"
@@ -132,35 +132,6 @@ passwd* getpwnam(const char* login) { // NOLINT: implementing bad function.
    return nullptr;
}

static std::optional<android::init::InterfaceInheritanceHierarchyMap>
ReadInterfaceInheritanceHierarchy(const std::string& interface_inheritance_hierarchy_file) {
    if (interface_inheritance_hierarchy_file.empty()) {
        LOG(WARNING) << "Missing an interface inheritance hierarchy file.";
        return {};
    }

    Json::Value root;
    Json::Reader reader;
    std::ifstream stream(interface_inheritance_hierarchy_file);
    if (!reader.parse(stream, root)) {
        LOG(ERROR) << "Failed to read interface inheritance hierarchy file: "
                   << interface_inheritance_hierarchy_file << "\n"
                   << reader.getFormattedErrorMessages();
        return {};
    }

    android::init::InterfaceInheritanceHierarchyMap result;
    for (const Json::Value& entry : root) {
        std::set<std::string> inherited_interfaces;
        for (const Json::Value& intf : entry["inheritedInterfaces"]) {
            inherited_interfaces.insert(intf.asString());
        }
        result[entry["interface"].asString()] = inherited_interfaces;
    }

    return result;
}

namespace android {
namespace init {

@@ -222,16 +193,21 @@ int main(int argc, char** argv) {
        return EXIT_FAILURE;
    }

    auto interface_inheritance_hierarchy_map =
            ReadInterfaceInheritanceHierarchy(interface_inheritance_hierarchy_file);
    if (!interface_inheritance_hierarchy_map) {
        LOG(ERROR) << interface_inheritance_hierarchy_map.error();
        return EXIT_FAILURE;
    }
    SetKnownInterfaces(*interface_inheritance_hierarchy_map);

    const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
    Action::set_function_map(&function_map);
    ActionManager& am = ActionManager::GetInstance();
    ServiceList& sl = ServiceList::GetInstance();
    Parser parser;
    parser.AddSectionParser(
            "service",
            std::make_unique<ServiceParser>(
                    &sl, nullptr,
                    ReadInterfaceInheritanceHierarchy(interface_inheritance_hierarchy_file)));
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(
                                               &sl, nullptr, *interface_inheritance_hierarchy_map));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
    parser.AddSectionParser("import", std::make_unique<HostImportParser>());

+149 −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 "interface_utils.h"

#include <fstream>
#include <sstream>

#include <android-base/strings.h>
#include <hidl-util/FqInstance.h>
#include <json/json.h>

using android::FqInstance;
using android::FQName;
using android::base::Error;

namespace android {
namespace init {

namespace {

std::string FQNamesToString(const std::set<FQName>& fqnames) {
    std::set<std::string> fqname_strings;
    for (const FQName& fqname : fqnames) {
        fqname_strings.insert(fqname.string());
    }
    return android::base::Join(fqname_strings, " ");
}

}  // namespace

Result<InterfaceInheritanceHierarchyMap> ReadInterfaceInheritanceHierarchy(
        const std::string& path) {
    Json::Value root;
    Json::Reader reader;
    std::ifstream stream(path);
    if (!reader.parse(stream, root)) {
        return Error() << "Failed to read interface inheritance hierarchy file: " << path << "\n"
                       << reader.getFormattedErrorMessages();
    }

    InterfaceInheritanceHierarchyMap result;
    for (const Json::Value& entry : root) {
        std::set<FQName> inherited_interfaces;
        for (const Json::Value& intf : entry["inheritedInterfaces"]) {
            FQName fqname;
            if (!fqname.setTo(intf.asString())) {
                return Error() << "Unable to parse interface '" << intf.asString() << "'";
            }
            inherited_interfaces.insert(fqname);
        }
        std::string intf_string = entry["interface"].asString();
        FQName fqname;
        if (!fqname.setTo(intf_string)) {
            return Error() << "Unable to parse interface '" << intf_string << "'";
        }
        result[fqname] = inherited_interfaces;
    }

    return result;
}

Result<void> CheckInterfaceInheritanceHierarchy(const std::set<std::string>& instances,
                                                const InterfaceInheritanceHierarchyMap& hierarchy) {
    std::set<FQName> interface_fqnames;
    for (const std::string& instance : instances) {
        FqInstance fqinstance;
        if (!fqinstance.setTo(instance)) {
            return Error() << "Unable to parse interface instance '" << instance << "'";
        }
        interface_fqnames.insert(fqinstance.getFqName());
    }
    return CheckInterfaceInheritanceHierarchy(interface_fqnames, hierarchy);
}

Result<void> CheckInterfaceInheritanceHierarchy(const std::set<FQName>& interfaces,
                                                const InterfaceInheritanceHierarchyMap& hierarchy) {
    std::ostringstream error_stream;
    for (const FQName& intf : interfaces) {
        if (hierarchy.count(intf) == 0) {
            error_stream << "\nInterface is not in the known set of hidl_interfaces: '"
                         << intf.string()
                         << "'. Please ensure the interface is spelled correctly and built "
                         << "by a hidl_interface target.";
            continue;
        }
        const std::set<FQName>& required_interfaces = hierarchy.at(intf);
        std::set<FQName> diff;
        std::set_difference(required_interfaces.begin(), required_interfaces.end(),
                            interfaces.begin(), interfaces.end(),
                            std::inserter(diff, diff.begin()));
        if (!diff.empty()) {
            error_stream << "\nInterface '" << intf.string() << "' requires its full inheritance "
                         << "hierarchy to be listed in this init_rc file. Missing "
                         << "interfaces: [" << FQNamesToString(diff) << "]";
        }
    }
    const std::string& errors = error_stream.str();
    if (!errors.empty()) {
        return Error() << errors;
    }

    return {};
}

std::optional<std::set<FQName>> known_interfaces;

void SetKnownInterfaces(const InterfaceInheritanceHierarchyMap& hierarchy) {
    known_interfaces = std::set<FQName>();
    for (const auto& [intf, inherited_interfaces] : hierarchy) {
        known_interfaces->insert(intf);
    }
}

Result<void> IsKnownInterface(const std::string& instance) {
    FqInstance fqinstance;
    if (!fqinstance.setTo(instance)) {
        return Error() << "Unable to parse interface instance '" << instance << "'";
    }
    return IsKnownInterface(fqinstance.getFqName());
}

Result<void> IsKnownInterface(const FQName& intf) {
    if (!known_interfaces) {
        return Error() << "No known interfaces have been loaded.";
    }
    if (known_interfaces->count(intf) == 0) {
        return Error() << "Interface is not in the known set of hidl_interfaces: '" << intf.string()
                       << "'. Please ensure the interface is spelled correctly and built "
                       << "by a hidl_interface target.";
    }
    return {};
}

}  // namespace init
}  // namespace android
Loading