diff options
| author | 2016-11-10 10:04:09 +0000 | |
|---|---|---|
| committer | 2016-11-10 10:04:13 +0000 | |
| commit | a67112ca925845af31b27cf8f5ec022e2c8bf231 (patch) | |
| tree | 329454fb2ce39edc25c91db7dea3a593ee7344c9 | |
| parent | 4146229e694b62cc3f91e9794cd7940aa36e8bfe (diff) | |
| parent | dfcc79ee8ecd4166cba19be7493c6175cb0c65a9 (diff) | |
Merge "Zygote : Block SIGCHLD during fork." into nyc-dev
| -rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index 9bec6a36b5e3..2fdabcd9fa69 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -452,6 +452,20 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetForkLoad(true); #endif + sigset_t sigchld; + sigemptyset(&sigchld); + sigaddset(&sigchld, SIGCHLD); + + // 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) { + ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed."); + } + // Close any logging related FDs before we start evaluating the list of // file descriptors. __android_log_close(); @@ -483,6 +497,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors."); } + if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { + ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); + } + // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(env); @@ -616,6 +635,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetForkLoad(false); #endif + // We blocked SIGCHLD prior to a fork, we unblock it here. + if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { + ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); + } } return pid; } |