Move to C API of libnativeloader.
Test: m
Bug: 119840313
Bug: 122710865
(cherry picked from commit e1d970df09
)
Merged-In: Id5b08ef5de0d38cb678a50e45d38dfb8107c4a1c
Change-Id: Ic82baa885caa5125dd3c8b5de854128c75f48caf
Exempt-From-Owner-Approval: Cherry-pick of approved CL in master.
This commit is contained in:
parent
6410fd2434
commit
c3a73dcd27
7 changed files with 144 additions and 66 deletions
|
@ -23,4 +23,20 @@ cc_library {
|
|||
"llndk.libraries.txt",
|
||||
"vndksp.libraries.txt",
|
||||
],
|
||||
target: {
|
||||
android: {
|
||||
version_script: "libnativeloader.map.txt",
|
||||
},
|
||||
},
|
||||
stubs: {
|
||||
symbol_file: "libnativeloader.map.txt",
|
||||
versions: ["1"],
|
||||
},
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "libnativeloader-dummy-headers",
|
||||
|
||||
host_supported: true,
|
||||
export_include_dirs: ["include"],
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define __ANDROID_DLEXT_NAMESPACES_H__
|
||||
|
||||
#include <android/dlext.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
|
@ -84,12 +85,9 @@ enum {
|
|||
* If a library or any of its dependencies are outside of the permitted_when_isolated_path
|
||||
* and search_path, and it is not part of the public namespace dlopen will fail.
|
||||
*/
|
||||
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,
|
||||
android_namespace_t* parent);
|
||||
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, struct android_namespace_t* parent);
|
||||
|
||||
/*
|
||||
* Creates a link between namespaces. Every link has list of sonames of
|
||||
|
@ -107,8 +105,8 @@ extern struct android_namespace_t* android_create_namespace(const char* name,
|
|||
* step will not go deeper into linked namespaces for this library but
|
||||
* will do so for DT_NEEDED libraries.
|
||||
*/
|
||||
extern bool android_link_namespaces(android_namespace_t* from,
|
||||
android_namespace_t* to,
|
||||
extern bool android_link_namespaces(struct android_namespace_t* from,
|
||||
struct android_namespace_t* to,
|
||||
const char* shared_libs_sonames);
|
||||
|
||||
/*
|
||||
|
@ -124,7 +122,7 @@ extern bool android_link_namespaces(android_namespace_t* from,
|
|||
*/
|
||||
extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
|
||||
|
||||
extern android_namespace_t* android_get_exported_namespace(const char* name);
|
||||
extern struct android_namespace_t* android_get_exported_namespace(const char* name);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -17,14 +17,21 @@
|
|||
#ifndef NATIVE_LOADER_H_
|
||||
#define NATIVE_LOADER_H_
|
||||
|
||||
#include "jni.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include "jni.h"
|
||||
#if defined(__ANDROID__)
|
||||
#include <android/dlext.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace android {
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// README: the char** error message parameter being passed
|
||||
// to the methods below need to be freed through calling NativeLoaderFreeErrorMessage.
|
||||
// It's the caller's responsibility to call that method.
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void InitializeNativeLoader();
|
||||
|
@ -38,42 +45,39 @@ jstring CreateClassLoaderNamespace(JNIEnv* env,
|
|||
jstring library_path,
|
||||
jstring permitted_path);
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void* OpenNativeLibrary(JNIEnv* env,
|
||||
int32_t target_sdk_version,
|
||||
const char* path,
|
||||
jobject class_loader,
|
||||
jstring library_path,
|
||||
bool* needs_native_bridge,
|
||||
std::string* error_msg);
|
||||
__attribute__((visibility("default"))) void* OpenNativeLibrary(
|
||||
JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
|
||||
jstring library_path, bool* needs_native_bridge, char** error_msg);
|
||||
|
||||
__attribute__((visibility("default"))) bool CloseNativeLibrary(void* handle,
|
||||
const bool needs_native_bridge,
|
||||
std::string* error_msg);
|
||||
char** error_msg);
|
||||
|
||||
__attribute__((visibility("default"))) void NativeLoaderFreeErrorMessage(char* msg);
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
// Look up linker namespace by class_loader. Returns nullptr if
|
||||
// there is no namespace associated with the class_loader.
|
||||
// TODO(b/79940628): move users to FindNativeLoaderNamespaceByClassLoader and remove this function.
|
||||
__attribute__((visibility("default")))
|
||||
android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
|
||||
// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
|
||||
class NativeLoaderNamespace;
|
||||
__attribute__((visibility("default")))
|
||||
NativeLoaderNamespace* FindNativeLoaderNamespaceByClassLoader(
|
||||
__attribute__((visibility("default"))) struct android_namespace_t* FindNamespaceByClassLoader(
|
||||
JNIEnv* env, jobject class_loader);
|
||||
// That version works with native bridge namespaces, but requires use of OpenNativeLibrary.
|
||||
struct NativeLoaderNamespace;
|
||||
__attribute__((visibility("default"))) struct NativeLoaderNamespace*
|
||||
FindNativeLoaderNamespaceByClassLoader(JNIEnv* env, jobject class_loader);
|
||||
// Load library. Unlinke OpenNativeLibrary above couldn't create namespace on demand, but does
|
||||
// not require access to JNIEnv either.
|
||||
__attribute__((visibility("default")))
|
||||
void* OpenNativeLibrary(NativeLoaderNamespace* ns,
|
||||
const char* path,
|
||||
bool* needs_native_bridge,
|
||||
std::string* error_msg);
|
||||
__attribute__((visibility("default"))) void* OpenNativeLibraryInNamespace(
|
||||
struct NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
|
||||
char** error_msg);
|
||||
#endif
|
||||
|
||||
__attribute__((visibility("default")))
|
||||
void ResetNativeLoader();
|
||||
|
||||
}; // namespace android
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
} // namespace android
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // NATIVE_BRIDGE_H_
|
||||
|
|
31
libnativeloader/libnativeloader.map.txt
Normal file
31
libnativeloader/libnativeloader.map.txt
Normal file
|
@ -0,0 +1,31 @@
|
|||
#
|
||||
# Copyright (C) 2019 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# TODO(b/122710865): Prune these uses once the runtime APEX is complete.
|
||||
LIBNATIVELOADER_1 {
|
||||
global:
|
||||
OpenNativeLibrary;
|
||||
InitializeNativeLoader;
|
||||
ResetNativeLoader;
|
||||
CloseNativeLibrary;
|
||||
OpenNativeLibraryInNamespace;
|
||||
FindNamespaceByClassLoader;
|
||||
FindNativeLoaderNamespaceByClassLoader;
|
||||
CreateClassLoaderNamespace;
|
||||
NativeLoaderFreeErrorMessage;
|
||||
local:
|
||||
*;
|
||||
};
|
|
@ -52,7 +52,7 @@ using namespace std::string_literals;
|
|||
namespace android {
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
class NativeLoaderNamespace {
|
||||
struct NativeLoaderNamespace {
|
||||
public:
|
||||
NativeLoaderNamespace()
|
||||
: android_ns_(nullptr), native_bridge_ns_(nullptr) { }
|
||||
|
@ -151,14 +151,9 @@ class LibraryNamespaces {
|
|||
public:
|
||||
LibraryNamespaces() : initialized_(false) { }
|
||||
|
||||
NativeLoaderNamespace* Create(JNIEnv* env,
|
||||
uint32_t target_sdk_version,
|
||||
jobject class_loader,
|
||||
bool is_shared,
|
||||
bool is_for_vendor,
|
||||
jstring java_library_path,
|
||||
jstring java_permitted_path,
|
||||
std::string* error_msg) {
|
||||
NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
|
||||
bool is_shared, bool is_for_vendor, jstring java_library_path,
|
||||
jstring java_permitted_path, std::string* error_msg) {
|
||||
std::string library_path; // empty string by default.
|
||||
|
||||
if (java_library_path != nullptr) {
|
||||
|
@ -628,13 +623,9 @@ jstring CreateClassLoaderNamespace(JNIEnv* env,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void* OpenNativeLibrary(JNIEnv* env,
|
||||
int32_t target_sdk_version,
|
||||
const char* path,
|
||||
jobject class_loader,
|
||||
jstring library_path,
|
||||
bool* needs_native_bridge,
|
||||
std::string* error_msg) {
|
||||
void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path,
|
||||
jobject class_loader, jstring library_path, bool* needs_native_bridge,
|
||||
char** error_msg) {
|
||||
#if defined(__ANDROID__)
|
||||
UNUSED(target_sdk_version);
|
||||
if (class_loader == nullptr) {
|
||||
|
@ -652,19 +643,16 @@ void* OpenNativeLibrary(JNIEnv* env,
|
|||
if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) {
|
||||
// This is the case where the classloader was not created by ApplicationLoaders
|
||||
// In this case we create an isolated not-shared namespace for it.
|
||||
if ((ns = g_namespaces->Create(env,
|
||||
target_sdk_version,
|
||||
class_loader,
|
||||
false /* is_shared */,
|
||||
false /* is_for_vendor */,
|
||||
library_path,
|
||||
nullptr,
|
||||
error_msg)) == nullptr) {
|
||||
std::string create_error_msg;
|
||||
if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
|
||||
false /* is_for_vendor */, library_path, nullptr,
|
||||
&create_error_msg)) == nullptr) {
|
||||
*error_msg = strdup(create_error_msg.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return OpenNativeLibrary(ns, path, needs_native_bridge, error_msg);
|
||||
return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg);
|
||||
#else
|
||||
UNUSED(env, target_sdk_version, class_loader);
|
||||
|
||||
|
@ -705,35 +693,40 @@ void* OpenNativeLibrary(JNIEnv* env,
|
|||
if (handle != nullptr) {
|
||||
return handle;
|
||||
}
|
||||
*error_msg = NativeBridgeGetError();
|
||||
*error_msg = strdup(NativeBridgeGetError());
|
||||
} else {
|
||||
*error_msg = dlerror();
|
||||
*error_msg = strdup(dlerror());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, std::string* error_msg) {
|
||||
bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) {
|
||||
bool success;
|
||||
if (needs_native_bridge) {
|
||||
success = (NativeBridgeUnloadLibrary(handle) == 0);
|
||||
if (!success) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
*error_msg = strdup(NativeBridgeGetError());
|
||||
}
|
||||
} else {
|
||||
success = (dlclose(handle) == 0);
|
||||
if (!success) {
|
||||
*error_msg = dlerror();
|
||||
*error_msg = strdup(dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void NativeLoaderFreeErrorMessage(char* msg) {
|
||||
// The error messages get allocated through strdup, so we must call free on them.
|
||||
free(msg);
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge,
|
||||
std::string* error_msg) {
|
||||
void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path,
|
||||
bool* needs_native_bridge, char** error_msg) {
|
||||
if (ns->is_android_namespace()) {
|
||||
android_dlextinfo extinfo;
|
||||
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||
|
@ -741,14 +734,14 @@ void* OpenNativeLibrary(NativeLoaderNamespace* ns, const char* path, bool* needs
|
|||
|
||||
void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo);
|
||||
if (handle == nullptr) {
|
||||
*error_msg = dlerror();
|
||||
*error_msg = strdup(dlerror());
|
||||
}
|
||||
*needs_native_bridge = false;
|
||||
return handle;
|
||||
} else {
|
||||
void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns->get_native_bridge_ns());
|
||||
if (handle == nullptr) {
|
||||
*error_msg = NativeBridgeGetError();
|
||||
*error_msg = strdup(NativeBridgeGetError());
|
||||
}
|
||||
*needs_native_bridge = true;
|
||||
return handle;
|
||||
|
|
|
@ -69,3 +69,14 @@ cc_library {
|
|||
"libbase",
|
||||
],
|
||||
}
|
||||
|
||||
// Build the test for the C API.
|
||||
cc_test {
|
||||
name: "libnativeloader-api-tests",
|
||||
host_supported: true,
|
||||
test_per_src: true,
|
||||
srcs: [
|
||||
"api_test.c",
|
||||
],
|
||||
header_libs: ["libnativeloader-dummy-headers"],
|
||||
}
|
||||
|
|
25
libnativeloader/test/api_test.c
Normal file
25
libnativeloader/test/api_test.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* The main purpose of this test is to ensure this C header compiles in C, so
|
||||
* that no C++ features inadvertently leak into the C ABI. */
|
||||
#include "nativeloader/native_loader.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue