1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "nativeloader/native_loader.h" 18#include <nativehelper/ScopedUtfChars.h> 19 20#include <dlfcn.h> 21#ifdef __ANDROID__ 22#define LOG_TAG "libnativeloader" 23#include "nativeloader/dlext_namespaces.h" 24#include "cutils/properties.h" 25#include "log/log.h" 26#endif 27#include "nativebridge/native_bridge.h" 28 29#include <algorithm> 30#include <vector> 31#include <string> 32#include <mutex> 33 34#include <android-base/file.h> 35#include <android-base/macros.h> 36#include <android-base/strings.h> 37 38#define CHECK(predicate) LOG_ALWAYS_FATAL_IF(!(predicate),\ 39 "%s:%d: %s CHECK '" #predicate "' failed.",\ 40 __FILE__, __LINE__, __FUNCTION__) 41 42namespace android { 43 44#if defined(__ANDROID__) 45class NativeLoaderNamespace { 46 public: 47 NativeLoaderNamespace() 48 : android_ns_(nullptr), native_bridge_ns_(nullptr) { } 49 50 explicit NativeLoaderNamespace(android_namespace_t* ns) 51 : android_ns_(ns), native_bridge_ns_(nullptr) { } 52 53 explicit NativeLoaderNamespace(native_bridge_namespace_t* ns) 54 : android_ns_(nullptr), native_bridge_ns_(ns) { } 55 56 NativeLoaderNamespace(NativeLoaderNamespace&& that) = default; 57 NativeLoaderNamespace(const NativeLoaderNamespace& that) = default; 58 59 NativeLoaderNamespace& operator=(const NativeLoaderNamespace& that) = default; 60 61 android_namespace_t* get_android_ns() const { 62 CHECK(native_bridge_ns_ == nullptr); 63 return android_ns_; 64 } 65 66 native_bridge_namespace_t* get_native_bridge_ns() const { 67 CHECK(android_ns_ == nullptr); 68 return native_bridge_ns_; 69 } 70 71 bool is_android_namespace() const { 72 return native_bridge_ns_ == nullptr; 73 } 74 75 private: 76 // Only one of them can be not null 77 android_namespace_t* android_ns_; 78 native_bridge_namespace_t* native_bridge_ns_; 79}; 80 81static constexpr const char* kPublicNativeLibrariesSystemConfigPathFromRoot = 82 "/etc/public.libraries.txt"; 83static constexpr const char* kPublicNativeLibrariesVendorConfig = 84 "/vendor/etc/public.libraries.txt"; 85static constexpr const char* kLlndkNativeLibrariesSystemConfigPathFromRoot = 86 "/etc/llndk.libraries.txt"; 87static constexpr const char* kVndkspNativeLibrariesSystemConfigPathFromRoot = 88 "/etc/vndksp.libraries.txt"; 89 90 91// The device may be configured to have the vendor libraries loaded to a separate namespace. 92// For historical reasons this namespace was named sphal but effectively it is intended 93// to use to load vendor libraries to separate namespace with controlled interface between 94// vendor and system namespaces. 95static constexpr const char* kVendorNamespaceName = "sphal"; 96 97static constexpr const char* kVndkNamespaceName = "vndk"; 98 99static constexpr const char* kClassloaderNamespaceName = "classloader-namespace"; 100static constexpr const char* kVendorClassloaderNamespaceName = "vendor-classloader-namespace"; 101 102// (http://b/27588281) This is a workaround for apps using custom classloaders and calling 103// System.load() with an absolute path which is outside of the classloader library search path. 104// This list includes all directories app is allowed to access this way. 105static constexpr const char* kWhitelistedDirectories = "/data:/mnt/expand"; 106 107static bool is_debuggable() { 108 char debuggable[PROP_VALUE_MAX]; 109 property_get("ro.debuggable", debuggable, "0"); 110 return std::string(debuggable) == "1"; 111} 112 113class LibraryNamespaces { 114 public: 115 LibraryNamespaces() : initialized_(false) { } 116 117 bool Create(JNIEnv* env, 118 uint32_t target_sdk_version, 119 jobject class_loader, 120 bool is_shared, 121 bool is_for_vendor, 122 jstring java_library_path, 123 jstring java_permitted_path, 124 NativeLoaderNamespace* ns, 125 std::string* error_msg) { 126 std::string library_path; // empty string by default. 127 128 if (java_library_path != nullptr) { 129 ScopedUtfChars library_path_utf_chars(env, java_library_path); 130 library_path = library_path_utf_chars.c_str(); 131 } 132 133 // (http://b/27588281) This is a workaround for apps using custom 134 // classloaders and calling System.load() with an absolute path which 135 // is outside of the classloader library search path. 136 // 137 // This part effectively allows such a classloader to access anything 138 // under /data and /mnt/expand 139 std::string permitted_path = kWhitelistedDirectories; 140 141 if (java_permitted_path != nullptr) { 142 ScopedUtfChars path(env, java_permitted_path); 143 if (path.c_str() != nullptr && path.size() > 0) { 144 permitted_path = permitted_path + ":" + path.c_str(); 145 } 146 } 147 148 if (!initialized_ && !InitPublicNamespace(library_path.c_str(), error_msg)) { 149 return false; 150 } 151 152 bool found = FindNamespaceByClassLoader(env, class_loader, nullptr); 153 154 LOG_ALWAYS_FATAL_IF(found, 155 "There is already a namespace associated with this classloader"); 156 157 uint64_t namespace_type = ANDROID_NAMESPACE_TYPE_ISOLATED; 158 if (is_shared) { 159 namespace_type |= ANDROID_NAMESPACE_TYPE_SHARED; 160 } 161 162 if (target_sdk_version < 24) { 163 namespace_type |= ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED; 164 } 165 166 NativeLoaderNamespace parent_ns; 167 bool found_parent_namespace = FindParentNamespaceByClassLoader(env, class_loader, &parent_ns); 168 169 bool is_native_bridge = false; 170 171 if (found_parent_namespace) { 172 is_native_bridge = !parent_ns.is_android_namespace(); 173 } else if (!library_path.empty()) { 174 is_native_bridge = NativeBridgeIsPathSupported(library_path.c_str()); 175 } 176 177 std::string system_exposed_libraries = system_public_libraries_; 178 const char* namespace_name = kClassloaderNamespaceName; 179 android_namespace_t* vndk_ns = nullptr; 180 if (is_for_vendor && !is_shared) { 181 LOG_FATAL_IF(is_native_bridge, "Unbundled vendor apk must not use translated architecture"); 182 183 // For vendor apks, give access to the vendor lib even though 184 // they are treated as unbundled; the libs and apks are still bundled 185 // together in the vendor partition. 186#if defined(__LP64__) 187 std::string vendor_lib_path = "/vendor/lib64"; 188#else 189 std::string vendor_lib_path = "/vendor/lib"; 190#endif 191 library_path = library_path + ":" + vendor_lib_path.c_str(); 192 permitted_path = permitted_path + ":" + vendor_lib_path.c_str(); 193 194 // Also give access to LLNDK libraries since they are available to vendors 195 system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str(); 196 197 // Give access to VNDK-SP libraries from the 'vndk' namespace. 198 vndk_ns = android_get_exported_namespace(kVndkNamespaceName); 199 LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr, 200 "Cannot find \"%s\" namespace for vendor apks", kVndkNamespaceName); 201 202 // Different name is useful for debugging 203 namespace_name = kVendorClassloaderNamespaceName; 204 ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str()); 205 } 206 207 NativeLoaderNamespace native_loader_ns; 208 if (!is_native_bridge) { 209 android_namespace_t* ns = android_create_namespace(namespace_name, 210 nullptr, 211 library_path.c_str(), 212 namespace_type, 213 permitted_path.c_str(), 214 parent_ns.get_android_ns()); 215 if (ns == nullptr) { 216 *error_msg = dlerror(); 217 return false; 218 } 219 220 // Note that when vendor_ns is not configured this function will return nullptr 221 // and it will result in linking vendor_public_libraries_ to the default namespace 222 // which is expected behavior in this case. 223 android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName); 224 225 if (!android_link_namespaces(ns, nullptr, system_exposed_libraries.c_str())) { 226 *error_msg = dlerror(); 227 return false; 228 } 229 230 if (vndk_ns != nullptr && !system_vndksp_libraries_.empty()) { 231 // vendor apks are allowed to use VNDK-SP libraries. 232 if (!android_link_namespaces(ns, vndk_ns, system_vndksp_libraries_.c_str())) { 233 *error_msg = dlerror(); 234 return false; 235 } 236 } 237 238 if (!vendor_public_libraries_.empty()) { 239 if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) { 240 *error_msg = dlerror(); 241 return false; 242 } 243 } 244 245 native_loader_ns = NativeLoaderNamespace(ns); 246 } else { 247 native_bridge_namespace_t* ns = NativeBridgeCreateNamespace(namespace_name, 248 nullptr, 249 library_path.c_str(), 250 namespace_type, 251 permitted_path.c_str(), 252 parent_ns.get_native_bridge_ns()); 253 254 if (ns == nullptr) { 255 *error_msg = NativeBridgeGetError(); 256 return false; 257 } 258 259 native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace(); 260 261 if (!NativeBridgeLinkNamespaces(ns, nullptr, system_exposed_libraries.c_str())) { 262 *error_msg = NativeBridgeGetError(); 263 return false; 264 } 265 266 if (!vendor_public_libraries_.empty()) { 267 if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) { 268 *error_msg = NativeBridgeGetError(); 269 return false; 270 } 271 } 272 273 native_loader_ns = NativeLoaderNamespace(ns); 274 } 275 276 namespaces_.push_back(std::make_pair(env->NewWeakGlobalRef(class_loader), native_loader_ns)); 277 278 *ns = native_loader_ns; 279 return true; 280 } 281 282 bool FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader, NativeLoaderNamespace* ns) { 283 auto it = std::find_if(namespaces_.begin(), namespaces_.end(), 284 [&](const std::pair<jweak, NativeLoaderNamespace>& value) { 285 return env->IsSameObject(value.first, class_loader); 286 }); 287 if (it != namespaces_.end()) { 288 if (ns != nullptr) { 289 *ns = it->second; 290 } 291 292 return true; 293 } 294 295 return false; 296 } 297 298 void Initialize() { 299 // Once public namespace is initialized there is no 300 // point in running this code - it will have no effect 301 // on the current list of public libraries. 302 if (initialized_) { 303 return; 304 } 305 306 std::vector<std::string> sonames; 307 const char* android_root_env = getenv("ANDROID_ROOT"); 308 std::string root_dir = android_root_env != nullptr ? android_root_env : "/system"; 309 std::string public_native_libraries_system_config = 310 root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot; 311 std::string llndk_native_libraries_system_config = 312 root_dir + kLlndkNativeLibrariesSystemConfigPathFromRoot; 313 std::string vndksp_native_libraries_system_config = 314 root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot; 315 316 std::string error_msg; 317 LOG_ALWAYS_FATAL_IF(!ReadConfig(public_native_libraries_system_config, &sonames, &error_msg), 318 "Error reading public native library list from \"%s\": %s", 319 public_native_libraries_system_config.c_str(), error_msg.c_str()); 320 321 // For debuggable platform builds use ANDROID_ADDITIONAL_PUBLIC_LIBRARIES environment 322 // variable to add libraries to the list. This is intended for platform tests only. 323 if (is_debuggable()) { 324 const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES"); 325 if (additional_libs != nullptr && additional_libs[0] != '\0') { 326 std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":"); 327 std::copy(additional_libs_vector.begin(), 328 additional_libs_vector.end(), 329 std::back_inserter(sonames)); 330 } 331 } 332 333 // android_init_namespaces() expects all the public libraries 334 // to be loaded so that they can be found by soname alone. 335 // 336 // TODO(dimitry): this is a bit misleading since we do not know 337 // if the vendor public library is going to be opened from /vendor/lib 338 // we might as well end up loading them from /system/lib 339 // For now we rely on CTS test to catch things like this but 340 // it should probably be addressed in the future. 341 for (const auto& soname : sonames) { 342 LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr, 343 "Error preloading public library %s: %s", 344 soname.c_str(), dlerror()); 345 } 346 347 system_public_libraries_ = base::Join(sonames, ':'); 348 349 sonames.clear(); 350 ReadConfig(kLlndkNativeLibrariesSystemConfigPathFromRoot, &sonames); 351 system_llndk_libraries_ = base::Join(sonames, ':'); 352 353 sonames.clear(); 354 ReadConfig(kVndkspNativeLibrariesSystemConfigPathFromRoot, &sonames); 355 system_vndksp_libraries_ = base::Join(sonames, ':'); 356 357 sonames.clear(); 358 // This file is optional, quietly ignore if the file does not exist. 359 ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames); 360 361 vendor_public_libraries_ = base::Join(sonames, ':'); 362 } 363 364 void Reset() { 365 namespaces_.clear(); 366 } 367 368 private: 369 bool ReadConfig(const std::string& configFile, std::vector<std::string>* sonames, 370 std::string* error_msg = nullptr) { 371 // Read list of public native libraries from the config file. 372 std::string file_content; 373 if(!base::ReadFileToString(configFile, &file_content)) { 374 if (error_msg) *error_msg = strerror(errno); 375 return false; 376 } 377 378 std::vector<std::string> lines = base::Split(file_content, "\n"); 379 380 for (auto& line : lines) { 381 auto trimmed_line = base::Trim(line); 382 if (trimmed_line[0] == '#' || trimmed_line.empty()) { 383 continue; 384 } 385 size_t space_pos = trimmed_line.rfind(' '); 386 if (space_pos != std::string::npos) { 387 std::string type = trimmed_line.substr(space_pos + 1); 388 if (type != "32" && type != "64") { 389 if (error_msg) *error_msg = "Malformed line: " + line; 390 return false; 391 } 392#if defined(__LP64__) 393 // Skip 32 bit public library. 394 if (type == "32") { 395 continue; 396 } 397#else 398 // Skip 64 bit public library. 399 if (type == "64") { 400 continue; 401 } 402#endif 403 trimmed_line.resize(space_pos); 404 } 405 406 sonames->push_back(trimmed_line); 407 } 408 409 return true; 410 } 411 412 bool InitPublicNamespace(const char* library_path, std::string* error_msg) { 413 // Ask native bride if this apps library path should be handled by it 414 bool is_native_bridge = NativeBridgeIsPathSupported(library_path); 415 416 // (http://b/25844435) - Some apps call dlopen from generated code (mono jited 417 // code is one example) unknown to linker in which case linker uses anonymous 418 // namespace. The second argument specifies the search path for the anonymous 419 // namespace which is the library_path of the classloader. 420 initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(), 421 is_native_bridge ? nullptr : library_path); 422 if (!initialized_) { 423 *error_msg = dlerror(); 424 return false; 425 } 426 427 // and now initialize native bridge namespaces if necessary. 428 if (NativeBridgeInitialized()) { 429 initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(), 430 is_native_bridge ? library_path : nullptr); 431 if (!initialized_) { 432 *error_msg = NativeBridgeGetError(); 433 } 434 } 435 436 return initialized_; 437 } 438 439 jobject GetParentClassLoader(JNIEnv* env, jobject class_loader) { 440 jclass class_loader_class = env->FindClass("java/lang/ClassLoader"); 441 jmethodID get_parent = env->GetMethodID(class_loader_class, 442 "getParent", 443 "()Ljava/lang/ClassLoader;"); 444 445 return env->CallObjectMethod(class_loader, get_parent); 446 } 447 448 bool FindParentNamespaceByClassLoader(JNIEnv* env, 449 jobject class_loader, 450 NativeLoaderNamespace* ns) { 451 jobject parent_class_loader = GetParentClassLoader(env, class_loader); 452 453 while (parent_class_loader != nullptr) { 454 if (FindNamespaceByClassLoader(env, parent_class_loader, ns)) { 455 return true; 456 } 457 458 parent_class_loader = GetParentClassLoader(env, parent_class_loader); 459 } 460 461 return false; 462 } 463 464 bool initialized_; 465 std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_; 466 std::string system_public_libraries_; 467 std::string vendor_public_libraries_; 468 std::string system_llndk_libraries_; 469 std::string system_vndksp_libraries_; 470 471 DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces); 472}; 473 474static std::mutex g_namespaces_mutex; 475static LibraryNamespaces* g_namespaces = new LibraryNamespaces; 476#endif 477 478void InitializeNativeLoader() { 479#if defined(__ANDROID__) 480 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 481 g_namespaces->Initialize(); 482#endif 483} 484 485void ResetNativeLoader() { 486#if defined(__ANDROID__) 487 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 488 g_namespaces->Reset(); 489#endif 490} 491 492jstring CreateClassLoaderNamespace(JNIEnv* env, 493 int32_t target_sdk_version, 494 jobject class_loader, 495 bool is_shared, 496 bool is_for_vendor, 497 jstring library_path, 498 jstring permitted_path) { 499#if defined(__ANDROID__) 500 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 501 502 std::string error_msg; 503 NativeLoaderNamespace ns; 504 bool success = g_namespaces->Create(env, 505 target_sdk_version, 506 class_loader, 507 is_shared, 508 is_for_vendor, 509 library_path, 510 permitted_path, 511 &ns, 512 &error_msg); 513 if (!success) { 514 return env->NewStringUTF(error_msg.c_str()); 515 } 516#else 517 UNUSED(env, target_sdk_version, class_loader, is_shared, is_for_vendor, 518 library_path, permitted_path); 519#endif 520 return nullptr; 521} 522 523void* OpenNativeLibrary(JNIEnv* env, 524 int32_t target_sdk_version, 525 const char* path, 526 jobject class_loader, 527 jstring library_path, 528 bool* needs_native_bridge, 529 std::string* error_msg) { 530#if defined(__ANDROID__) 531 UNUSED(target_sdk_version); 532 if (class_loader == nullptr) { 533 *needs_native_bridge = false; 534 return dlopen(path, RTLD_NOW); 535 } 536 537 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 538 NativeLoaderNamespace ns; 539 540 if (!g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) { 541 // This is the case where the classloader was not created by ApplicationLoaders 542 // In this case we create an isolated not-shared namespace for it. 543 if (!g_namespaces->Create(env, 544 target_sdk_version, 545 class_loader, 546 false /* is_shared */, 547 false /* is_for_vendor */, 548 library_path, 549 nullptr, 550 &ns, 551 error_msg)) { 552 return nullptr; 553 } 554 } 555 556 if (ns.is_android_namespace()) { 557 android_dlextinfo extinfo; 558 extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE; 559 extinfo.library_namespace = ns.get_android_ns(); 560 561 void* handle = android_dlopen_ext(path, RTLD_NOW, &extinfo); 562 if (handle == nullptr) { 563 *error_msg = dlerror(); 564 } 565 *needs_native_bridge = false; 566 return handle; 567 } else { 568 void* handle = NativeBridgeLoadLibraryExt(path, RTLD_NOW, ns.get_native_bridge_ns()); 569 if (handle == nullptr) { 570 *error_msg = NativeBridgeGetError(); 571 } 572 *needs_native_bridge = true; 573 return handle; 574 } 575#else 576 UNUSED(env, target_sdk_version, class_loader, library_path); 577 *needs_native_bridge = false; 578 void* handle = dlopen(path, RTLD_NOW); 579 if (handle == nullptr) { 580 if (NativeBridgeIsSupported(path)) { 581 *needs_native_bridge = true; 582 handle = NativeBridgeLoadLibrary(path, RTLD_NOW); 583 if (handle == nullptr) { 584 *error_msg = NativeBridgeGetError(); 585 } 586 } else { 587 *needs_native_bridge = false; 588 *error_msg = dlerror(); 589 } 590 } 591 return handle; 592#endif 593} 594 595bool CloseNativeLibrary(void* handle, const bool needs_native_bridge) { 596 return needs_native_bridge ? NativeBridgeUnloadLibrary(handle) : 597 dlclose(handle); 598} 599 600#if defined(__ANDROID__) 601// native_bridge_namespaces are not supported for callers of this function. 602// This function will return nullptr in the case when application is running 603// on native bridge. 604android_namespace_t* FindNamespaceByClassLoader(JNIEnv* env, jobject class_loader) { 605 std::lock_guard<std::mutex> guard(g_namespaces_mutex); 606 NativeLoaderNamespace ns; 607 if (g_namespaces->FindNamespaceByClassLoader(env, class_loader, &ns)) { 608 return ns.is_android_namespace() ? ns.get_android_ns() : nullptr; 609 } 610 611 return nullptr; 612} 613#endif 614 615}; // android namespace 616