Loading core/jni/com_android_internal_os_Zygote.cpp +219 −196 Original line number Diff line number Diff line Loading @@ -535,20 +535,14 @@ static bool FillFileDescriptorVector(JNIEnv* env, return true; } // Utility routine to fork zygote and specialize the child process. static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, // Utility routine to specialize a zygote child process. static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint runtime_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jintArray fdsToIgnore, bool is_child_zygote, jstring instructionSet, jstring dataDir) { SetSignalHandlers(); sigset_t sigchld; sigemptyset(&sigchld); sigaddset(&sigchld, SIGCHLD); jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, bool is_child_zygote, jstring instructionSet, jstring dataDir) { std::string error_msg; auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg) __attribute__ ((noreturn)) { Loading @@ -568,57 +562,6 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra __builtin_unreachable(); }; // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); std::string error_msg; // If this is the first fork for this zygote, create the open FD table. // If it isn't, we just need to check whether the list of open files has // changed (and it shouldn't in the normal case). std::vector<int> fds_to_ignore; if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) { fail_fn(error_msg); } if (gOpenFdTable == NULL) { gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); if (gOpenFdTable == NULL) { fail_fn(error_msg); } } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { fail_fn(error_msg); } pid_t pid = fork(); if (pid == 0) { PreApplicationInit(); // Clean up any descriptors which must be closed immediately if (!DetachDescriptors(env, fdsToClose, &error_msg)) { fail_fn(error_msg); } // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { fail_fn(error_msg); } if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { if (!EnableKeepCapabilities(&error_msg)) { Loading Loading @@ -667,12 +610,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra if (rc == -EROFS) { ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); } else { ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc)); ALOGE("createProcessGroup(%d, %d) failed: %s", uid, 0/*pid*/, strerror(-rc)); } } } std::string error_msg; if (!SetGids(env, javaGids, &error_msg)) { fail_fn(error_msg); } Loading Loading @@ -786,14 +728,90 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra if (env->ExceptionCheck()) { fail_fn("Error calling post fork hooks."); } } else if (pid > 0) { // the parent process } // Utility routine to fork zygote and specialize the child process. static pid_t ForkCommon(JNIEnv* env, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jintArray fdsToIgnore) { SetSignalHandlers(); // Block SIGCHLD prior to fork. sigset_t sigchld; sigemptyset(&sigchld); sigaddset(&sigchld, SIGCHLD); auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg) __attribute__ ((noreturn)) { const char* se_name_c_str = nullptr; std::unique_ptr<ScopedUtfChars> se_name; if (java_se_name != nullptr) { se_name.reset(new ScopedUtfChars(env, java_se_name)); se_name_c_str = se_name->c_str(); } if (se_name_c_str == nullptr && is_system_server) { se_name_c_str = "system_server"; } const std::string& error_msg = (se_name_c_str == nullptr) ? msg : StringPrintf("(%s) %s", se_name_c_str, msg.c_str()); env->FatalError(error_msg.c_str()); __builtin_unreachable(); }; // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); std::string error_msg; // If this is the first fork for this zygote, create the open FD table. // If it isn't, we just need to check whether the list of open files has // changed (and it shouldn't in the normal case). std::vector<int> fds_to_ignore; if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) { fail_fn(error_msg); } if (gOpenFdTable == NULL) { gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); if (gOpenFdTable == NULL) { fail_fn(error_msg); } } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { fail_fn(error_msg); } pid_t pid = fork(); if (pid == 0) { // The child process. PreApplicationInit(); // Clean up any descriptors which must be closed immediately if (!DetachDescriptors(env, fdsToClose, &error_msg)) { fail_fn(error_msg); } // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { fail_fn(error_msg); } } // We blocked SIGCHLD prior to a fork, we unblock it here. if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } } return pid; } Loading Loading @@ -879,22 +897,27 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( // available. capabilities &= GetEffectiveCapabilityMask(env); return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE, instructionSet, appDataDir); pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, is_child_zygote == JNI_TRUE, instructionSet, appDataDir); } return pid; } 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 permittedCapabilities, jlong effectiveCapabilities) { pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, pid_t pid = ForkCommon(env, NULL, true, NULL, NULL); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permittedCapabilities, effectiveCapabilities, MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL, NULL, false, NULL, NULL); if (pid > 0) { MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, false, NULL, NULL); } 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; Loading Loading
core/jni/com_android_internal_os_Zygote.cpp +219 −196 Original line number Diff line number Diff line Loading @@ -535,20 +535,14 @@ static bool FillFileDescriptorVector(JNIEnv* env, return true; } // Utility routine to fork zygote and specialize the child process. static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, // Utility routine to specialize a zygote child process. static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint runtime_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jintArray fdsToIgnore, bool is_child_zygote, jstring instructionSet, jstring dataDir) { SetSignalHandlers(); sigset_t sigchld; sigemptyset(&sigchld); sigaddset(&sigchld, SIGCHLD); jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, bool is_child_zygote, jstring instructionSet, jstring dataDir) { std::string error_msg; auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg) __attribute__ ((noreturn)) { Loading @@ -568,57 +562,6 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra __builtin_unreachable(); }; // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); std::string error_msg; // If this is the first fork for this zygote, create the open FD table. // If it isn't, we just need to check whether the list of open files has // changed (and it shouldn't in the normal case). std::vector<int> fds_to_ignore; if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) { fail_fn(error_msg); } if (gOpenFdTable == NULL) { gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); if (gOpenFdTable == NULL) { fail_fn(error_msg); } } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { fail_fn(error_msg); } pid_t pid = fork(); if (pid == 0) { PreApplicationInit(); // Clean up any descriptors which must be closed immediately if (!DetachDescriptors(env, fdsToClose, &error_msg)) { fail_fn(error_msg); } // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { fail_fn(error_msg); } if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { if (!EnableKeepCapabilities(&error_msg)) { Loading Loading @@ -667,12 +610,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra if (rc == -EROFS) { ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); } else { ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc)); ALOGE("createProcessGroup(%d, %d) failed: %s", uid, 0/*pid*/, strerror(-rc)); } } } std::string error_msg; if (!SetGids(env, javaGids, &error_msg)) { fail_fn(error_msg); } Loading Loading @@ -786,14 +728,90 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra if (env->ExceptionCheck()) { fail_fn("Error calling post fork hooks."); } } else if (pid > 0) { // the parent process } // Utility routine to fork zygote and specialize the child process. static pid_t ForkCommon(JNIEnv* env, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jintArray fdsToIgnore) { SetSignalHandlers(); // Block SIGCHLD prior to fork. sigset_t sigchld; sigemptyset(&sigchld); sigaddset(&sigchld, SIGCHLD); auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg) __attribute__ ((noreturn)) { const char* se_name_c_str = nullptr; std::unique_ptr<ScopedUtfChars> se_name; if (java_se_name != nullptr) { se_name.reset(new ScopedUtfChars(env, java_se_name)); se_name_c_str = se_name->c_str(); } if (se_name_c_str == nullptr && is_system_server) { se_name_c_str = "system_server"; } const std::string& error_msg = (se_name_c_str == nullptr) ? msg : StringPrintf("(%s) %s", se_name_c_str, msg.c_str()); env->FatalError(error_msg.c_str()); __builtin_unreachable(); }; // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); std::string error_msg; // If this is the first fork for this zygote, create the open FD table. // If it isn't, we just need to check whether the list of open files has // changed (and it shouldn't in the normal case). std::vector<int> fds_to_ignore; if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) { fail_fn(error_msg); } if (gOpenFdTable == NULL) { gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); if (gOpenFdTable == NULL) { fail_fn(error_msg); } } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { fail_fn(error_msg); } pid_t pid = fork(); if (pid == 0) { // The child process. PreApplicationInit(); // Clean up any descriptors which must be closed immediately if (!DetachDescriptors(env, fdsToClose, &error_msg)) { fail_fn(error_msg); } // Re-open all remaining open file descriptors so that they aren't shared // with the zygote across a fork. if (!gOpenFdTable->ReopenOrDetach(&error_msg)) { fail_fn(error_msg); } } // We blocked SIGCHLD prior to a fork, we unblock it here. if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno))); } } return pid; } Loading Loading @@ -879,22 +897,27 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( // available. capabilities &= GetEffectiveCapabilityMask(env); return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE, instructionSet, appDataDir); pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, is_child_zygote == JNI_TRUE, instructionSet, appDataDir); } return pid; } 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 permittedCapabilities, jlong effectiveCapabilities) { pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, pid_t pid = ForkCommon(env, NULL, true, NULL, NULL); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permittedCapabilities, effectiveCapabilities, MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL, NULL, false, NULL, NULL); if (pid > 0) { MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, false, NULL, NULL); } 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; Loading