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
This commit is contained in:
Daniel Norman 2022-03-09 10:49:26 -08:00
parent 81cc9d986f
commit f1200fb117
4 changed files with 84 additions and 52 deletions

View file

@ -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",

View file

@ -1306,58 +1306,11 @@ static Result<void> 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<std::string, std::pair<std::string, int>> script_map;
for (const auto& c : configs) {
int sdk = 0;
const std::vector<std::string> 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) {

View file

@ -18,6 +18,8 @@
#include <dirent.h>
#include <map>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
@ -154,6 +156,58 @@ bool Parser::ParseConfigFile(const std::string& path) {
return true;
}
std::vector<std::string> Parser::FilterVersionedConfigs(const std::vector<std::string>& configs,
int active_sdk) {
std::vector<std::string> filtered_configs;
std::map<std::string, std::pair<std::string, int>> script_map;
for (const auto& c : configs) {
int sdk = 0;
const std::vector<std::string> 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<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir);

View file

@ -76,6 +76,12 @@ class Parser {
void AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> 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<std::string> FilterVersionedConfigs(const std::vector<std::string>& configs,
int active_sdk);
// Host init verifier check file permissions.
bool ParseConfigFileInsecure(const std::string& path);