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 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 kNativeBridgeCallbackVersion = 1; 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 // We only allow simple names for the library. It is supposed to be a file in 113 // /system/lib or /vendor/lib. Only allow a small range of characters, that is 114 // names consisting of [a-zA-Z0-9._-] and starting with [a-zA-Z]. 115 bool NativeBridgeNameAcceptable(const char* nb_library_filename) { 116 const char* ptr = nb_library_filename; 117 if (*ptr == 0) { 118 // Emptry string. Allowed, means no native bridge. 119 return true; 120 } else { 121 // First character must be [a-zA-Z]. 122 if (!CharacterAllowed(*ptr, true)) { 123 // Found an invalid fist character, don't accept. 124 ALOGE("Native bridge library %s has been rejected for first character %c", nb_library_filename, *ptr); 125 return false; 126 } else { 127 // For the rest, be more liberal. 128 ptr++; 129 while (*ptr != 0) { 130 if (!CharacterAllowed(*ptr, false)) { 131 // Found an invalid character, don't accept. 132 ALOGE("Native bridge library %s has been rejected for %c", nb_library_filename, *ptr); 133 return false; 134 } 135 ptr++; 136 } 137 } 138 return true; 139 } 140 } 141 142 static bool VersionCheck(NativeBridgeCallbacks* cb) { 143 return cb != nullptr && cb->version == kNativeBridgeCallbackVersion; 144 } 145 146 static void CloseNativeBridge(bool with_error) { 147 state = NativeBridgeState::kClosed; 148 had_error |= with_error; 149 delete[] app_code_cache_dir; 150 app_code_cache_dir = nullptr; 151 } 152 153 bool LoadNativeBridge(const char* nb_library_filename, 154 const NativeBridgeRuntimeCallbacks* runtime_cbs) { 155 // We expect only one place that calls LoadNativeBridge: Runtime::Init. At that point we are not 156 // multi-threaded, so we do not need locking here. 157 158 if (state != NativeBridgeState::kNotSetup) { 159 // Setup has been called before. Ignore this call. 160 if (nb_library_filename != nullptr) { // Avoids some log-spam for dalvikvm. 161 ALOGW("Called LoadNativeBridge for an already set up native bridge. State is %s.", 162 GetNativeBridgeStateString(state)); 163 } 164 // Note: counts as an error, even though the bridge may be functional. 165 had_error = true; 166 return false; 167 } 168 169 if (nb_library_filename == nullptr || *nb_library_filename == 0) { 170 CloseNativeBridge(false); 171 return false; 172 } else { 173 if (!NativeBridgeNameAcceptable(nb_library_filename)) { 174 CloseNativeBridge(true); 175 } else { 176 // Try to open the library. 177 void* handle = dlopen(nb_library_filename, RTLD_LAZY); 178 if (handle != nullptr) { 179 callbacks = reinterpret_cast<NativeBridgeCallbacks*>(dlsym(handle, 180 kNativeBridgeInterfaceSymbol)); 181 if (callbacks != nullptr) { 182 if (VersionCheck(callbacks)) { 183 // Store the handle for later. 184 native_bridge_handle = handle; 185 } else { 186 callbacks = nullptr; 187 dlclose(handle); 188 ALOGW("Unsupported native bridge interface."); 189 } 190 } else { 191 dlclose(handle); 192 } 193 } 194 195 // Two failure conditions: could not find library (dlopen failed), or could not find native 196 // bridge interface (dlsym failed). Both are an error and close the native bridge. 197 if (callbacks == nullptr) { 198 CloseNativeBridge(true); 199 } else { 200 runtime_callbacks = runtime_cbs; 201 state = NativeBridgeState::kOpened; 202 } 203 } 204 return state == NativeBridgeState::kOpened; 205 } 206 } 207 208 #if defined(__arm__) 209 static const char* kRuntimeISA = "arm"; 210 #elif defined(__aarch64__) 211 static const char* kRuntimeISA = "arm64"; 212 #elif defined(__mips__) 213 static const char* kRuntimeISA = "mips"; 214 #elif defined(__i386__) 215 static const char* kRuntimeISA = "x86"; 216 #elif defined(__x86_64__) 217 static const char* kRuntimeISA = "x86_64"; 218 #else 219 static const char* kRuntimeISA = "unknown"; 220 #endif 221 222 223 bool NeedsNativeBridge(const char* instruction_set) { 224 if (instruction_set == nullptr) { 225 ALOGE("Null instruction set in NeedsNativeBridge."); 226 return false; 227 } 228 return strncmp(instruction_set, kRuntimeISA, strlen(kRuntimeISA) + 1) != 0; 229 } 230 231 #ifdef __APPLE__ 232 template<typename T> void UNUSED(const T&) {} 233 #endif 234 235 bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) { 236 if (state != NativeBridgeState::kOpened) { 237 ALOGE("Invalid state: native bridge is expected to be opened."); 238 CloseNativeBridge(true); 239 return false; 240 } 241 242 if (app_data_dir_in == nullptr) { 243 ALOGE("Application private directory cannot be null."); 244 CloseNativeBridge(true); 245 return false; 246 } 247 248 // Create the path to the application code cache directory. 249 // The memory will be release after Initialization or when the native bridge is closed. 250 const size_t len = strlen(app_data_dir_in) + strlen(kCodeCacheDir) + 2; // '\0' + '/' 251 app_code_cache_dir = new char[len]; 252 snprintf(app_code_cache_dir, len, "%s/%s", app_data_dir_in, kCodeCacheDir); 253 254 // Bind-mount /system/lib{,64}/<isa>/cpuinfo to /proc/cpuinfo. 255 // Failure is not fatal and will keep the native bridge in kPreInitialized. 256 state = NativeBridgeState::kPreInitialized; 257 258 #ifndef __APPLE__ 259 if (instruction_set == nullptr) { 260 return true; 261 } 262 size_t isa_len = strlen(instruction_set); 263 if (isa_len > 10) { 264 // 10 is a loose upper bound on the currently known instruction sets (a tight bound is 7 for 265 // x86_64 [including the trailing \0]). This is so we don't have to change here if there will 266 // be another instruction set in the future. 267 ALOGW("Instruction set %s is malformed, must be less than or equal to 10 characters.", 268 instruction_set); 269 return true; 270 } 271 272 // If the file does not exist, the mount command will fail, 273 // so we save the extra file existence check. 274 char cpuinfo_path[1024]; 275 276 #ifdef HAVE_ANDROID_OS 277 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "/system/lib" 278 #ifdef __LP64__ 279 "64" 280 #endif // __LP64__ 281 "/%s/cpuinfo", instruction_set); 282 #else // !HAVE_ANDROID_OS 283 // To be able to test on the host, we hardwire a relative path. 284 snprintf(cpuinfo_path, sizeof(cpuinfo_path), "./cpuinfo"); 285 #endif 286 287 // Bind-mount. 288 if (TEMP_FAILURE_RETRY(mount(cpuinfo_path, // Source. 289 "/proc/cpuinfo", // Target. 290 nullptr, // FS type. 291 MS_BIND, // Mount flags: bind mount. 292 nullptr)) == -1) { // "Data." 293 ALOGW("Failed to bind-mount %s as /proc/cpuinfo: %s", cpuinfo_path, strerror(errno)); 294 } 295 #else // __APPLE__ 296 UNUSED(instruction_set); 297 ALOGW("Mac OS does not support bind-mounting. Host simulation of native bridge impossible."); 298 #endif 299 300 return true; 301 } 302 303 static void SetCpuAbi(JNIEnv* env, jclass build_class, const char* field, const char* value) { 304 if (value != nullptr) { 305 jfieldID field_id = env->GetStaticFieldID(build_class, field, "Ljava/lang/String;"); 306 if (field_id == nullptr) { 307 env->ExceptionClear(); 308 ALOGW("Could not find %s field.", field); 309 return; 310 } 311 312 jstring str = env->NewStringUTF(value); 313 if (str == nullptr) { 314 env->ExceptionClear(); 315 ALOGW("Could not create string %s.", value); 316 return; 317 } 318 319 env->SetStaticObjectField(build_class, field_id, str); 320 } 321 } 322 323 // Set up the environment for the bridged app. 324 static void SetupEnvironment(NativeBridgeCallbacks* callbacks, JNIEnv* env, const char* isa) { 325 // Need a JNIEnv* to do anything. 326 if (env == nullptr) { 327 ALOGW("No JNIEnv* to set up app environment."); 328 return; 329 } 330 331 // Query the bridge for environment values. 332 const struct NativeBridgeRuntimeValues* env_values = callbacks->getAppEnv(isa); 333 if (env_values == nullptr) { 334 return; 335 } 336 337 // Keep the JNIEnv clean. 338 jint success = env->PushLocalFrame(16); // That should be small and large enough. 339 if (success < 0) { 340 // Out of memory, really borked. 341 ALOGW("Out of memory while setting up app environment."); 342 env->ExceptionClear(); 343 return; 344 } 345 346 // Reset CPU_ABI & CPU_ABI2 to values required by the apps running with native bridge. 347 if (env_values->cpu_abi != nullptr || env_values->cpu_abi2 != nullptr || 348 env_values->abi_count >= 0) { 349 jclass bclass_id = env->FindClass("android/os/Build"); 350 if (bclass_id != nullptr) { 351 SetCpuAbi(env, bclass_id, "CPU_ABI", env_values->cpu_abi); 352 SetCpuAbi(env, bclass_id, "CPU_ABI2", env_values->cpu_abi2); 353 } else { 354 // For example in a host test environment. 355 env->ExceptionClear(); 356 ALOGW("Could not find Build class."); 357 } 358 } 359 360 if (env_values->os_arch != nullptr) { 361 jclass sclass_id = env->FindClass("java/lang/System"); 362 if (sclass_id != nullptr) { 363 jmethodID set_prop_id = env->GetStaticMethodID(sclass_id, "initUnchangeableSystemProperty", 364 "(Ljava/lang/String;Ljava/lang/String;)V"); 365 if (set_prop_id != nullptr) { 366 // Init os.arch to the value reqired by the apps running with native bridge. 367 env->CallStaticVoidMethod(sclass_id, set_prop_id, env->NewStringUTF("os.arch"), 368 env->NewStringUTF(env_values->os_arch)); 369 } else { 370 env->ExceptionClear(); 371 ALOGW("Could not find initUnchangeableSystemProperty method."); 372 } 373 } else { 374 env->ExceptionClear(); 375 ALOGW("Could not find System class."); 376 } 377 } 378 379 // Make it pristine again. 380 env->PopLocalFrame(nullptr); 381 } 382 383 bool InitializeNativeBridge(JNIEnv* env, const char* instruction_set) { 384 // We expect only one place that calls InitializeNativeBridge: Runtime::DidForkFromZygote. At that 385 // point we are not multi-threaded, so we do not need locking here. 386 387 if (state == NativeBridgeState::kPreInitialized) { 388 // Check for code cache: if it doesn't exist try to create it. 389 struct stat st; 390 if (stat(app_code_cache_dir, &st) == -1) { 391 if (errno == ENOENT) { 392 if (mkdir(app_code_cache_dir, S_IRWXU | S_IRWXG | S_IXOTH) == -1) { 393 ALOGE("Cannot create code cache directory %s: %s.", app_code_cache_dir, strerror(errno)); 394 CloseNativeBridge(true); 395 } 396 } else { 397 ALOGE("Cannot stat code cache directory %s: %s.", app_code_cache_dir, strerror(errno)); 398 CloseNativeBridge(true); 399 } 400 } else if (!S_ISDIR(st.st_mode)) { 401 ALOGE("Code cache is not a directory %s.", app_code_cache_dir); 402 CloseNativeBridge(true); 403 } 404 405 // If we're still PreInitialized (dind't fail the code cache checks) try to initialize. 406 if (state == NativeBridgeState::kPreInitialized) { 407 if (callbacks->initialize(runtime_callbacks, app_code_cache_dir, instruction_set)) { 408 SetupEnvironment(callbacks, env, instruction_set); 409 state = NativeBridgeState::kInitialized; 410 // We no longer need the code cache path, release the memory. 411 delete[] app_code_cache_dir; 412 app_code_cache_dir = nullptr; 413 } else { 414 // Unload the library. 415 dlclose(native_bridge_handle); 416 CloseNativeBridge(true); 417 } 418 } 419 } else { 420 CloseNativeBridge(true); 421 } 422 423 return state == NativeBridgeState::kInitialized; 424 } 425 426 void UnloadNativeBridge() { 427 // We expect only one place that calls UnloadNativeBridge: Runtime::DidForkFromZygote. At that 428 // point we are not multi-threaded, so we do not need locking here. 429 430 switch(state) { 431 case NativeBridgeState::kOpened: 432 case NativeBridgeState::kPreInitialized: 433 case NativeBridgeState::kInitialized: 434 // Unload. 435 dlclose(native_bridge_handle); 436 CloseNativeBridge(false); 437 break; 438 439 case NativeBridgeState::kNotSetup: 440 // Not even set up. Error. 441 CloseNativeBridge(true); 442 break; 443 444 case NativeBridgeState::kClosed: 445 // Ignore. 446 break; 447 } 448 } 449 450 bool NativeBridgeError() { 451 return had_error; 452 } 453 454 bool NativeBridgeAvailable() { 455 return state == NativeBridgeState::kOpened 456 || state == NativeBridgeState::kPreInitialized 457 || state == NativeBridgeState::kInitialized; 458 } 459 460 bool NativeBridgeInitialized() { 461 // Calls of this are supposed to happen in a state where the native bridge is stable, i.e., after 462 // Runtime::DidForkFromZygote. In that case we do not need a lock. 463 return state == NativeBridgeState::kInitialized; 464 } 465 466 void* NativeBridgeLoadLibrary(const char* libpath, int flag) { 467 if (NativeBridgeInitialized()) { 468 return callbacks->loadLibrary(libpath, flag); 469 } 470 return nullptr; 471 } 472 473 void* NativeBridgeGetTrampoline(void* handle, const char* name, const char* shorty, 474 uint32_t len) { 475 if (NativeBridgeInitialized()) { 476 return callbacks->getTrampoline(handle, name, shorty, len); 477 } 478 return nullptr; 479 } 480 481 bool NativeBridgeIsSupported(const char* libpath) { 482 if (NativeBridgeInitialized()) { 483 return callbacks->isSupported(libpath); 484 } 485 return false; 486 } 487 488 }; // namespace android 489