diff --git a/libnativeloader/library_namespaces.cpp b/libnativeloader/library_namespaces.cpp index 1e29f4e457..683e76247f 100644 --- a/libnativeloader/library_namespaces.cpp +++ b/libnativeloader/library_namespaces.cpp @@ -16,6 +16,8 @@ #if defined(ART_TARGET_ANDROID) +#define LOG_TAG "nativeloader" + #include "library_namespaces.h" #include @@ -25,14 +27,13 @@ #include #include -#include -#include -#include -#include -#include -#include -#include - +#include "android-base/file.h" +#include "android-base/logging.h" +#include "android-base/macros.h" +#include "android-base/result.h" +#include "android-base/stringprintf.h" +#include "android-base/strings.h" +#include "nativehelper/scoped_utf_chars.h" #include "nativeloader/dlext_namespaces.h" #include "public_libraries.h" #include "utils.h" @@ -43,19 +44,6 @@ namespace { constexpr const char* kApexPath = "/apex/"; -// The device may be configured to have the vendor libraries loaded to a separate namespace. -// For historical reasons this namespace was named sphal but effectively it is intended -// to use to load vendor libraries to separate namespace with controlled interface between -// vendor and system namespaces. -constexpr const char* kVendorNamespaceName = "sphal"; -// Similar to sphal namespace, product namespace provides some product libraries. -constexpr const char* kProductNamespaceName = "product"; - -// vndk namespace for unbundled vendor apps -constexpr const char* kVndkNamespaceName = "vndk"; -// vndk_product namespace for unbundled product apps -constexpr const char* kVndkProductNamespaceName = "vndk_product"; - // clns-XX is a linker namespace that is created for normal apps installed in // the data partition. To be specific, it is created for the app classloader. // When System.load() is called from a Java class that is loaded from the @@ -89,15 +77,8 @@ constexpr const char* kVendorLibPath = "/vendor/" LIB; // a symlink to the other. constexpr const char* kProductLibPath = "/product/" LIB ":/system/product/" LIB; -const std::regex kVendorDexPathRegex("(^|:)(/system)?/vendor/"); -const std::regex kProductDexPathRegex("(^|:)(/system)?/product/"); - -// Define origin partition of APK -using ApkOrigin = enum { - APK_ORIGIN_DEFAULT = 0, - APK_ORIGIN_VENDOR = 1, // Includes both /vendor and /system/vendor - APK_ORIGIN_PRODUCT = 2, // Includes both /product and /system/product -}; +const std::regex kVendorPathRegex("(^|:)(/system)?/vendor/"); +const std::regex kProductPathRegex("(^|:)(/system)?/product/"); jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) { jclass class_loader_class = env->FindClass("java/lang/ClassLoader"); @@ -107,23 +88,22 @@ jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) { return env->CallObjectMethod(class_loader, get_parent); } -ApkOrigin GetApkOriginFromDexPath(const std::string& dex_path) { - ApkOrigin apk_origin = APK_ORIGIN_DEFAULT; - if (std::regex_search(dex_path, kVendorDexPathRegex)) { - apk_origin = APK_ORIGIN_VENDOR; - } - if (std::regex_search(dex_path, kProductDexPathRegex)) { - LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR, - "Dex path contains both vendor and product partition : %s", - dex_path.c_str()); +} // namespace - apk_origin = APK_ORIGIN_PRODUCT; +ApiDomain GetApiDomainFromPath(const std::string& path) { + ApiDomain api_domain = API_DOMAIN_DEFAULT; + if (std::regex_search(path, kVendorPathRegex)) { + api_domain = API_DOMAIN_VENDOR; } - return apk_origin; + if (is_product_treblelized() && std::regex_search(path, kProductPathRegex)) { + LOG_ALWAYS_FATAL_IF(api_domain == API_DOMAIN_VENDOR, + "Path matches both vendor and product partitions: %s", + path.c_str()); + api_domain = API_DOMAIN_PRODUCT; + } + return api_domain; } -} // namespace - void LibraryNamespaces::Initialize() { // Once public namespace is initialized there is no // point in running this code - it will have no effect @@ -170,7 +150,7 @@ static const std::string filter_public_libraries( } std::vector filtered; std::vector orig = android::base::Split(public_libraries, ":"); - for (const auto& lib : uses_libraries) { + for (const std::string& lib : uses_libraries) { if (std::find(orig.begin(), orig.end(), lib) != orig.end()) { filtered.emplace_back(lib); } @@ -178,32 +158,29 @@ static const std::string filter_public_libraries( return android::base::Join(filtered, ":"); } -Result LibraryNamespaces::Create(JNIEnv* env, uint32_t target_sdk_version, - jobject class_loader, bool is_shared, - jstring dex_path_j, - jstring java_library_path, - jstring java_permitted_path, - jstring uses_library_list) { +Result LibraryNamespaces::Create(JNIEnv* env, + uint32_t target_sdk_version, + jobject class_loader, + ApiDomain api_domain, + bool is_shared, + const std::string& dex_path, + jstring library_path_j, + jstring permitted_path_j, + jstring uses_library_list_j) { std::string library_path; // empty string by default. - std::string dex_path; - if (java_library_path != nullptr) { - ScopedUtfChars library_path_utf_chars(env, java_library_path); + if (library_path_j != nullptr) { + ScopedUtfChars library_path_utf_chars(env, library_path_j); library_path = library_path_utf_chars.c_str(); } - if (dex_path_j != nullptr) { - ScopedUtfChars dex_path_chars(env, dex_path_j); - dex_path = dex_path_chars.c_str(); - } - std::vector uses_libraries; - if (uses_library_list != nullptr) { - ScopedUtfChars names(env, uses_library_list); + if (uses_library_list_j != nullptr) { + ScopedUtfChars names(env, uses_library_list_j); uses_libraries = android::base::Split(names.c_str(), ":"); } else { - // uses_library_list could be nullptr when System.loadLibrary is called from a - // custom classloader. In that case, we don't know the list of public + // uses_library_list_j could be nullptr when System.loadLibrary is called + // from a custom classloader. In that case, we don't know the list of public // libraries because we don't know which apk the classloader is for. Only // choices we can have are 1) allowing all public libs (as before), or 2) // not allowing all but NDK libs. Here we take #1 because #2 would surprise @@ -214,8 +191,6 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t uses_libraries.emplace_back(LIBRARY_ALL); } - ApkOrigin apk_origin = GetApkOriginFromDexPath(dex_path); - // (http://b/27588281) This is a workaround for apps using custom // classloaders and calling System.load() with an absolute path which // is outside of the classloader library search path. @@ -224,8 +199,8 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t // under /data and /mnt/expand std::string permitted_path = kAlwaysPermittedDirectories; - if (java_permitted_path != nullptr) { - ScopedUtfChars path(env, java_permitted_path); + if (permitted_path_j != nullptr) { + ScopedUtfChars path(env, permitted_path_j); if (path.c_str() != nullptr && path.size() > 0) { permitted_path = permitted_path + ":" + path.c_str(); } @@ -236,13 +211,13 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t std::string system_exposed_libraries = default_public_libraries(); std::string namespace_name = kClassloaderNamespaceName; - ApkOrigin unbundled_app_origin = APK_ORIGIN_DEFAULT; - const char* apk_origin_msg = "other apk"; // Only for debug logging. + ApiDomain unbundled_app_domain = API_DOMAIN_DEFAULT; + const char* api_domain_msg = "other apk"; // Only for debug logging. if (!is_shared) { - if (apk_origin == APK_ORIGIN_VENDOR) { - unbundled_app_origin = APK_ORIGIN_VENDOR; - apk_origin_msg = "unbundled vendor apk"; + if (api_domain == API_DOMAIN_VENDOR) { + unbundled_app_domain = API_DOMAIN_VENDOR; + api_domain_msg = "unbundled vendor apk"; // For vendor apks, give access to the vendor libs even though they are // treated as unbundled; the libs and apks are still bundled together in the @@ -255,9 +230,9 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t // Different name is useful for debugging namespace_name = kVendorClassloaderNamespaceName; - } else if (apk_origin == APK_ORIGIN_PRODUCT && is_product_treblelized()) { - unbundled_app_origin = APK_ORIGIN_PRODUCT; - apk_origin_msg = "unbundled product apk"; + } else if (api_domain == API_DOMAIN_PRODUCT) { + unbundled_app_domain = API_DOMAIN_PRODUCT; + api_domain_msg = "unbundled product apk"; // Like for vendor apks, give access to the product libs since they are // bundled together in the same partition. @@ -287,20 +262,20 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t "Configuring %s for %s %s. target_sdk_version=%u, uses_libraries=%s, library_path=%s, " "permitted_path=%s", namespace_name.c_str(), - apk_origin_msg, + api_domain_msg, dex_path.c_str(), static_cast(target_sdk_version), android::base::Join(uses_libraries, ':').c_str(), library_path.c_str(), permitted_path.c_str()); - if (unbundled_app_origin != APK_ORIGIN_VENDOR) { + if (unbundled_app_domain != API_DOMAIN_VENDOR) { // Extended public libraries are NOT available to unbundled vendor apks, but // they are to other apps, including those in system, system_ext, and // product partitions. The reason is that when GSI is used, the system // partition may get replaced, and then vendor apps may fail. It's fine for // product apps, because that partition isn't mounted in GSI tests. - auto libs = + const std::string libs = filter_public_libraries(target_sdk_version, uses_libraries, extended_public_libraries()); if (!libs.empty()) { ALOGD("Extending system_exposed_libraries: %s", libs.c_str()); @@ -320,27 +295,33 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t 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_exempt_list_enabled */, also_used_as_anonymous); + Result app_ns = + NativeLoaderNamespace::Create(namespace_name, + library_path, + permitted_path, + parent_ns, + is_shared, + target_sdk_version < 24 /* is_exempt_list_enabled */, + also_used_as_anonymous); if (!app_ns.ok()) { return app_ns.error(); } // ... and link to other namespaces to allow access to some public libraries bool is_bridged = app_ns->IsBridged(); - auto system_ns = NativeLoaderNamespace::GetSystemNamespace(is_bridged); + Result system_ns = NativeLoaderNamespace::GetSystemNamespace(is_bridged); if (!system_ns.ok()) { return system_ns.error(); } - auto linked = app_ns->Link(&system_ns.value(), system_exposed_libraries); + Result linked = app_ns->Link(&system_ns.value(), system_exposed_libraries); if (!linked.ok()) { return linked.error(); } for (const auto&[apex_ns_name, public_libs] : apex_public_libraries()) { - auto ns = NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged); + Result ns = + NativeLoaderNamespace::GetExportedNamespace(apex_ns_name, is_bridged); // Even if APEX namespace is visible, it may not be available to bridged. if (ns.ok()) { linked = app_ns->Link(&ns.value(), public_libs); @@ -351,8 +332,9 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t } // Give access to VNDK-SP libraries from the 'vndk' namespace for unbundled vendor apps. - if (unbundled_app_origin == APK_ORIGIN_VENDOR && !vndksp_libraries_vendor().empty()) { - auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged); + if (unbundled_app_domain == API_DOMAIN_VENDOR && !vndksp_libraries_vendor().empty()) { + Result vndk_ns = + NativeLoaderNamespace::GetExportedNamespace(kVndkNamespaceName, is_bridged); if (vndk_ns.ok()) { linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_vendor()); if (!linked.ok()) { @@ -362,8 +344,9 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t } // Give access to VNDK-SP libraries from the 'vndk_product' namespace for unbundled product apps. - if (unbundled_app_origin == APK_ORIGIN_PRODUCT && !vndksp_libraries_product().empty()) { - auto vndk_ns = NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged); + if (unbundled_app_domain == API_DOMAIN_PRODUCT && !vndksp_libraries_product().empty()) { + Result vndk_ns = + NativeLoaderNamespace::GetExportedNamespace(kVndkProductNamespaceName, is_bridged); if (vndk_ns.ok()) { linked = app_ns->Link(&vndk_ns.value(), vndksp_libraries_product()); if (!linked.ok()) { @@ -373,11 +356,12 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t } for (const std::string& each_jar_path : android::base::Split(dex_path, ":")) { - auto apex_ns_name = FindApexNamespaceName(each_jar_path); + Result apex_ns_name = FindApexNamespaceName(each_jar_path); if (apex_ns_name.ok()) { - const auto& jni_libs = apex_jni_libraries(*apex_ns_name); + const std::string& jni_libs = apex_jni_libraries(*apex_ns_name); if (jni_libs != "") { - auto apex_ns = NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged); + Result apex_ns = + NativeLoaderNamespace::GetExportedNamespace(*apex_ns_name, is_bridged); if (apex_ns.ok()) { linked = app_ns->Link(&apex_ns.value(), jni_libs); if (!linked.ok()) { @@ -388,12 +372,13 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t } } - auto vendor_libs = filter_public_libraries(target_sdk_version, uses_libraries, - vendor_public_libraries()); + const std::string vendor_libs = + filter_public_libraries(target_sdk_version, uses_libraries, vendor_public_libraries()); if (!vendor_libs.empty()) { - auto vendor_ns = NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged); + Result vendor_ns = + NativeLoaderNamespace::GetExportedNamespace(kVendorNamespaceName, is_bridged); // when vendor_ns is not configured, link to the system namespace - auto target_ns = vendor_ns.ok() ? vendor_ns : system_ns; + Result target_ns = vendor_ns.ok() ? vendor_ns : system_ns; if (target_ns.ok()) { linked = app_ns->Link(&target_ns.value(), vendor_libs); if (!linked.ok()) { @@ -402,10 +387,10 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t } } - auto product_libs = filter_public_libraries(target_sdk_version, uses_libraries, - product_public_libraries()); + const std::string product_libs = + filter_public_libraries(target_sdk_version, uses_libraries, product_public_libraries()); if (!product_libs.empty()) { - auto target_ns = system_ns; + Result target_ns = system_ns; if (is_product_treblelized()) { target_ns = NativeLoaderNamespace::GetExportedNamespace(kProductNamespaceName, is_bridged); } @@ -422,8 +407,8 @@ Result LibraryNamespaces::Create(JNIEnv* env, uint32_t t } } - auto& emplaced = namespaces_.emplace_back( - std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns)); + std::pair& emplaced = + namespaces_.emplace_back(std::make_pair(env->NewWeakGlobalRef(class_loader), *app_ns)); if (is_main_classloader) { app_main_namespace_ = &emplaced.second; } diff --git a/libnativeloader/library_namespaces.h b/libnativeloader/library_namespaces.h index 4871528f47..25edf4faf7 100644 --- a/libnativeloader/library_namespaces.h +++ b/libnativeloader/library_namespaces.h @@ -21,20 +21,40 @@ #error "Not available for host or linux target" #endif -#define LOG_TAG "nativeloader" - -#include "native_loader_namespace.h" - #include #include -#include -#include +#include "android-base/result.h" +#include "jni.h" +#include "native_loader_namespace.h" namespace android::nativeloader { using android::base::Result; +// The device may be configured to have the vendor libraries loaded to a separate namespace. +// For historical reasons this namespace was named sphal but effectively it is intended +// to use to load vendor libraries to separate namespace with controlled interface between +// vendor and system namespaces. +constexpr const char* kVendorNamespaceName = "sphal"; +// Similar to sphal namespace, product namespace provides some product libraries. +constexpr const char* kProductNamespaceName = "product"; + +// vndk namespace for unbundled vendor apps +constexpr const char* kVndkNamespaceName = "vndk"; +// vndk_product namespace for unbundled product apps +constexpr const char* kVndkProductNamespaceName = "vndk_product"; + +// API domains, roughly corresponding to partitions. Interdependencies between +// these must follow API restrictions, while intradependencies do not. +using ApiDomain = enum { + API_DOMAIN_DEFAULT = 0, // Locations other than those below, in particular for ordinary apps + API_DOMAIN_VENDOR = 1, // Vendor partition + API_DOMAIN_PRODUCT = 2, // Product partition +}; + +nativeloader::ApiDomain GetApiDomainFromPath(const std::string& path); + // LibraryNamespaces is a singleton object that manages NativeLoaderNamespace // objects for an app process. Its main job is to create (and configure) a new // NativeLoaderNamespace object for a Java ClassLoader, and to find an existing @@ -53,10 +73,15 @@ class LibraryNamespaces { initialized_ = false; app_main_namespace_ = nullptr; } - Result Create(JNIEnv* env, uint32_t target_sdk_version, - jobject class_loader, bool is_shared, jstring dex_path, - jstring java_library_path, jstring java_permitted_path, - jstring uses_library_list); + Result Create(JNIEnv* env, + uint32_t target_sdk_version, + jobject class_loader, + ApiDomain api_domain, + bool is_shared, + const std::string& dex_path, + jstring library_path_j, + jstring permitted_path_j, + jstring uses_library_list_j); NativeLoaderNamespace* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader); private: diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp index 2deb5ef3d0..42a0d39a87 100644 --- a/libnativeloader/native_loader.cpp +++ b/libnativeloader/native_loader.cpp @@ -27,16 +27,17 @@ #include #include -#include -#include -#include -#include -#include -#include +#include "android-base/file.h" +#include "android-base/macros.h" +#include "android-base/strings.h" +#include "android-base/thread_annotations.h" +#include "nativebridge/native_bridge.h" +#include "nativehelper/scoped_utf_chars.h" +#include "public_libraries.h" #ifdef ART_TARGET_ANDROID -#include #include "library_namespaces.h" +#include "log/log.h" #include "nativeloader/dlext_namespaces.h" #endif @@ -46,6 +47,9 @@ namespace { #if defined(ART_TARGET_ANDROID) +using ::android::base::Result; +using ::android::nativeloader::LibraryNamespaces; + // NATIVELOADER_DEFAULT_NAMESPACE_LIBS is an environment variable that can be // used to list extra libraries (separated by ":") that libnativeloader will // load from the default namespace. The libraries must be listed without paths, @@ -62,14 +66,12 @@ namespace { // test libraries that depend on ART internal libraries. constexpr const char* kNativeloaderExtraLibs = "nativeloader-extra-libs"; -using android::nativeloader::LibraryNamespaces; - std::mutex g_namespaces_mutex; -LibraryNamespaces* g_namespaces = new LibraryNamespaces; -NativeLoaderNamespace* g_nativeloader_extra_libs_namespace = nullptr; +LibraryNamespaces* g_namespaces GUARDED_BY(g_namespaces_mutex) = new LibraryNamespaces; +NativeLoaderNamespace* g_nativeloader_extra_libs_namespace GUARDED_BY(g_namespaces_mutex) = nullptr; android_namespace_t* FindExportedNamespace(const char* caller_location) { - auto name = nativeloader::FindApexNamespaceName(caller_location); + Result name = nativeloader::FindApexNamespaceName(caller_location); if (name.ok()) { android_namespace_t* boot_namespace = android_get_exported_namespace(name->c_str()); LOG_ALWAYS_FATAL_IF((boot_namespace == nullptr), @@ -139,20 +141,22 @@ Result TryLoadNativeloaderExtraLib(const char* path) { Result CreateClassLoaderNamespaceLocked(JNIEnv* env, int32_t target_sdk_version, jobject class_loader, + nativeloader::ApiDomain api_domain, bool is_shared, - jstring dex_path, - jstring library_path, - jstring permitted_path, - jstring uses_library_list) + const std::string& dex_path, + jstring library_path_j, + jstring permitted_path_j, + jstring uses_library_list_j) REQUIRES(g_namespaces_mutex) { Result ns = g_namespaces->Create(env, target_sdk_version, class_loader, + api_domain, is_shared, dex_path, - library_path, - permitted_path, - uses_library_list); + library_path_j, + permitted_path_j, + uses_library_list_j); if (!ns.ok()) { return ns; } @@ -163,7 +167,7 @@ Result CreateClassLoaderNamespaceLocked(JNIEnv* env, return ns; } -#endif // #if defined(ART_TARGET_ANDROID) +#endif // ART_TARGET_ANDROID } // namespace @@ -183,36 +187,63 @@ void ResetNativeLoader() { #endif } -jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader, - bool is_shared, jstring dex_path, jstring library_path, - jstring permitted_path, jstring uses_library_list) { +jstring CreateClassLoaderNamespace(JNIEnv* env, + int32_t target_sdk_version, + jobject class_loader, + bool is_shared, + jstring dex_path_j, + jstring library_path_j, + jstring permitted_path_j, + jstring uses_library_list_j) { #if defined(ART_TARGET_ANDROID) + std::string dex_path; + if (dex_path_j != nullptr) { + ScopedUtfChars dex_path_chars(env, dex_path_j); + dex_path = dex_path_chars.c_str(); + } + nativeloader::ApiDomain api_domain = nativeloader::GetApiDomainFromPath(dex_path); + std::lock_guard guard(g_namespaces_mutex); Result ns = CreateClassLoaderNamespaceLocked(env, target_sdk_version, class_loader, + api_domain, is_shared, dex_path, - library_path, - permitted_path, - uses_library_list); + library_path_j, + permitted_path_j, + uses_library_list_j); if (!ns.ok()) { return env->NewStringUTF(ns.error().message().c_str()); } + #else - UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path, - uses_library_list); + UNUSED(env, + target_sdk_version, + class_loader, + is_shared, + dex_path_j, + library_path_j, + permitted_path_j, + uses_library_list_j); #endif + return nullptr; } -void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* path, - jobject class_loader, const char* caller_location, jstring library_path, - bool* needs_native_bridge, char** error_msg) { +void* OpenNativeLibrary(JNIEnv* env, + int32_t target_sdk_version, + const char* path, + jobject class_loader, + const char* caller_location, + jstring library_path_j, + bool* needs_native_bridge, + char** error_msg) { #if defined(ART_TARGET_ANDROID) - UNUSED(target_sdk_version); - if (class_loader == nullptr) { + // class_loader is null only for the boot class loader (see + // IsBootClassLoader call in JavaVMExt::LoadNativeLibrary), i.e. the caller + // is in the boot classpath. *needs_native_bridge = false; if (caller_location != nullptr) { android_namespace_t* boot_namespace = FindExportedNamespace(caller_location); @@ -244,8 +275,6 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat // Fall back to the system namespace. This happens for preloaded JNI // libraries in the zygote. - // TODO(b/185833744): Investigate if this should fall back to the app main - // namespace (aka anonymous namespace) instead. void* handle = OpenSystemLibrary(path, RTLD_NOW); if (handle == nullptr) { *error_msg = strdup(dlerror()); @@ -254,43 +283,46 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat } std::lock_guard guard(g_namespaces_mutex); - NativeLoaderNamespace* ns; + NativeLoaderNamespace* ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader); - if ((ns = g_namespaces->FindNamespaceByClassLoader(env, class_loader)) == nullptr) { + if (ns == 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. + const std::string empty_dex_path; Result isolated_ns = CreateClassLoaderNamespaceLocked(env, target_sdk_version, class_loader, + nativeloader::API_DOMAIN_DEFAULT, /*is_shared=*/false, - /*dex_path=*/nullptr, - library_path, + empty_dex_path, + library_path_j, /*permitted_path=*/nullptr, /*uses_library_list=*/nullptr); if (!isolated_ns.ok()) { *error_msg = strdup(isolated_ns.error().message().c_str()); return nullptr; } else { - ns = *isolated_ns; + ns = isolated_ns.value(); } } return OpenNativeLibraryInNamespace(ns, path, needs_native_bridge, error_msg); -#else + +#else // !ART_TARGET_ANDROID UNUSED(env, target_sdk_version, class_loader, caller_location); // Do some best effort to emulate library-path support. It will not // work for dependencies. // // Note: null has a special meaning and must be preserved. - std::string c_library_path; // Empty string by default. - if (library_path != nullptr && path != nullptr && path[0] != '/') { - ScopedUtfChars library_path_utf_chars(env, library_path); - c_library_path = library_path_utf_chars.c_str(); + std::string library_path; // Empty string by default. + if (library_path_j != nullptr && path != nullptr && path[0] != '/') { + ScopedUtfChars library_path_utf_chars(env, library_path_j); + library_path = library_path_utf_chars.c_str(); } - std::vector library_paths = base::Split(c_library_path, ":"); + std::vector library_paths = base::Split(library_path, ":"); for (const std::string& lib_path : library_paths) { *needs_native_bridge = false; @@ -323,7 +355,7 @@ void* OpenNativeLibrary(JNIEnv* env, int32_t target_sdk_version, const char* pat } } return nullptr; -#endif +#endif // !ART_TARGET_ANDROID } bool CloseNativeLibrary(void* handle, const bool needs_native_bridge, char** error_msg) { @@ -351,7 +383,7 @@ void NativeLoaderFreeErrorMessage(char* msg) { #if defined(ART_TARGET_ANDROID) void* OpenNativeLibraryInNamespace(NativeLoaderNamespace* ns, const char* path, bool* needs_native_bridge, char** error_msg) { - auto handle = ns->Load(path); + Result handle = ns->Load(path); if (!handle.ok() && error_msg != nullptr) { *error_msg = strdup(handle.error().message().c_str()); } @@ -397,4 +429,4 @@ void LinkNativeLoaderNamespaceToExportedNamespaceLibrary(struct NativeLoaderName #endif // ART_TARGET_ANDROID -}; // namespace android +} // namespace android diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp index 5b82d00560..1c82dc428f 100644 --- a/libnativeloader/native_loader_lazy.cpp +++ b/libnativeloader/native_loader_lazy.cpp @@ -35,7 +35,7 @@ void* GetLibHandle() { template FuncPtr GetFuncPtr(const char* function_name) { - auto f = reinterpret_cast(dlsym(GetLibHandle(), function_name)); + FuncPtr f = reinterpret_cast(dlsym(GetLibHandle(), function_name)); LOG_FATAL_IF(f == nullptr, "Failed to get address of %s: %s", function_name, dlerror()); return f; } diff --git a/libnativeloader/native_loader_namespace.cpp b/libnativeloader/native_loader_namespace.cpp index 669fa74dc2..cfb84b7d9e 100644 --- a/libnativeloader/native_loader_namespace.cpp +++ b/libnativeloader/native_loader_namespace.cpp @@ -52,12 +52,12 @@ std::string GetLinkerError(bool is_bridged) { Result NativeLoaderNamespace::GetExportedNamespace(const std::string& name, bool is_bridged) { if (!is_bridged) { - auto raw = android_get_exported_namespace(name.c_str()); + android_namespace_t* raw = android_get_exported_namespace(name.c_str()); if (raw != nullptr) { return NativeLoaderNamespace(name, raw); } } else { - auto raw = NativeBridgeGetExportedNamespace(name.c_str()); + native_bridge_namespace_t* raw = NativeBridgeGetExportedNamespace(name.c_str()); if (raw != nullptr) { return NativeLoaderNamespace(name, raw); } @@ -69,7 +69,7 @@ Result NativeLoaderNamespace::GetExportedNamespace(const // "system" for those in the Runtime APEX. Try "system" first since // "default" always exists. Result NativeLoaderNamespace::GetSystemNamespace(bool is_bridged) { - auto ns = GetExportedNamespace(kSystemNamespaceName, is_bridged); + Result ns = GetExportedNamespace(kSystemNamespaceName, is_bridged); if (ns.ok()) return ns; ns = GetExportedNamespace(kDefaultNamespaceName, is_bridged); if (ns.ok()) return ns; @@ -96,7 +96,7 @@ Result NativeLoaderNamespace::Create( } // Fall back to the system namespace if no parent is set. - auto system_ns = GetSystemNamespace(is_bridged); + Result system_ns = GetSystemNamespace(is_bridged); if (!system_ns.ok()) { return system_ns.error(); } diff --git a/libnativeloader/native_loader_test.cpp b/libnativeloader/native_loader_test.cpp index 72348ed364..3b05aae06b 100644 --- a/libnativeloader/native_loader_test.cpp +++ b/libnativeloader/native_loader_test.cpp @@ -564,7 +564,8 @@ jni com_android_bar libbar.so:libbar2.so public com_android_bar libpublic.so )"; - auto jni_libs = ParseApexLibrariesConfig(file_content, "jni"); + Result> jni_libs = + ParseApexLibrariesConfig(file_content, "jni"); ASSERT_RESULT_OK(jni_libs); std::map expected_jni_libs { {"com_android_foo", "libfoo.so"}, @@ -572,7 +573,8 @@ jni com_android_bar libbar.so:libbar2.so }; ASSERT_EQ(expected_jni_libs, *jni_libs); - auto public_libs = ParseApexLibrariesConfig(file_content, "public"); + Result> public_libs = + ParseApexLibrariesConfig(file_content, "public"); ASSERT_RESULT_OK(public_libs); std::map expected_public_libs { {"com_android_bar", "libpublic.so"}, @@ -586,7 +588,7 @@ jni com_android_foo libfoo # missing jni com_android_bar )"; - auto result = ParseApexLibrariesConfig(file_content, "jni"); + Result> result = ParseApexLibrariesConfig(file_content, "jni"); ASSERT_FALSE(result.ok()); ASSERT_EQ("Malformed line \"jni com_android_bar\"", result.error().message()); } @@ -598,7 +600,7 @@ public apex2 lib # unknown tag unknown com_android_foo libfoo )"; - auto result = ParseApexLibrariesConfig(file_content, "jni"); + Result> result = ParseApexLibrariesConfig(file_content, "jni"); ASSERT_FALSE(result.ok()); ASSERT_EQ("Invalid tag \"unknown com_android_foo libfoo\"", result.error().message()); } @@ -608,7 +610,7 @@ TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidApexNamespace) { # apex linker namespace should be mangled ('.' -> '_') jni com.android.foo lib )"; - auto result = ParseApexLibrariesConfig(file_content, "jni"); + Result> result = ParseApexLibrariesConfig(file_content, "jni"); ASSERT_FALSE(result.ok()); ASSERT_EQ("Invalid apex_namespace \"jni com.android.foo lib\"", result.error().message()); } @@ -618,7 +620,7 @@ TEST(NativeLoaderApexLibrariesConfigParser, RejectInvalidLibraryList) { # library list is ":" separated list of filenames jni com_android_foo lib64/libfoo.so )"; - auto result = ParseApexLibrariesConfig(file_content, "jni"); + Result> result = ParseApexLibrariesConfig(file_content, "jni"); ASSERT_FALSE(result.ok()); ASSERT_EQ("Invalid library_list \"jni com_android_foo lib64/libfoo.so\"", result.error().message()); } diff --git a/libnativeloader/public_libraries.cpp b/libnativeloader/public_libraries.cpp index 0ba18f3ecf..af965a09a9 100644 --- a/libnativeloader/public_libraries.cpp +++ b/libnativeloader/public_libraries.cpp @@ -78,7 +78,7 @@ std::string vndk_version_str(bool use_product_vndk) { // insert vndk version in every {} placeholder void InsertVndkVersionStr(std::string* file_name, bool use_product_vndk) { CHECK(file_name != nullptr); - auto version = vndk_version_str(use_product_vndk); + const std::string version = vndk_version_str(use_product_vndk); size_t pos = file_name->find("{}"); while (pos != std::string::npos) { file_name->replace(pos, 2, version); @@ -123,7 +123,7 @@ void ReadExtensionLibraries(const char* dirname, std::vector* sonam "Error extracting company name from public native library list file path \"%s\"", config_file_path.c_str()); - auto ret = ReadConfig( + Result> ret = ReadConfig( config_file_path, [&company_name](const struct ConfigEntry& entry) -> Result { if (android::base::StartsWith(entry.soname, "lib") && android::base::EndsWith(entry.soname, "." + company_name + ".so")) { @@ -149,7 +149,7 @@ void ReadExtensionLibraries(const char* dirname, std::vector* sonam static std::string InitDefaultPublicLibraries(bool for_preload) { std::string config_file = root_dir() + kDefaultPublicLibrariesFile; - auto sonames = + Result> sonames = ReadConfig(config_file, [&for_preload](const struct ConfigEntry& entry) -> Result { if (for_preload) { return !entry.nopreload; @@ -167,8 +167,8 @@ static std::string InitDefaultPublicLibraries(bool for_preload) { if (!for_preload) { // Remove the public libs provided by apexes because these libs are available // from apex namespaces. - for (const auto& p : apex_public_libraries()) { - auto public_libs = base::Split(p.second, ":"); + for (const std::pair& p : apex_public_libraries()) { + std::vector public_libs = base::Split(p.second, ":"); sonames->erase(std::remove_if(sonames->begin(), sonames->end(), [&public_libs](const std::string& v) { @@ -186,7 +186,7 @@ static std::string InitDefaultPublicLibraries(bool for_preload) { static std::string InitVendorPublicLibraries() { // This file is optional, quietly ignore if the file does not exist. - auto sonames = ReadConfig(kVendorPublicLibrariesFile, always_true); + Result> sonames = ReadConfig(kVendorPublicLibrariesFile, always_true); if (!sonames.ok()) { ALOGI("InitVendorPublicLibraries skipped: %s", sonames.error().message().c_str()); return ""; @@ -250,7 +250,7 @@ static std::string InitLlndkLibrariesVendor() { } else { config_file = kLlndkLibrariesNoVndkFile; } - auto sonames = ReadConfig(config_file, always_true); + Result> sonames = ReadConfig(config_file, always_true); if (!sonames.ok()) { LOG_ALWAYS_FATAL("%s: %s", config_file.c_str(), sonames.error().message().c_str()); return ""; @@ -272,7 +272,7 @@ static std::string InitLlndkLibrariesProduct() { } else { config_file = kLlndkLibrariesNoVndkFile; } - auto sonames = ReadConfig(config_file, always_true); + Result> sonames = ReadConfig(config_file, always_true); if (!sonames.ok()) { LOG_ALWAYS_FATAL("%s: %s", config_file.c_str(), sonames.error().message().c_str()); return ""; @@ -290,7 +290,7 @@ static std::string InitVndkspLibrariesVendor() { std::string config_file = kVndkLibrariesFile; InsertVndkVersionStr(&config_file, false); - auto sonames = ReadConfig(config_file, always_true); + Result> sonames = ReadConfig(config_file, always_true); if (!sonames.ok()) { LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str()); return ""; @@ -307,7 +307,7 @@ static std::string InitVndkspLibrariesProduct() { } std::string config_file = kVndkLibrariesFile; InsertVndkVersionStr(&config_file, true); - auto sonames = ReadConfig(config_file, always_true); + Result> sonames = ReadConfig(config_file, always_true); if (!sonames.ok()) { LOG_ALWAYS_FATAL("%s", sonames.error().message().c_str()); return ""; @@ -460,8 +460,8 @@ Result> ParseConfig( std::vector lines = base::Split(file_content, "\n"); std::vector sonames; - for (auto& line : lines) { - auto trimmed_line = base::Trim(line); + for (std::string& line : lines) { + std::string trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue; } @@ -528,12 +528,12 @@ Result> ParseConfig( Result> ParseApexLibrariesConfig(const std::string& file_content, const std::string& tag) { std::map entries; std::vector lines = base::Split(file_content, "\n"); - for (auto& line : lines) { - auto trimmed_line = base::Trim(line); + for (std::string& line : lines) { + std::string trimmed_line = base::Trim(line); if (trimmed_line[0] == '#' || trimmed_line.empty()) { continue; } - auto config_line = ParseApexLibrariesConfigLine(trimmed_line); + Result config_line = ParseApexLibrariesConfigLine(trimmed_line); if (!config_line.ok()) { return config_line.error(); }