diff options
| author | Narayan Kamath <narayan@google.com> | 2016-11-10 11:12:11 +0000 |
|---|---|---|
| committer | android-build-merger <android-build-merger@google.com> | 2016-11-10 11:12:11 +0000 |
| commit | 14bd75fa795fcf0f6aff59ea28f2d6352d852136 (patch) | |
| tree | a0ee97da95463b0f0d56ce74eaf5a4eae5a9291c | |
| parent | 846f64c6fc36585063610925d8c25df2b98e194a (diff) | |
| parent | 35b84533386421422f6459839dee6b4092af18d7 (diff) | |
Zygote : Block SIGCHLD during fork. am: b1f1209d9a
am: 35b8453338
Change-Id: I7c73b1a37d79f31ad8fff6d0b83426debbfd88f9
| -rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index d618c98f551b..5bee5f1ff9da 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -446,6 +446,20 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler"); + 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, NULL) == -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(); @@ -479,6 +493,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, NULL) == -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); @@ -613,6 +632,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra } } else if (pid > 0) { // the parent process + + // We blocked SIGCHLD prior to a fork, we unblock it here. + if (sigprocmask(SIG_UNBLOCK, &sigchld, NULL) == -1) { + ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); + RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); + } } return pid; } |
