diff options
| -rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 489 |
1 files changed, 257 insertions, 232 deletions
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 6f400c42bcbe..b96b8ecfb5e7 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -20,7 +20,9 @@ #include <sys/mount.h> #include <linux/fs.h> +#include <functional> #include <list> +#include <optional> #include <sstream> #include <string> @@ -70,6 +72,8 @@ namespace { +using namespace std::placeholders; + using android::String8; using android::base::StringPrintf; using android::base::WriteStringToFile; @@ -522,12 +526,12 @@ void SetThreadName(const char* thread_name) { static FileDescriptorTable* gOpenFdTable = NULL; static bool FillFileDescriptorVector(JNIEnv* env, - jintArray java_fds, + jintArray managed_fds, std::vector<int>* fds, std::string* error_msg) { CHECK(fds != nullptr); - if (java_fds != nullptr) { - ScopedIntArrayRO ar(env, java_fds); + if (managed_fds != nullptr) { + ScopedIntArrayRO ar(env, managed_fds); if (ar.get() == nullptr) { *error_msg = "Bad fd array"; return false; @@ -540,32 +544,138 @@ static bool FillFileDescriptorVector(JNIEnv* env, return true; } -// 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, bool is_child_zygote, jstring instructionSet, - jstring dataDir) { +[[noreturn]] +static void ZygoteFailure(JNIEnv* env, + const char* process_name, + jstring managed_process_name, + const std::string& msg) { + std::unique_ptr<ScopedUtfChars> scoped_managed_process_name_ptr = nullptr; + if (managed_process_name != nullptr) { + scoped_managed_process_name_ptr.reset(new ScopedUtfChars(env, managed_process_name)); + if (scoped_managed_process_name_ptr->c_str() != nullptr) { + process_name = scoped_managed_process_name_ptr->c_str(); + } + } + + const std::string& error_msg = + (process_name == nullptr) ? msg : StringPrintf("(%s) %s", process_name, msg.c_str()); + + env->FatalError(error_msg.c_str()); + __builtin_unreachable(); +} + +static std::optional<std::string> ExtractJString(JNIEnv* env, + const char* process_name, + jstring managed_process_name, + jstring managed_string) { + if (managed_string == nullptr) { + return std::optional<std::string>(); + } else { + ScopedUtfChars scoped_string_chars(env, managed_string); + + if (scoped_string_chars.c_str() != nullptr) { + return std::optional<std::string>(scoped_string_chars.c_str()); + } else { + ZygoteFailure(env, process_name, managed_process_name, "Failed to extract JString."); + } + } +} + +// Utility routine to fork a zygote. +static pid_t ForkCommon(JNIEnv* env, bool is_system_server, + jintArray managed_fds_to_close, jintArray managed_fds_to_ignore) { + SetSignalHandlers(); + + // Block SIGCHLD prior to fork. + sigset_t sigchld; + sigemptyset(&sigchld); + sigaddset(&sigchld, SIGCHLD); + + // Curry a failure function. + auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote", + nullptr, _1); + + // 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(); + stats_log_close(); + + // 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::string error_msg; + std::vector<int> fds_to_ignore; + if (!FillFileDescriptorVector(env, managed_fds_to_ignore, &fds_to_ignore, &error_msg)) { + fail_fn(error_msg); + } - 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 (gOpenFdTable == nullptr) { + gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg); + if (gOpenFdTable == nullptr) { + fail_fn(error_msg); } - if (se_name_c_str == nullptr && is_system_server) { - se_name_c_str = "system_server"; + } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) { + fail_fn(error_msg); + } + + android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level(); + + pid_t pid = fork(); + + if (pid == 0) { + // The child process. + PreApplicationInit(); + + // Clean up any descriptors which must be closed immediately + if (!DetachDescriptors(env, managed_fds_to_close, &error_msg)) { + fail_fn(error_msg); } - 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(); - }; + + // 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); + } + + // Turn fdsan back on. + android_fdsan_set_error_level(fdsan_error_level); + } + + // 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; +} + +// Utility routine to specialize a zygote child process. +static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, + jint runtime_flags, jobjectArray rlimits, + jlong permitted_capabilities, jlong effective_capabilities, + jint mount_external, jstring managed_se_info, + jstring managed_nice_name, bool is_system_server, + bool is_child_zygote, jstring managed_instruction_set, + jstring managed_app_data_dir) { + auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote", + managed_nice_name, _1); + auto extract_fn = std::bind(ExtractJString, env, is_system_server ? "system_server" : "zygote", + managed_nice_name, _1); + + auto se_info = extract_fn(managed_se_info); + auto nice_name = extract_fn(managed_nice_name); + auto instruction_set = extract_fn(managed_instruction_set); + auto app_data_dir = extract_fn(managed_app_data_dir); + + std::string error_msg; // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { @@ -574,26 +684,27 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi } } - if (!SetInheritable(permittedCapabilities, &error_msg)) { + if (!SetInheritable(permitted_capabilities, &error_msg)) { fail_fn(error_msg); } + if (!DropCapabilitiesBoundingSet(&error_msg)) { fail_fn(error_msg); } - bool use_native_bridge = !is_system_server && (instructionSet != NULL) - && android::NativeBridgeAvailable(); - if (use_native_bridge) { - ScopedUtfChars isa_string(env, instructionSet); - use_native_bridge = android::NeedsNativeBridge(isa_string.c_str()); - } - if (use_native_bridge && dataDir == NULL) { - // dataDir should never be null if we need to use a native bridge. - // In general, dataDir will never be null for normal applications. It can only happen in - // special cases (for isolated processes which are not associated with any app). These are - // launched by the framework and should not be emulated anyway. + bool use_native_bridge = !is_system_server && + instruction_set.has_value() && + android::NativeBridgeAvailable() && + android::NeedsNativeBridge(instruction_set.value().c_str()); + + if (use_native_bridge && !app_data_dir.has_value()) { + // The app_data_dir variable should never be empty if we need to use a + // native bridge. In general, app_data_dir will never be empty for normal + // applications. It can only happen in special cases (for isolated + // processes which are not associated with any app). These are launched by + // the framework and should not be emulated anyway. use_native_bridge = false; - ALOGW("Native bridge will not be used because dataDir == NULL."); + ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr."); } if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) { @@ -622,34 +733,33 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi } } - if (!SetGids(env, javaGids, &error_msg)) { + if (!SetGids(env, gids, &error_msg)) { fail_fn(error_msg); } - if (!SetRLimits(env, javaRlimits, &error_msg)) { + if (!SetRLimits(env, rlimits, &error_msg)) { fail_fn(error_msg); } if (use_native_bridge) { - ScopedUtfChars isa_string(env, instructionSet); - ScopedUtfChars data_dir(env, dataDir); - android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str()); + // Due to the logic behind use_native_bridge we know that both app_data_dir + // and instruction_set contain values. + android::PreInitializeNativeBridge(app_data_dir.value().c_str(), + instruction_set.value().c_str()); } - int rc = setresgid(gid, gid, gid); - if (rc == -1) { + if (setresgid(gid, gid, gid) == -1) { fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno))); } - // Must be called when the new process still has CAP_SYS_ADMIN, in this case, before changing - // uid from 0, which clears capabilities. The other alternative is to call - // prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that breaks SELinux domain transition (see - // b/71859146). As the result, privileged syscalls used below still need to be accessible in - // app process. + // Must be called when the new process still has CAP_SYS_ADMIN, in this case, + // before changing uid from 0, which clears capabilities. The other + // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that + // breaks SELinux domain transition (see b/71859146). As the result, + // privileged syscalls used below still need to be accessible in app process. SetUpSeccompFilter(uid); - rc = setresuid(uid, uid, uid); - if (rc == -1) { + if (setresuid(uid, uid, uid) == -1) { fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno))); } @@ -666,6 +776,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno)); RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed"); } + if (dumpable == 2 && uid >= AID_APP) { if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) { ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno)); @@ -682,7 +793,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi } } - if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities, + if (!SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, &error_msg)) { fail_fn(error_msg); } @@ -691,42 +802,22 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi fail_fn(error_msg); } - const char* se_info_c_str = NULL; - ScopedUtfChars* se_info = NULL; - if (java_se_info != NULL) { - se_info = new ScopedUtfChars(env, java_se_info); - se_info_c_str = se_info->c_str(); - if (se_info_c_str == NULL) { - fail_fn("se_info_c_str == NULL"); - } - } - const char* se_name_c_str = NULL; - ScopedUtfChars* se_name = NULL; - if (java_se_name != NULL) { - se_name = new ScopedUtfChars(env, java_se_name); - se_name_c_str = se_name->c_str(); - if (se_name_c_str == NULL) { - fail_fn("se_name_c_str == NULL"); - } - } - rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str); - if (rc == -1) { - fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid, - is_system_server, se_info_c_str, se_name_c_str)); + const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr; + const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr; + + if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) { + fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", + uid, is_system_server, se_info_ptr, nice_name_ptr)); } // Make it easier to debug audit logs by setting the main thread's name to the // nice name rather than "app_process". - if (se_name_c_str == NULL && is_system_server) { - se_name_c_str = "system_server"; - } - if (se_name_c_str != NULL) { - SetThreadName(se_name_c_str); + if (nice_name.has_value()) { + SetThreadName(nice_name.value().c_str()); + } else if (is_system_server) { + SetThreadName("system_server"); } - delete se_info; - delete se_name; - // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers). UnsetChldSignalHandler(); @@ -743,124 +834,101 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGi } env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, - is_system_server, is_child_zygote, instructionSet); + is_system_server, is_child_zygote, managed_instruction_set); + if (env->ExceptionCheck()) { fail_fn("Error calling post fork hooks."); } } -// 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); +static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { + __user_cap_header_struct capheader; + memset(&capheader, 0, sizeof(capheader)); + capheader.version = _LINUX_CAPABILITY_VERSION_3; + capheader.pid = 0; - 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"; + __user_cap_data_struct capdata[2]; + if (capget(&capheader, &capdata[0]) == -1) { + ALOGE("capget failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "capget failed"); } - 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(); - stats_log_close(); - std::string error_msg; + return capdata[0].effective | (static_cast<uint64_t>(capdata[1].effective) << 32); +} - // 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); +static jlong CalculateCapabilities(JNIEnv* env, jint uid, jint gid, jintArray gids, + bool is_child_zygote) { + jlong capabilities = 0; + + /* + * Grant the following capabilities to the Bluetooth user: + * - CAP_WAKE_ALARM + * - CAP_NET_RAW + * - CAP_NET_BIND_SERVICE (for DHCP client functionality) + * - CAP_SYS_NICE (for setting RT priority for audio-related threads) + */ + + if (multiuser_get_app_id(uid) == AID_BLUETOOTH) { + capabilities |= (1LL << CAP_WAKE_ALARM); + capabilities |= (1LL << CAP_NET_RAW); + capabilities |= (1LL << CAP_NET_BIND_SERVICE); + capabilities |= (1LL << CAP_SYS_NICE); } - android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level(); + /* + * Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock" + */ - pid_t pid = fork(); + bool gid_wakelock_found = false; + if (gid == AID_WAKELOCK) { + gid_wakelock_found = true; + } else if (gids != nullptr) { + jsize gids_num = env->GetArrayLength(gids); + ScopedIntArrayRO native_gid_proxy(env, gids); - 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); + if (native_gid_proxy.get() == nullptr) { + RuntimeAbort(env, __LINE__, "Bad gids array"); } - // 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); + for (int gid_index = gids_num; --gids_num >= 0;) { + if (native_gid_proxy[gid_index] == AID_WAKELOCK) { + gid_wakelock_found = true; + break; + } } - - // Turn fdsan back on. - android_fdsan_set_error_level(fdsan_error_level); } - // 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))); + if (gid_wakelock_found) { + capabilities |= (1LL << CAP_BLOCK_SUSPEND); } - return pid; -} -static uint64_t GetEffectiveCapabilityMask(JNIEnv* env) { - __user_cap_header_struct capheader; - memset(&capheader, 0, sizeof(capheader)); - capheader.version = _LINUX_CAPABILITY_VERSION_3; - capheader.pid = 0; + /* + * Grant child Zygote processes the following capabilities: + * - CAP_SETUID (change UID of child processes) + * - CAP_SETGID (change GID of child processes) + * - CAP_SETPCAP (change capabilities of child processes) + */ + + if (is_child_zygote) { + capabilities |= (1LL << CAP_SETUID); + capabilities |= (1LL << CAP_SETGID); + capabilities |= (1LL << CAP_SETPCAP); + } - __user_cap_data_struct capdata[2]; - if (capget(&capheader, &capdata[0]) == -1) { - ALOGE("capget failed: %s", strerror(errno)); - RuntimeAbort(env, __LINE__, "capget failed"); - } + /* + * Containers run without some capabilities, so drop any caps that are not + * available. + */ - return capdata[0].effective | - (static_cast<uint64_t>(capdata[1].effective) << 32); + return capabilities & GetEffectiveCapabilityMask(env); } } // anonymous namespace namespace android { static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) { - // security_getenforce is not allowed on app process. Initialize and cache the value before - // zygote forks. + // security_getenforce is not allowed on app process. Initialize and cache + // the value before zygote forks. g_is_security_enforced = security_getenforce(); } @@ -871,76 +939,33 @@ static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jcl static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, - jint mount_external, jstring se_info, jstring se_name, - jintArray fdsToClose, jintArray fdsToIgnore, jboolean is_child_zygote, - jstring instructionSet, jstring appDataDir) { - jlong capabilities = 0; - - // Grant CAP_WAKE_ALARM to the Bluetooth process. - // Additionally, allow bluetooth to open packet sockets so it can start the DHCP client. - // Grant CAP_SYS_NICE to allow Bluetooth to set RT priority for - // audio-related threads. - // TODO: consider making such functionality an RPC to netd. - if (multiuser_get_app_id(uid) == AID_BLUETOOTH) { - capabilities |= (1LL << CAP_WAKE_ALARM); - capabilities |= (1LL << CAP_NET_RAW); - capabilities |= (1LL << CAP_NET_BIND_SERVICE); - capabilities |= (1LL << CAP_SYS_NICE); - } - - // 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); - } - - // If forking a child zygote process, that zygote will need to be able to change - // the UID and GID of processes it forks, as well as drop those capabilities. - if (is_child_zygote) { - capabilities |= (1LL << CAP_SETUID); - capabilities |= (1LL << CAP_SETGID); - capabilities |= (1LL << CAP_SETPCAP); - } - - // Containers run without some capabilities, so drop any caps that are not - // available. - capabilities &= GetEffectiveCapabilityMask(env); + jint mount_external, jstring se_info, jstring nice_name, + jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, + jstring instruction_set, jstring app_data_dir) { + jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); - pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore); + pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore); 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); + mount_external, se_info, nice_name, false, + is_child_zygote == JNI_TRUE, instruction_set, app_data_dir); } 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 = ForkCommon(env, NULL, true, NULL, NULL); + 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, - permittedCapabilities, effectiveCapabilities, - MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, - false, NULL, NULL); + 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); @@ -974,7 +999,7 @@ static void com_android_internal_os_Zygote_nativeAllowFileAcrossFork( ScopedUtfChars path_native(env, path); const char* path_cstr = path_native.c_str(); if (!path_cstr) { - RuntimeAbort(env, __LINE__, "path_cstr == NULL"); + RuntimeAbort(env, __LINE__, "path_cstr == nullptr"); } FileDescriptorWhitelist::Get()->Allow(path_cstr); } |