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

Commit 9df2a657 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

Updatable Driver: Decouple gfx_driver from sphal

This change manually constructs updatable graphics driver namespace
without inheriting from sphal namespace. Manually link against default
namespace to access llndk libraries and link against vndk namespace to
access vndksp libraries. Then the newly created namespace will not have
access to libraries under /vendor/lib[64]/.

Bug: 120106759
Test: Manual. Install updatable driver apk with/without some missing
libraries to verify the namespace isolation working as intended.
Change-Id: I6225bb018028bbb72f77b288c3b5bf60a5b86422
Merged-In: I6225bb018028bbb72f77b288c3b5bf60a5b86422
parent a6498684
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ cc_library_shared {
    cflags: ["-Wall", "-Werror"],

    shared_libs: [
        "libbase",
        "libcutils",
        "libdl_android",
        "liblog",
    ],
+115 −25
Original line number Diff line number Diff line
@@ -18,20 +18,26 @@
#define LOG_TAG "GraphicsEnv"
#include <graphicsenv/GraphicsEnv.h>

#include <mutex>
#include <dlfcn.h>

#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <android/dlext.h>
#include <log/log.h>
#include <sys/prctl.h>

#include <mutex>

// TODO(b/37049319) Get this from a header once one exists
extern "C" {
android_namespace_t* android_get_exported_namespace(const char*);
  android_namespace_t* android_create_namespace(const char* name,
                                                const char* ld_library_path,
                                                const char* default_library_path,
                                                uint64_t type,
android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
                                              const char* default_library_path, uint64_t type,
                                              const char* permitted_when_isolated_path,
                                              android_namespace_t* parent);
bool android_link_namespaces(android_namespace_t* from, android_namespace_t* to,
                             const char* shared_libs_sonames);

enum {
    ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
@@ -41,6 +47,69 @@ extern "C" {

namespace android {

enum NativeLibrary {
    LLNDK = 0,
    VNDKSP = 1,
};

static constexpr const char* kNativeLibrariesSystemConfigPath[] = {"/etc/llndk.libraries.txt",
                                                                   "/etc/vndksp.libraries.txt"};

static std::string vndkVersionStr() {
#ifdef __BIONIC__
    std::string version = android::base::GetProperty("ro.vndk.version", "");
    if (version != "" && version != "current") {
        return "." + version;
    }
#endif
    return "";
}

static void insertVndkVersionStr(std::string* fileName) {
    LOG_ALWAYS_FATAL_IF(!fileName, "fileName should never be nullptr");
    size_t insertPos = fileName->find_last_of(".");
    if (insertPos == std::string::npos) {
        insertPos = fileName->length();
    }
    fileName->insert(insertPos, vndkVersionStr());
}

static bool readConfig(const std::string& configFile, std::vector<std::string>* soNames) {
    // Read list of public native libraries from the config file.
    std::string fileContent;
    if (!base::ReadFileToString(configFile, &fileContent)) {
        return false;
    }

    std::vector<std::string> lines = base::Split(fileContent, "\n");

    for (auto& line : lines) {
        auto trimmedLine = base::Trim(line);
        if (!trimmedLine.empty()) {
            soNames->push_back(trimmedLine);
        }
    }

    return true;
}

static const std::string getSystemNativeLibraries(NativeLibrary type) {
    static const char* androidRootEnv = getenv("ANDROID_ROOT");
    static const std::string rootDir = androidRootEnv != nullptr ? androidRootEnv : "/system";

    std::string nativeLibrariesSystemConfig = rootDir + kNativeLibrariesSystemConfigPath[type];

    insertVndkVersionStr(&nativeLibrariesSystemConfig);

    std::vector<std::string> soNames;
    if (!readConfig(nativeLibrariesSystemConfig, &soNames)) {
        ALOGE("Failed to retrieve library names from %s", nativeLibrariesSystemConfig.c_str());
        return "";
    }

    return base::Join(soNames, ':');
}

/*static*/ GraphicsEnv& GraphicsEnv::getInstance() {
    static GraphicsEnv env;
    return env;
@@ -48,8 +117,8 @@ namespace android {

void GraphicsEnv::setDriverPath(const std::string path) {
    if (!mDriverPath.empty()) {
        ALOGV("ignoring attempt to change driver path from '%s' to '%s'",
                mDriverPath.c_str(), path.c_str());
        ALOGV("ignoring attempt to change driver path from '%s' to '%s'", mDriverPath.c_str(),
              path.c_str());
        return;
    }
    ALOGV("setting driver path to '%s'", path.c_str());
@@ -85,20 +154,41 @@ void GraphicsEnv::setDebugLayers(const std::string layers) {
android_namespace_t* GraphicsEnv::getDriverNamespace() {
    static std::once_flag once;
    std::call_once(once, [this]() {
        if (mDriverPath.empty())
            return;
        // If the sphal namespace isn't configured for a device, don't support updatable drivers.
        // We need a parent namespace to inherit the default search path from.
        auto sphalNamespace = android_get_exported_namespace("sphal");
        if (!sphalNamespace) return;
        if (mDriverPath.empty()) return;

        auto vndkNamespace = android_get_exported_namespace("vndk");
        if (!vndkNamespace) return;

        mDriverNamespace = android_create_namespace("gfx driver",
                                                    mDriverPath.c_str(), // ld_library_path
                                                    mDriverPath.c_str(), // default_library_path
                                                    ANDROID_NAMESPACE_TYPE_SHARED |
                                                    ANDROID_NAMESPACE_TYPE_ISOLATED,
                                                    nullptr, // permitted_when_isolated_path
                                                    sphalNamespace);
                                                    nullptr);

        const std::string llndkLibraries = getSystemNativeLibraries(NativeLibrary::LLNDK);
        if (llndkLibraries.empty()) {
            mDriverNamespace = nullptr;
            return;
        }
        if (!android_link_namespaces(mDriverNamespace, nullptr, llndkLibraries.c_str())) {
            ALOGE("Failed to link default namespace[%s]", dlerror());
            mDriverNamespace = nullptr;
            return;
        }

        const std::string vndkspLibraries = getSystemNativeLibraries(NativeLibrary::VNDKSP);
        if (vndkspLibraries.empty()) {
            mDriverNamespace = nullptr;
            return;
        }
        if (!android_link_namespaces(mDriverNamespace, vndkNamespace, vndkspLibraries.c_str())) {
            ALOGE("Failed to link vndk namespace[%s]", dlerror());
            mDriverNamespace = nullptr;
            return;
        }
    });

    return mDriverNamespace;
}