Use apexservice to get the list of apexes

In this change, the logic to get the list of apexes is replaced with
the query to apexservice, which is the source of truth. This dedups
the manual scanning of /apex for the apex list, which should be
internal to apexd. (Note how vold_prepare_subdirs filtered out
directories with "@" character).

This also makes vold_prepare_subdirs immune to the upcoming changes:
/apex directory containing only bootstrap APEXes in the bootstrap NS.

Until now, getting the list of apexes by scanning /apex was okay
because of the accidental fact that /apex directory has directories
for all the apexes, not only bootstrap apexes.

Bug: 293949266
Bug: 293546778
Test: CtsPackageSettingHostTestCases
Change-Id: I3fe373ca6f4c2281439bb2449845a1a14357131e
This commit is contained in:
Jooyung Han 2023-08-01 11:58:34 +09:00
parent c2b3fefa01
commit 443a73b100
2 changed files with 32 additions and 14 deletions

View file

@ -239,7 +239,10 @@ cc_binary {
cc_binary {
name: "vold_prepare_subdirs",
defaults: ["vold_default_flags"],
defaults: [
"vold_default_flags",
"libapexservice-deps",
],
srcs: [
"vold_prepare_subdirs.cpp",

View file

@ -30,7 +30,11 @@
#include <sys/types.h>
#include <android-base/logging.h>
#include <android-base/result.h>
#include <android-base/scopeguard.h>
#include <android/apex/ApexInfo.h>
#include <android/apex/IApexService.h>
#include <binder/IServiceManager.h>
#include <cutils/fs.h>
#include <selinux/android.h>
@ -141,24 +145,35 @@ static bool rmrf_contents(const std::string& path) {
}
}
static android::base::Result<std::vector<std::string>> get_apex_list() {
auto sm = android::defaultServiceManager();
auto binder = sm->waitForService(android::String16("apexservice"));
if (binder == nullptr) {
return android::base::Error() << "Failed to get apexservice";
}
auto service = android::interface_cast<android::apex::IApexService>(binder);
std::vector<android::apex::ApexInfo> list;
auto status = service->getActivePackages(&list);
if (!status.isOk()) {
return android::base::Error() << status.exceptionMessage().c_str();
}
std::vector<std::string> names;
names.reserve(list.size());
for (const auto& apex_info : list) {
names.push_back(apex_info.moduleName);
}
return names;
}
static bool prepare_apex_subdirs(struct selabel_handle* sehandle, const std::string& path) {
if (!prepare_dir(sehandle, 0711, 0, 0, path + "/apexdata")) return false;
auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir("/apex"), closedir);
if (!dirp) {
PLOG(ERROR) << "Unable to open apex directory";
auto apex_list = get_apex_list();
if (!apex_list.ok()) {
LOG(ERROR) << apex_list.error();
return false;
}
struct dirent* entry;
while ((entry = readdir(dirp.get())) != nullptr) {
if (entry->d_type != DT_DIR) continue;
const char* name = entry->d_name;
// skip any starting with "."
if (name[0] == '.') continue;
if (strchr(name, '@') != NULL) continue;
for (const auto& name : *apex_list) {
if (!prepare_dir(sehandle, 0771, AID_ROOT, AID_SYSTEM, path + "/apexdata/" + name)) {
return false;
}