Use subcontext for APEX configs from /{vendor, odm}

Instead of using config file path, use APEX's preinstalled path to
determine whether to use subcontext or not for APEX configs.

Bug: 232021354
Test: CtsInitTestCases, CtsBluetoothTestCases
Change-Id: Iba603f09602f0bec3113e2be3d15c62055c09e72
This commit is contained in:
Jooyung Han 2022-05-10 05:35:35 +09:00
parent 1eb3394e9c
commit 38e8e74550
3 changed files with 68 additions and 7 deletions

View file

@ -85,6 +85,10 @@
#include "system/core/init/property_service.pb.h"
#include "util.h"
#ifndef RECOVERY
#include "com_android_apex.h"
#endif // RECOVERY
using namespace std::chrono_literals;
using namespace std::string_literals;
@ -293,14 +297,58 @@ Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
return parser;
}
#ifndef RECOVERY
template <typename T>
struct LibXmlErrorHandler {
T handler_;
template <typename Handler>
LibXmlErrorHandler(Handler&& handler) : handler_(std::move(handler)) {
xmlSetGenericErrorFunc(nullptr, &ErrorHandler);
}
~LibXmlErrorHandler() { xmlSetGenericErrorFunc(nullptr, nullptr); }
static void ErrorHandler(void*, const char* msg, ...) {
va_list args;
va_start(args, msg);
char* formatted;
if (vasprintf(&formatted, msg, args) >= 0) {
LOG(ERROR) << formatted;
}
free(formatted);
va_end(args);
}
};
template <typename Handler>
LibXmlErrorHandler(Handler&&) -> LibXmlErrorHandler<Handler>;
#endif // RECOVERY
// Returns a Parser that accepts scripts from APEX modules. It supports `service` and `on`.
Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list) {
Parser parser;
parser.AddSectionParser(
"service", std::make_unique<ServiceParser>(&service_list, GetSubcontext(), std::nullopt,
/*from_apex=*/true));
parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
auto subcontext = GetSubcontext();
#ifndef RECOVERY
if (subcontext) {
const auto apex_info_list_file = "/apex/apex-info-list.xml";
auto error_handler = LibXmlErrorHandler([&](const auto& error_message) {
LOG(ERROR) << "Failed to read " << apex_info_list_file << ":" << error_message;
});
const auto apex_info_list = com::android::apex::readApexInfoList(apex_info_list_file);
if (apex_info_list.has_value()) {
std::vector<std::string> subcontext_apexes;
for (const auto& info : apex_info_list->getApexInfo()) {
if (info.hasPreinstalledModulePath() &&
subcontext->PathMatchesSubcontext(info.getPreinstalledModulePath())) {
subcontext_apexes.push_back(info.getModuleName());
}
}
subcontext->SetApexList(std::move(subcontext_apexes));
}
}
#endif // RECOVERY
parser.AddSectionParser("service",
std::make_unique<ServiceParser>(&service_list, subcontext, std::nullopt,
/*from_apex=*/true));
parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontext));
return parser;
}

View file

@ -250,7 +250,14 @@ void Subcontext::Restart() {
Fork();
}
bool Subcontext::PathMatchesSubcontext(const std::string& path) {
bool Subcontext::PathMatchesSubcontext(const std::string& path) const {
static const std::string kApexDir = "/apex/";
if (StartsWith(path, kApexDir)) {
auto begin = kApexDir.size();
auto end = path.find('/', begin);
auto apex_name = path.substr(begin, end - begin);
return std::find(apex_list_.begin(), apex_list_.end(), apex_name) != apex_list_.end();
}
for (const auto& prefix : path_prefixes_) {
if (StartsWith(path, prefix)) {
return true;
@ -259,6 +266,10 @@ bool Subcontext::PathMatchesSubcontext(const std::string& path) {
return false;
}
void Subcontext::SetApexList(std::vector<std::string>&& apex_list) {
apex_list_ = std::move(apex_list);
}
Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& subcontext_command) {
if (auto result = SendMessage(socket_, subcontext_command); !result.ok()) {
Restart();

View file

@ -46,7 +46,8 @@ class Subcontext {
Result<void> Execute(const std::vector<std::string>& args);
Result<std::vector<std::string>> ExpandArgs(const std::vector<std::string>& args);
void Restart();
bool PathMatchesSubcontext(const std::string& path);
bool PathMatchesSubcontext(const std::string& path) const;
void SetApexList(std::vector<std::string>&& apex_list);
const std::string& context() const { return context_; }
pid_t pid() const { return pid_; }
@ -56,6 +57,7 @@ class Subcontext {
Result<SubcontextReply> TransmitMessage(const SubcontextCommand& subcontext_command);
std::vector<std::string> path_prefixes_;
std::vector<std::string> apex_list_;
std::string context_;
pid_t pid_;
android::base::unique_fd socket_;