From f1200fb1170e1fe6c2cd86bda0ebfcacde224953 Mon Sep 17 00:00:00 2001 From: Daniel Norman Date: Wed, 9 Mar 2022 10:49:26 -0800 Subject: [PATCH] Adds an init host lib for use in host_apex_verifier. Includes extracting the APEX-specific SDK version naming scheme filter logic so it can be reused when host_apex_verifier looks at rc files inside the APEX. Bug: 222121216 Test: Use in host_apex_verifier Change-Id: I0396a455f30d2de71525ccd3fa69c75576054048 --- init/Android.bp | 25 +++++++++++++++++++--- init/builtins.cpp | 51 ++------------------------------------------ init/parser.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++ init/parser.h | 6 ++++++ 4 files changed, 84 insertions(+), 52 deletions(-) diff --git a/init/Android.bp b/init/Android.bp index c39d163b8..dd67d04c0 100644 --- a/init/Android.bp +++ b/init/Android.bp @@ -532,8 +532,8 @@ genrule { cmd: "$(location host_builtin_map.py) --builtins $(location builtins.cpp) --check_builtins $(location check_builtins.cpp) > $(out)", } -cc_binary { - name: "host_init_verifier", +cc_defaults { + name: "init_host_defaults", host_supported: true, cflags: [ "-Wall", @@ -556,7 +556,6 @@ cc_binary { "libprocessgroup", "libprotobuf-cpp-lite", ], - srcs: init_common_sources + init_host_sources, proto: { type: "lite", }, @@ -574,6 +573,26 @@ cc_binary { }, } +cc_binary { + name: "host_init_verifier", + defaults: ["init_host_defaults"], + srcs: init_common_sources + init_host_sources, +} + +cc_library_host_static { + name: "libinit_host", + defaults: ["init_host_defaults"], + srcs: init_common_sources, + export_include_dirs: ["."], + proto: { + export_proto_headers: true, + }, + visibility: [ + // host_apex_verifier performs a subset of init.rc validation + "//system/apex/tools", + ], +} + sh_binary { name: "extra_free_kbytes.sh", src: "extra_free_kbytes.sh", diff --git a/init/builtins.cpp b/init/builtins.cpp index 0eb894bec..01db4f5da 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -1306,58 +1306,11 @@ static Result parse_apex_configs() { } globfree(&glob_result); - // Compare all files /apex/path.#rc and /apex/path.rc with the same "/apex/path" prefix, - // choosing the one with the highest # that doesn't exceed the system's SDK. - // (.rc == .0rc for ranking purposes) - // int active_sdk = android::base::GetIntProperty("ro.build.version.sdk", INT_MAX); - std::map> script_map; - - for (const auto& c : configs) { - int sdk = 0; - const std::vector parts = android::base::Split(c, "."); - std::string base; - if (parts.size() < 2) { - continue; - } - - // parts[size()-1], aka the suffix, should be "rc" or "#rc" - // any other pattern gets discarded - - const auto& suffix = parts[parts.size() - 1]; - if (suffix == "rc") { - sdk = 0; - } else { - char trailer[9] = {0}; - int r = sscanf(suffix.c_str(), "%d%8s", &sdk, trailer); - if (r != 2) { - continue; - } - if (strlen(trailer) > 2 || strcmp(trailer, "rc") != 0) { - continue; - } - } - - if (sdk < 0 || sdk > active_sdk) { - continue; - } - - base = parts[0]; - for (unsigned int i = 1; i < parts.size() - 1; i++) { - base = base + "." + parts[i]; - } - - // is this preferred over what we already have - auto it = script_map.find(base); - if (it == script_map.end() || it->second.second < sdk) { - script_map[base] = std::make_pair(c, sdk); - } - } - bool success = true; - for (const auto& m : script_map) { - success &= parser.ParseConfigFile(m.second.first); + for (const auto& c : parser.FilterVersionedConfigs(configs, active_sdk)) { + success &= parser.ParseConfigFile(c); } ServiceList::GetInstance().MarkServicesUpdate(); if (success) { diff --git a/init/parser.cpp b/init/parser.cpp index 5c18551e1..abc201742 100644 --- a/init/parser.cpp +++ b/init/parser.cpp @@ -18,6 +18,8 @@ #include +#include + #include #include #include @@ -154,6 +156,58 @@ bool Parser::ParseConfigFile(const std::string& path) { return true; } +std::vector Parser::FilterVersionedConfigs(const std::vector& configs, + int active_sdk) { + std::vector filtered_configs; + + std::map> script_map; + for (const auto& c : configs) { + int sdk = 0; + const std::vector parts = android::base::Split(c, "."); + std::string base; + if (parts.size() < 2) { + continue; + } + + // parts[size()-1], aka the suffix, should be "rc" or "#rc" + // any other pattern gets discarded + + const auto& suffix = parts[parts.size() - 1]; + if (suffix == "rc") { + sdk = 0; + } else { + char trailer[9] = {0}; + int r = sscanf(suffix.c_str(), "%d%8s", &sdk, trailer); + if (r != 2) { + continue; + } + if (strlen(trailer) > 2 || strcmp(trailer, "rc") != 0) { + continue; + } + } + + if (sdk < 0 || sdk > active_sdk) { + continue; + } + + base = parts[0]; + for (unsigned int i = 1; i < parts.size() - 1; i++) { + base = base + "." + parts[i]; + } + + // is this preferred over what we already have + auto it = script_map.find(base); + if (it == script_map.end() || it->second.second < sdk) { + script_map[base] = std::make_pair(c, sdk); + } + } + + for (const auto& m : script_map) { + filtered_configs.push_back(m.second.first); + } + return filtered_configs; +} + bool Parser::ParseConfigDir(const std::string& path) { LOG(INFO) << "Parsing directory " << path << "..."; std::unique_ptr config_dir(opendir(path.c_str()), closedir); diff --git a/init/parser.h b/init/parser.h index 95b0cd76e..2f4108fd0 100644 --- a/init/parser.h +++ b/init/parser.h @@ -76,6 +76,12 @@ class Parser { void AddSectionParser(const std::string& name, std::unique_ptr parser); void AddSingleLineParser(const std::string& prefix, LineCallback callback); + // Compare all files */path.#rc and */path.rc with the same path prefix. + // Keep the one with the highest # that doesn't exceed the system's SDK. + // (.rc == .0rc for ranking purposes) + std::vector FilterVersionedConfigs(const std::vector& configs, + int active_sdk); + // Host init verifier check file permissions. bool ParseConfigFileInsecure(const std::string& path);