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