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

Commit ade364b4 authored by Dimitry Ivanov's avatar Dimitry Ivanov
Browse files

Set parent namespace for linker-namespaces

This change allows applications to share RTLD_GLOBAL
native libraries between namespaces associated with
different classloaders.

The rule is - if a library is GLOBAL within namespace
associated with parent classloader, it is shared
with namespace associated with this classloader

Note that the sharing happens on create_namespace
event, which is tied to createClassloader in case of
application classloaders created by the framework, for
custom application classloaders it is tied to first
loadLibrary() event.

Bug: http://b/28560538
Bug: https://code.google.com/p/android/issues/detail?id=208458
Change-Id: I7ee701166f8ec5eff033b7acc0f80c7aa4ec5bda
(cherry picked from commit 24db75c1)
parent 6e394f0f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -83,7 +83,8 @@ extern struct 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);
                                                            const char* permitted_when_isolated_path,
                                                            android_namespace_t* parent);

__END_DECLS

+27 −1
Original line number Diff line number Diff line
@@ -97,11 +97,14 @@ class LibraryNamespaces {
      namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED;
    }

    android_namespace_t* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);

    ns = android_create_namespace("classloader-namespace",
                                  nullptr,
                                  library_path.c_str(),
                                  namespace_type,
                                  permitted_path.c_str());
                                  permitted_path.c_str(),
                                  parent_ns);

    if (ns != nullptr) {
      namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), ns));
@@ -198,6 +201,29 @@ class LibraryNamespaces {
    return initialized_;
  }

  jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) {
    jclass class_loader_class = env->FindClass("java/lang/ClassLoader");
    jmethodID get_parent = env->GetMethodID(class_loader_class,
                                            "getParent",
                                            "()Ljava/lang/ClassLoader;");

    return env->CallObjectMethod(class_loader, get_parent);
  }

  android_namespace_t* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader) {
    jobject parent_class_loader = GetParentClassLoader(env, class_loader);

    while (parent_class_loader != nullptr) {
      android_namespace_t* ns = FindNamespaceByClassLoader(env, parent_class_loader);
      if (ns != nullptr) {
        return ns;
      }

      parent_class_loader = GetParentClassLoader(env, parent_class_loader);
    }
    return nullptr;
  }

  bool initialized_;
  std::vector<std::pair<jweak, android_namespace_t*>> namespaces_;
  std::string public_libraries_;