Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f870b88e authored by Shikha Malhotra's avatar Shikha Malhotra Committed by Gerrit Code Review
Browse files

Merge "Move flattened APEX activation logic to apexd."

parents 2b521806 720694dc
Loading
Loading
Loading
Loading
+1 −13
Original line number Diff line number Diff line
@@ -1305,22 +1305,10 @@ static Result<void> MountLinkerConfigForDefaultNamespace() {

    return {};
}

static bool IsApexUpdatable() {
    static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
    return updatable;
}

static Result<void> do_update_linker_config(const BuiltinArguments&) {
    // If APEX is not updatable, then all APEX information are already included in the first
    // linker config generation, so there is no need to update linker configuration again.
    if (IsApexUpdatable()) {
    return GenerateLinkerConfiguration();
}

    return {};
}

static Result<void> parse_apex_configs() {
    glob_t glob_result;
    static constexpr char glob_pattern[] = "/apex/*/etc/*.rc";
+1 −107
Original line number Diff line number Diff line
@@ -97,110 +97,6 @@ static bool NeedsTwoMountNamespaces() {
    return true;
}

#ifdef ACTIVATE_FLATTENED_APEX

static Result<void> MountDir(const std::string& path, const std::string& mount_path) {
    if (int ret = mkdir(mount_path.c_str(), 0755); ret != 0 && errno != EEXIST) {
        return ErrnoError() << "Could not create mount point " << mount_path;
    }
    if (mount(path.c_str(), mount_path.c_str(), nullptr, MS_BIND, nullptr) != 0) {
        return ErrnoError() << "Could not bind mount " << path << " to " << mount_path;
    }
    return {};
}

static Result<apex::proto::ApexManifest> GetApexManifest(const std::string& apex_dir) {
    const std::string manifest_path = apex_dir + "/apex_manifest.pb";
    std::string content;
    if (!android::base::ReadFileToString(manifest_path, &content)) {
        return Error() << "Failed to read manifest file: " << manifest_path;
    }
    apex::proto::ApexManifest manifest;
    if (!manifest.ParseFromString(content)) {
        return Error() << "Can't parse manifest file: " << manifest_path;
    }
    return manifest;
}

template <typename Fn>
static Result<void> ActivateFlattenedApexesFrom(const std::string& from_dir,
                                                const std::string& to_dir, Fn on_activate) {
    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(from_dir.c_str()), closedir);
    if (!dir) {
        return {};
    }
    dirent* entry;
    std::vector<std::string> entries;

    while ((entry = readdir(dir.get())) != nullptr) {
        if (entry->d_name[0] == '.') continue;
        if (entry->d_type == DT_DIR) {
            entries.push_back(entry->d_name);
        }
    }

    std::sort(entries.begin(), entries.end());
    for (const auto& name : entries) {
        const std::string apex_path = from_dir + "/" + name;
        const auto apex_manifest = GetApexManifest(apex_path);
        if (!apex_manifest.ok()) {
            LOG(ERROR) << apex_path << " is not an APEX directory: " << apex_manifest.error();
            continue;
        }
        const std::string mount_path = to_dir + "/" + apex_manifest->name();
        if (auto result = MountDir(apex_path, mount_path); !result.ok()) {
            return result;
        }
        on_activate(apex_path, *apex_manifest);
    }
    return {};
}

static bool ActivateFlattenedApexesIfPossible() {
    if (IsRecoveryMode() || IsApexUpdatable()) {
        return true;
    }

    const std::string kApexTop = "/apex";
    const std::vector<std::string> kBuiltinDirsForApexes = {
            "/system/apex",
            "/system_ext/apex",
            "/product/apex",
            "/vendor/apex",
    };

    std::vector<com::android::apex::ApexInfo> apex_infos;
    auto on_activate = [&](const std::string& apex_path,
                           const apex::proto::ApexManifest& apex_manifest) {
        apex_infos.emplace_back(apex_manifest.name(), apex_path, apex_path, apex_manifest.version(),
                                apex_manifest.versionname(), /*isFactory=*/true, /*isActive=*/true,
                                /* lastUpdateMillis= */ 0);
    };

    for (const auto& dir : kBuiltinDirsForApexes) {
        if (auto result = ActivateFlattenedApexesFrom(dir, kApexTop, on_activate); !result.ok()) {
            LOG(ERROR) << result.error();
            return false;
        }
    }

    std::ostringstream oss;
    com::android::apex::ApexInfoList apex_info_list(apex_infos);
    com::android::apex::write(oss, apex_info_list);
    const std::string kApexInfoList = kApexTop + "/apex-info-list.xml";
    if (!android::base::WriteStringToFile(oss.str(), kApexInfoList)) {
        PLOG(ERROR) << "Failed to write " << kApexInfoList;
        return false;
    }
    if (selinux_android_restorecon(kApexInfoList.c_str(), 0) != 0) {
        PLOG(ERROR) << "selinux_android_restorecon(" << kApexInfoList << ") failed";
    }

    return true;
}

#endif  // ACTIVATE_FLATTENED_APEX

static android::base::unique_fd bootstrap_ns_fd;
static android::base::unique_fd default_ns_fd;

@@ -294,9 +190,7 @@ bool SetupMountNamespaces() {
        default_ns_fd.reset(OpenMountNamespace());
        default_ns_id = GetMountNamespaceId();
    }
#ifdef ACTIVATE_FLATTENED_APEX
    success &= ActivateFlattenedApexesIfPossible();
#endif

    LOG(INFO) << "SetupMountNamespaces done";
    return success;
}