1 /* 2 * Copyright (C) 2014 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 #define LOG_TAG "nativebridge" 18 19 #include "nativebridge/native_bridge.h" 20 21 #include <dlfcn.h> 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <stdio.h> 25 #include <sys/mount.h> 26 #include <sys/stat.h> 27 #include <unistd.h> 28 29 #include <cstring> 30 31 #include <android-base/macros.h> 32 #include <log/log.h> 33 34 namespace android { 35 36 // Environment values required by the apps running with native bridge. 37 struct NativeBridgeRuntimeValues { 38 const char* os_arch; 39 const char* cpu_abi; 40 const char* cpu_abi2; 41 const char* *supported_abis; 42 int32_t abi_count; 43 }; 44 45 // The symbol name exposed by native-bridge with the type of NativeBridgeCallbacks. 46 static constexpr const char* kNativeBridgeInterfaceSymbol = "NativeBridgeItf"; 47 48 enum class NativeBridgeState { 49 kNotSetup, // Initial state. 50 kOpened, // After successful dlopen. 51 kPreInitialized, // After successful pre-initialization. 52 kInitialized, // After successful initialization. 53 kClosed // Closed or errors. 54 }; 55 56 static constexpr const char* kNotSetupString = "kNotSetup"; 57 static constexpr const char* kOpenedString = "kOpened"; 58 static constexpr const char* kPreInitializedString = "kPreInitialized"; 59 static constexpr const char* kInitializedString = "kInitialized"; 60 static constexpr const char* kClosedString = "kClosed"; 61 62 static const char* GetNativeBridgeStateString(NativeBridgeState state) { 63 switch (state) { 64 case NativeBridgeState::kNotSetup: 65 return kNotSetupString; 66 67 case NativeBridgeState::kOpened: 68 return kOpenedString; 69 70 case NativeBridgeState::kPreInitialized: 71 return kPreInitializedString; 72 73 case NativeBridgeState::kInitialized: 74 return kInitializedString; 75 76 case NativeBridgeState::kClosed: 77 return kClosedString; 78 } 79 } 80 81 // Current state of the native bridge. 82 static NativeBridgeState state = NativeBridgeState::kNotSetup; 83 84 // The version of NativeBridge implementation. 85 // Different Nativebridge interface needs the service of different version of 86 // Nativebridge implementation. 87 // Used by isCompatibleWith() which is introduced in v2. 88 enum NativeBridgeImplementationVersion { 89 // first version, not used. 90 DEFAULT_VERSION = 1, 91 // The version which signal semantic is introduced. 92 SIGNAL_VERSION = 2, 93 // The version which namespace semantic is introduced. 94 NAMESPACE_VERSION = 3, 95 // The version with vendor namespaces 96 VENDOR_NAMESPACE_VERSION = 4, 97 }; 98 99 // Whether we had an error at some point. 100 static bool had_error = false; 101 102 // Handle of the loaded library. 103 static void* native_bridge_handle = nullptr; 104 // Pointer to the callbacks. Available as soon as LoadNativeBridge succeeds, but only initialized 105 // later. 106 static const NativeBridgeCallbacks* callbacks = nullptr; 107 // Callbacks provided by the environment to the bridge. Passed to LoadNativeBridge. 108 static const NativeBridgeRuntimeCallbacks* runtime_callbacks = nullptr; 109 110 // The app's code cache directory. 111 static char* app_code_cache_dir = nullptr; 112 113 // Code cache directory (relative to the application private directory) 114 // Ideally we'd like to call into framework to retrieve this name. However that's considered an 115 // implementation detail and will require either hacks or consistent refactorings. We compromise 116 // and hard code the directory name again here. 117 static constexpr const char* kCodeCacheDir = "code_cache"; 118 119 // Characters allowed in a native bridge filename. The first character must 120 // be in [a-zA-Z] (expected 'l' for "libx"). The rest must be in [a-zA-Z0-9._-]. 121 static bool CharacterAllowed(char c, bool first) { 122 if (first) { 123 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); 124 } else { 125 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || 126 (c == '.') || (c == '_') || (c == '-'); 127 } 128 } 129 130 static void ReleaseAppCodeCacheDir() { 131 if (app_code_cache_dir != nullptr) { 132 delete[] app_code_cache_dir; 133 app_code_cache_dir = nullptr; 134 } 135 } 136 137 // We only allow simple names for the library. It is supposed to be a file in 138 // /system/lib or /vendor/lib. Only allow a small range of characters, that is 139 // names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z]. 140 bool NativeBridgeNameAcceptable(const char* nb_library_filename) { 141 const char* ptr = nb_library_filename; 142 if (*ptr == 0) { 143 // Emptry string. Allowed, means no native bridge. 144 return true; 145 } else { 146 // First character must be [a-zA-Z]. 147 if (!CharacterAllowed(*ptr, true)) { 148 // Found an invalid fist character, don't accept. 149 ALOGE("Native bridge library %s has been rejected for first character %c", 150 nb_library_filename, 151 *ptr); 152 return false; 153 } else { 154 // For the rest, be more liberal. 155 ptr++; 156 while (*ptr != 0) { 157 if (!CharacterAllowed(*ptr, false)) { 158 // Found an invalid character, don't accept. 159 ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr); 160 return false; 161 } 162 ptr++; 163 } 164 } 165 return true; 166 } 167 } 168 169 // The policy of invoking Nativebridge changed in v3 with/without namespace. 170 // Suggest Nativebridge implementation not maintain backward-compatible. 171 static bool isCompatibleWith(const uint32_t version) { 172 // Libnativebridge is now designed to be forward-compatible. So only "0" is an unsupported 173 // version. 174 if (callbacks == nullptr || callbacks->version == 0 || version == 0) { 175 return false; 176 } 177 178 // If this is a v2+ bridge, it may not be forwards- or backwards-compatible. Check. 179 if (callbacks->version >= SIGNAL_VERSION) { 180 return callbacks->isCompatibleWith(version); 181 } 182 183 return true; 184 } 185 186 static void CloseNativeBridge(bool with_error) { 187 state = NativeBridgeState::kClosed; 188 had_error |= with_error; 189 ReleaseAppCodeCacheDir(); 190 } 191 192 bool LoadNativeBridge(const char* nb_library_filename, 193 const NativeBridgeRuntimeCallbacks* runtime_cbs) { 194 // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not 195 // multi-threaded, so we do not need locking here. 196 197 if (state != NativeBridgeState::kNotSetup) { 198 // Setup has been called before. Ignore this call. 199 if (nb_library_filename != nullptr) { // Avoids some log-spam for dalvikvm. 200 ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.", 201 GetNativeBridgeStateString(state)); 202 } 203 // Note: counts as an error, even though the bridge may be functional. 204 had_error = true; 205 return false; 206 } 207 208 if (nb_library_filename == nullptr || *nb_library_filename == 0) { 209 CloseNativeBridge(false); 210 return false; 211 } else { 212 if (!NativeBridgeNameAcceptable(nb_library_filename)) { 213 CloseNativeBridge(true); 214 } else { 215 // Try to open the library. 216 void* handle = dlopen(nb_library_filename, RTLD_LAZY); 217 if (handle != nullptr) { 218 callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, 219 kNativeBridgeInterfaceSymbol)); 220 if (callbacks != nullptr) { 221 if (isCompatibleWith(NAMESPACE_VERSION)) { 222 // Store the handle for later. 223 native_bridge_handle = handle; 224 } else { 225 callbacks = nullptr; 226 dlclose(handle); 227 ALOGW("Unsupported native bridge interface."); 228 } 229 } else { 230 dlclose(handle); 231 } 232 } 233 234 // Two failure conditions: could not find library (dlopen failed), or could not find native 235 // bridge interface (dlsym failed). Both are an error and close the native bridge. 236 if (callbacks == nullptr) { 237 CloseNativeBridge(true); 238 } else { 239 runtime_callbacks = runtime_cbs; 240 state = NativeBridgeState::kOpened; 241 } 242 } 243 return state == NativeBridgeState::kOpened; 244 } 245 } 246 247 bool NeedsNativeBridge(const char* instruction_set) { 248 if (instruction_set == nullptr) { 249 ALOGE("Null instruction set in NeedsNativeBridge."); 250 return false; 251 } 252 return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0; 253 } 254 255 #ifdef __APPLE__ 256 template<typename T> void UNUSED(const T&) {} 257 #endif 258 259 bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) { 260 if (state != NativeBridgeState::kOpened) { 261 ALOGE("Invalid state: native bridge is expected to be opened."); 262 CloseNativeBridge(true); 263 return false; 264 } 265 266 if (app_data_dir_in == nullptr) { 267 ALOGE("Application private directory cannot be null."); 268 CloseNativeBridge(true); 269 return false; 270 } 271 272 // Create the path to the application code cache directory. 273 // The memory will be release after Initialization or when the native bridge is closed. 274 const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/' 275 app_code_cache_dir = new char[len]; 276 snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir); 277 278 // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo. 279 // Failure is not fatal and will keep the native bridge in kPreInitialized. 280 state = NativeBridgeState::kPreInitialized; 281 282 #ifndef __APPLE__ 283 if (instruction_set == nullptr) { 284 return true; 285 } 286 size_t isa_len = strlen(instruction_set); 287 if (isa_len > 10) { 288 // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for 289 // x86_64 [including the trailing \0]). This is so we don't have to change here if there will 290 // be another instruction set in the future. 291 ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.", 292 instruction_set); 293 return true; 294 } 295 296 // If the file does not exist, the mount command will fail, 297 // so we save the extra file existence check. 298 char cpuinfo_path[1024]; 299 300 #if defined(__ANDROID__) 301 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib" 302 #ifdef __LP64__ 303 "64" 304 #endif // __LP64__ 305 "/%s/cpuinfo", instruction_set); 306 #else // !__ANDROID__ 307 // To be able to test on the host, we hardwire a relative path. 308 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo"); 309 #endif 310 311 // Bind-mount. 312 if (TEMP_FAILURE_RETRY(mount(cpuinfo_path, // Source. 313 "/proc/cpuinfo", // Target. 314 nullptr, // FS type. 315 MS_BIND, // Mount flags: bind mount. 316 nullptr)) == -1) { // "Data." 317 ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno)); 318 } 319 #else // __APPLE__ 320 UNUSED(instruction_set); 321 ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible."); 322 #endif 323 324 return true; 325 } 326 327 static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) { 328 if (value != nullptr) { 329 jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;"); 330 if (field_id == nullptr) { 331 env->ExceptionClear(); 332 ALOGW("Could not find %s field.", field); 333 return; 334 } 335 336 jstring str = env->NewStringUTF(value); 337 if (str == nullptr) { 338 env->ExceptionClear(); 339 ALOGW("Could not create string %s.", value); 340 return; 341 } 342 343 env->SetStaticObjectField(build_class, field_id, str); 344 } 345 } 346 347 // Set up the environment for the bridged app. 348 static void SetupEnvironment(const NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) { 349 // Need a JNIEnv* to do anything. 350 if (env == nullptr) { 351 ALOGW("No JNIEnv* to set up app environment."); 352 return; 353 } 354 355 // Query the bridge for environment values. 356 const struct NativeBridgeRuntimeValues* env_values = callbacks->getAppEnv(isa); 357 if (env_values == nullptr) { 358 return; 359 } 360 361 // Keep the JNIEnv clean. 362 jint success = env->PushLocalFrame(16); // That should be small and large enough. 363 if (success < 0) { 364 // Out of memory, really borked. 365 ALOGW("Out of memory while setting up app environment."); 366 env->ExceptionClear(); 367 return; 368 } 369 370 // Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge. 371 if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr || 372 env_values->abi_count >= 0) { 373 jclass bclass_id = env->FindClass("android/os/Build"); 374 if (bclass_id != nullptr) { 375 SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi); 376 SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2); 377 } else { 378 // For example in a host test environment. 379 env->ExceptionClear(); 380 ALOGW("Could not find Build class."); 381 } 382 } 383 384 if (env_values->os_arch != nullptr) { 385 jclass sclass_id = env->FindClass("java/lang/System"); 386 if (sclass_id != nullptr) { 387 jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "setUnchangeableSystemProperty", 388 "(Ljava/lang/String;Ljava/lang/String;)V"); 389 if (set_prop_id != nullptr) { 390 // Init os.arch to the value reqired by the apps running with native bridge. 391 env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"), 392 env->NewStringUTF(env_values->os_arch)); 393 } else { 394 env->ExceptionClear(); 395 ALOGW("Could not find System#setUnchangeableSystemProperty."); 396 } 397 } else { 398 env->ExceptionClear(); 399 ALOGW("Could not find System class."); 400 } 401 } 402 403 // Make it pristine again. 404 env->PopLocalFrame(nullptr); 405 } 406 407 bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) { 408 // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that 409 // point we are not multi-threaded, so we do not need locking here. 410 411 if (state == NativeBridgeState::kPreInitialized) { 412 // Check for code cache: if it doesn't exist try to create it. 413 struct stat st; 414 if (stat(app_code_cache_dir, &st) == -1) { 415 if (errno == ENOENT) { 416 if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) { 417 ALOGW("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno)); 418 ReleaseAppCodeCacheDir(); 419 } 420 } else { 421 ALOGW("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno)); 422 ReleaseAppCodeCacheDir(); 423 } 424 } else if (!S_ISDIR(st.st_mode)) { 425 ALOGW("Code cache is not a directory %s.", app_code_cache_dir); 426 ReleaseAppCodeCacheDir(); 427 } 428 429 // If we're still PreInitialized (dind't fail the code cache checks) try to initialize. 430 if (state == NativeBridgeState::kPreInitialized) { 431 if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) { 432 SetupEnvironment(callbacks, env, instruction_set); 433 state = NativeBridgeState::kInitialized; 434 // We no longer need the code cache path, release the memory. 435 ReleaseAppCodeCacheDir(); 436 } else { 437 // Unload the library. 438 dlclose(native_bridge_handle); 439 CloseNativeBridge(true); 440 } 441 } 442 } else { 443 CloseNativeBridge(true); 444 } 445 446 return state == NativeBridgeState::kInitialized; 447 } 448 449 void UnloadNativeBridge() { 450 // We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that 451 // point we are not multi-threaded, so we do not need locking here. 452 453 switch(state) { 454 case NativeBridgeState::kOpened: 455 case NativeBridgeState::kPreInitialized: 456 case NativeBridgeState::kInitialized: 457 // Unload. 458 dlclose(native_bridge_handle); 459 CloseNativeBridge(false); 460 break; 461 462 case NativeBridgeState::kNotSetup: 463 // Not even set up. Error. 464 CloseNativeBridge(true); 465 break; 466 467 case NativeBridgeState::kClosed: 468 // Ignore. 469 break; 470 } 471 } 472 473 bool NativeBridgeError() { 474 return had_error; 475 } 476 477 bool NativeBridgeAvailable() { 478 return state == NativeBridgeState::kOpened 479 || state == NativeBridgeState::kPreInitialized 480 || state == NativeBridgeState::kInitialized; 481 } 482 483 bool NativeBridgeInitialized() { 484 // Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after 485 // Runtime::DidForkFromZygote. In that case we do not need a lock. 486 return state == NativeBridgeState::kInitialized; 487 } 488 489 void* NativeBridgeLoadLibrary(const char* libpath, int flag) { 490 if (NativeBridgeInitialized()) { 491 return callbacks->loadLibrary(libpath, flag); 492 } 493 return nullptr; 494 } 495 496 void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, 497 uint32_t len) { 498 if (NativeBridgeInitialized()) { 499 return callbacks->getTrampoline(handle, name, shorty, len); 500 } 501 return nullptr; 502 } 503 504 bool NativeBridgeIsSupported(const char* libpath) { 505 if (NativeBridgeInitialized()) { 506 return callbacks->isSupported(libpath); 507 } 508 return false; 509 } 510 511 uint32_t NativeBridgeGetVersion() { 512 if (NativeBridgeAvailable()) { 513 return callbacks->version; 514 } 515 return 0; 516 } 517 518 NativeBridgeSignalHandlerFn NativeBridgeGetSignalHandler(int signal) { 519 if (NativeBridgeInitialized()) { 520 if (isCompatibleWith(SIGNAL_VERSION)) { 521 return callbacks->getSignalHandler(signal); 522 } else { 523 ALOGE("not compatible with version %d, cannot get signal handler", SIGNAL_VERSION); 524 } 525 } 526 return nullptr; 527 } 528 529 int NativeBridgeUnloadLibrary(void* handle) { 530 if (NativeBridgeInitialized()) { 531 if (isCompatibleWith(NAMESPACE_VERSION)) { 532 return callbacks->unloadLibrary(handle); 533 } else { 534 ALOGE("not compatible with version %d, cannot unload library", NAMESPACE_VERSION); 535 } 536 } 537 return -1; 538 } 539 540 const char* NativeBridgeGetError() { 541 if (NativeBridgeInitialized()) { 542 if (isCompatibleWith(NAMESPACE_VERSION)) { 543 return callbacks->getError(); 544 } else { 545 return "native bridge implementation is not compatible with version 3, cannot get message"; 546 } 547 } 548 return "native bridge is not initialized"; 549 } 550 551 bool NativeBridgeIsPathSupported(const char* path) { 552 if (NativeBridgeInitialized()) { 553 if (isCompatibleWith(NAMESPACE_VERSION)) { 554 return callbacks->isPathSupported(path); 555 } else { 556 ALOGE("not compatible with version %d, cannot check via library path", NAMESPACE_VERSION); 557 } 558 } 559 return false; 560 } 561 562 bool NativeBridgeInitAnonymousNamespace(const char* public_ns_sonames, 563 const char* anon_ns_library_path) { 564 if (NativeBridgeInitialized()) { 565 if (isCompatibleWith(NAMESPACE_VERSION)) { 566 return callbacks->initAnonymousNamespace(public_ns_sonames, anon_ns_library_path); 567 } else { 568 ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); 569 } 570 } 571 572 return false; 573 } 574 575 native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name, 576 const char* ld_library_path, 577 const char* default_library_path, 578 uint64_t type, 579 const char* permitted_when_isolated_path, 580 native_bridge_namespace_t* parent_ns) { 581 if (NativeBridgeInitialized()) { 582 if (isCompatibleWith(NAMESPACE_VERSION)) { 583 return callbacks->createNamespace(name, 584 ld_library_path, 585 default_library_path, 586 type, 587 permitted_when_isolated_path, 588 parent_ns); 589 } else { 590 ALOGE("not compatible with version %d, cannot create namespace %s", NAMESPACE_VERSION, name); 591 } 592 } 593 594 return nullptr; 595 } 596 597 bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to, 598 const char* shared_libs_sonames) { 599 if (NativeBridgeInitialized()) { 600 if (isCompatibleWith(NAMESPACE_VERSION)) { 601 return callbacks->linkNamespaces(from, to, shared_libs_sonames); 602 } else { 603 ALOGE("not compatible with version %d, cannot init namespace", NAMESPACE_VERSION); 604 } 605 } 606 607 return false; 608 } 609 610 native_bridge_namespace_t* NativeBridgeGetVendorNamespace() { 611 if (!NativeBridgeInitialized() || !isCompatibleWith(VENDOR_NAMESPACE_VERSION)) { 612 return nullptr; 613 } 614 615 return callbacks->getVendorNamespace(); 616 } 617 618 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) { 619 if (NativeBridgeInitialized()) { 620 if (isCompatibleWith(NAMESPACE_VERSION)) { 621 return callbacks->loadLibraryExt(libpath, flag, ns); 622 } else { 623 ALOGE("not compatible with version %d, cannot load library in namespace", NAMESPACE_VERSION); 624 } 625 } 626 return nullptr; 627 } 628 629 }; // namespace android 630