static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork( JNIEnv* env, jclass, jstring path) { ScopedUtfChars path_native(env, path); const char* path_cstr = path_native.c_str(); if (!path_cstr) { RuntimeAbort(env, __LINE__, "path_cstr == nullptr"); } FileDescriptorWhitelist::Get()->Allow(path_cstr); }
int register_com_android_internal_os_Zygote(JNIEnv* env) { gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName)); if (gZygoteClass == NULL) { RuntimeAbort(env); } gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V"); return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote", gMethods, NELEM(gMethods)); }
static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) { // Zygote process unmount root storage space initially before every child processes are forked. // Every forked child processes (include SystemServer) only mount their own root storage space // and no need unmount storage operation in MountEmulatedStorage method. // Zygote process does not utilize root storage spaces and unshares its mount namespace below. // See storage config details at http://source.android.com/tech/storage/ // Create private mount namespace shared by all children if (unshare(CLONE_NEWNS) == -1) { RuntimeAbort(env, __LINE__, "Failed to unshare()"); return; } // Mark rootfs as being a slave so that changes from default // namespace only flow into our children. if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) { RuntimeAbort(env, __LINE__, "Failed to mount() rootfs as MS_SLAVE"); return; } // Create a staging tmpfs that is shared by our children; they will // bind mount storage into their respective private namespaces, which // are isolated from each other. const char* target_base = getenv("EMULATED_STORAGE_TARGET"); if (target_base != nullptr) { #define STRINGIFY_UID(x) __STRING(x) if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV, "uid=0,gid=" STRINGIFY_UID(AID_SDCARD_R) ",mode=0751") == -1) { ALOGE("Failed to mount tmpfs to %s", target_base); RuntimeAbort(env, __LINE__, "Failed to mount tmpfs"); return; } #undef STRINGIFY_UID } UnmountTree("/storage"); }
static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) { pid_t pid = ForkCommon(env, true, /* managed_fds_to_close= */ nullptr, /* managed_fds_to_ignore= */ nullptr); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr); } else if (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); gSystemServerPid = pid; // There is a slight window that the system server process has crashed // but it went unnoticed because we haven't published its pid yet. So // we recheck here just to make sure that all is well. int status; if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid); RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!"); } bool low_ram_device = GetBoolProperty("ro.config.low_ram", false); bool per_app_memcg = GetBoolProperty("ro.config.per_app_memcg", low_ram_device); if (per_app_memcg) { // Assign system_server to the correct memory cgroup. // Not all devices mount /dev/memcg so check for the file first // to avoid unnecessarily printing errors and denials in the logs. if (!access("/dev/memcg/system/tasks", F_OK) && !WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) { ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid); } } } return pid; }
static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities, jlong effectiveCapabilities) { pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, permittedCapabilities, effectiveCapabilities, MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL); if (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); gSystemServerPid = pid; // There is a slight window that the system server process has crashed // but it went unnoticed because we haven't published its pid yet. So // we recheck here just to make sure that all is well. int status; if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid); RuntimeAbort(env); } } return pid; }
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint debug_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring se_name, jintArray fdsToClose, jstring instructionSet, jstring appDataDir) { jlong capabilities = 0; // Grant CAP_WAKE_ALARM to the Bluetooth process. if (uid == AID_BLUETOOTH) { capabilities |= (1LL << CAP_WAKE_ALARM); } // Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" bool gid_wakelock_found = false; if (gid == AID_WAKELOCK) { gid_wakelock_found = true; } else if (gids != NULL) { jsize gids_num = env->GetArrayLength(gids); ScopedIntArrayRO ar(env, gids); if (ar.get() == NULL) { RuntimeAbort(env, __LINE__, "Bad gids array"); } for (int i = 0; i < gids_num; i++) { if (ar[i] == AID_WAKELOCK) { gid_wakelock_found = true; break; } } } if (gid_wakelock_found) { capabilities |= (1LL << CAP_BLOCK_SUSPEND); } return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, instructionSet, appDataDir); }