Loading init/Android.bp +7 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ cc_defaults { "libfscrypt", "libgsi", "libhidl-gen-utils", "libjsoncpp", "libkeyutils", "liblog", "liblogwrap", Loading Loading @@ -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", Loading Loading @@ -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)", } Loading Loading @@ -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", Loading init/check_builtins.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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"; } Loading init/check_builtins.h +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading init/host_init_verifier.cpp +11 −35 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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" Loading Loading @@ -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 { Loading Loading @@ -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>()); Loading init/interface_utils.cpp 0 → 100644 +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
init/Android.bp +7 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ cc_defaults { "libfscrypt", "libgsi", "libhidl-gen-utils", "libjsoncpp", "libkeyutils", "liblog", "liblogwrap", Loading Loading @@ -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", Loading Loading @@ -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)", } Loading Loading @@ -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", Loading
init/check_builtins.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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"; } Loading
init/check_builtins.h +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
init/host_init_verifier.cpp +11 −35 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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" Loading Loading @@ -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 { Loading Loading @@ -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>()); Loading
init/interface_utils.cpp 0 → 100644 +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