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

Commit e846d8bd authored by Jiyong Park's avatar Jiyong Park Committed by android-build-merger
Browse files

Merge "Don't create anonymous namespace" am: 085a0b44 am: 4b1462c0

am: be711aba

Change-Id: Iee93cd8dd4271796fc6e10292b23706fd27bda90
parents 069dedb3 be711aba
Loading
Loading
Loading
Loading
+12 −14
Original line number Diff line number Diff line
@@ -22,18 +22,6 @@

__BEGIN_DECLS

/*
 * Initializes anonymous namespaces. The shared_libs_sonames is the list of sonames
 * to be shared by default namespace separated by colon. Example: "libc.so:libm.so:libdl.so".
 *
 * The library_search_path is the search path for anonymous namespace. The anonymous namespace
 * is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens
 * for the code not loaded by dynamic linker; for example calls from the mono-compiled code.
 */
extern bool android_init_anonymous_namespace(const char* shared_libs_sonames,
                                             const char* library_search_path);


enum {
  /* A regular namespace is the namespace with a custom search path that does
   * not impose any restrictions on the location of native libraries.
@@ -62,8 +50,18 @@ enum {
   */
  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,

  ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
                                           ANDROID_NAMESPACE_TYPE_ISOLATED,
  /* This flag instructs linker to use this namespace as the anonymous
   * namespace. The anonymous namespace is used in the case when linker cannot
   * identify the caller of dlopen/dlsym. This happens for the code not loaded
   * by dynamic linker; for example calls from the mono-compiled code. There can
   * be only one anonymous namespace in a process. If there already is an
   * anonymous namespace in the process, using this flag when creating a new
   * namespace causes an error.
   */
  ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000,

  ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED =
      ANDROID_NAMESPACE_TYPE_SHARED | ANDROID_NAMESPACE_TYPE_ISOLATED,
};

/*
+16 −37
Original line number Diff line number Diff line
@@ -159,13 +159,6 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
    }
  }

  // Initialize the anonymous namespace with the first non-empty library path.
  Result<void> ret;
  if (!library_path.empty() && !initialized_ &&
      !(ret = InitPublicNamespace(library_path.c_str()))) {
    return ret.error();
  }

  LOG_ALWAYS_FATAL_IF(FindNamespaceByClassLoader(env, class_loader) != nullptr,
                      "There is already a namespace associated with this classloader");

@@ -215,13 +208,22 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t

  // Create the app namespace
  NativeLoaderNamespace* parent_ns = FindParentNamespaceByClassLoader(env, class_loader);
  auto app_ns =
      NativeLoaderNamespace::Create(namespace_name, library_path, permitted_path, parent_ns,
                                    is_shared, target_sdk_version < 24 /* is_greylist_enabled */);
  // Heuristic: the first classloader with non-empty library_path is assumed to
  // be the main classloader for app
  // TODO(b/139178525) remove this heuristic by determining this in LoadedApk (or its
  // friends) and then passing it down to here.
  bool is_main_classloader = app_main_namespace_ == nullptr && !library_path.empty();
  // Policy: the namespace for the main classloader is also used as the
  // anonymous namespace.
  bool also_used_as_anonymous = is_main_classloader;
  // Note: this function is executed with g_namespaces_mutex held, thus no
  // racing here.
  auto app_ns = NativeLoaderNamespace::Create(
      namespace_name, library_path, permitted_path, parent_ns, is_shared,
      target_sdk_version < 24 /* is_greylist_enabled */, also_used_as_anonymous);
  if (!app_ns) {
    return app_ns.error();
  }

  // ... and link to other namespaces to allow access to some public libraries
  bool is_bridged = app_ns->IsBridged();

@@ -278,6 +280,9 @@ Result<NativeLoaderNamespace*> LibraryNamespaces::Create(JNIEnv* env, uint32_t t
  }

  namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns));
  if (is_main_classloader) {
    app_main_namespace_ = &(*app_ns);
  }

  return &(namespaces_.back().second);
}
@@ -295,32 +300,6 @@ NativeLoaderNamespace* LibraryNamespaces::FindNamespaceByClassLoader(JNIEnv* env
  return nullptr;
}

Result<void> LibraryNamespaces::InitPublicNamespace(const char* library_path) {
  // Ask native bride if this apps library path should be handled by it
  bool is_native_bridge = NativeBridgeIsPathSupported(library_path);

  // (http://b/25844435) - Some apps call dlopen from generated code (mono jited
  // code is one example) unknown to linker in which  case linker uses anonymous
  // namespace. The second argument specifies the search path for the anonymous
  // namespace which is the library_path of the classloader.
  initialized_ = android_init_anonymous_namespace(default_public_libraries().c_str(),
                                                  is_native_bridge ? nullptr : library_path);
  if (!initialized_) {
    return Error() << dlerror();
  }

  // and now initialize native bridge namespaces if necessary.
  if (NativeBridgeInitialized()) {
    initialized_ = NativeBridgeInitAnonymousNamespace(default_public_libraries().c_str(),
                                                      is_native_bridge ? library_path : nullptr);
    if (!initialized_) {
      return Error() << NativeBridgeGetError();
    }
  }

  return {};
}

NativeLoaderNamespace* LibraryNamespaces::FindParentNamespaceByClassLoader(JNIEnv* env,
                                                                           jobject class_loader) {
  jobject parent_class_loader = GetParentClassLoader(env, class_loader);
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ class LibraryNamespaces {
  void Reset() {
    namespaces_.clear();
    initialized_ = false;
    app_main_namespace_ = nullptr;
  }
  Result<NativeLoaderNamespace*> Create(JNIEnv* env, uint32_t target_sdk_version,
                                        jobject class_loader, bool is_shared, jstring dex_path,
@@ -59,6 +60,7 @@ class LibraryNamespaces {
  NativeLoaderNamespace* FindParentNamespaceByClassLoader(JNIEnv* env, jobject class_loader);

  bool initialized_;
  NativeLoaderNamespace* app_main_namespace_;
  std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
};

+12 −1
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::GetPlatformNamespace(bool i

Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
    const std::string& name, const std::string& search_paths, const std::string& permitted_paths,
    const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled) {
    const NativeLoaderNamespace* parent, bool is_shared, bool is_greylist_enabled,
    bool also_used_as_anonymous) {
  bool is_bridged = false;
  if (parent != nullptr) {
    is_bridged = parent->IsBridged();
@@ -100,7 +101,17 @@ Result<NativeLoaderNamespace> NativeLoaderNamespace::Create(
  }
  const NativeLoaderNamespace& effective_parent = parent != nullptr ? *parent : *platform_ns;

  // All namespaces for apps are isolated
  uint64_t type = ANDROID_NAMESPACE_TYPE_ISOLATED;

  // The namespace is also used as the anonymous namespace
  // which is used when the linker fails to determine the caller address
  if (also_used_as_anonymous) {
    type |= ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS;
  }

  // Bundled apps have access to all system libraries that are currently loaded
  // in the default namespace
  if (is_shared) {
    type |= ANDROID_NAMESPACE_TYPE_SHARED;
  }
+2 −1
Original line number Diff line number Diff line
@@ -39,7 +39,8 @@ struct NativeLoaderNamespace {
                                              const std::string& search_paths,
                                              const std::string& permitted_paths,
                                              const NativeLoaderNamespace* parent, bool is_shared,
                                              bool is_greylist_enabled);
                                              bool is_greylist_enabled,
                                              bool also_used_as_anonymous);

  NativeLoaderNamespace(NativeLoaderNamespace&&) = default;
  NativeLoaderNamespace(const NativeLoaderNamespace&) = default;
Loading