summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2016-11-07 16:22:48 +0000
committerBadash <badash@google.com>2016-11-17 15:16:12 -0800
commit949b06016427e931bad4a3ae6b5913fa75e2c907 (patch)
tree0c79f1165c5a2aa266da52271eb0fe8ff25a1c99
parent39e9323ab6e87be86c11ebb8f6ca06421062a9b4 (diff)
downloadbase-949b06016427e931bad4a3ae6b5913fa75e2c907.tar.gz
Zygote : Block SIGCHLD during fork.
We close the android logging related sockets prior as late as possible before every fork to avoid having to whitelist them. If one of the zygote's children dies after this point (but prior to the fork), we can end up reopening the logging sockets from the SIGCHLD signal handler. To prevent this from happening, block SIGCHLD during this critical section. Bug: 32693692 Test: Manual (cherry picked from commit e9a525829a354c92983a35455ccab16d1b0d3892) Zygote: Unblock SIGCHLD in the parent after fork. Follow up to change e9a525829a354c92983a. Allows the zygote to receive SIGCHLD again and prevents the zygote from getting into a zombie state if it's killed. Contributed-By: rhed_jao <rhed_jao@htc.com> Bug: 32693692 Test: manual (cherry picked from commit c7161f756e86b98f2244a04d9207b47149965fd7) Change-Id: If89903a29c84dfc9b056f9e19618046874bba689
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp24
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 a1fef4a4d963..4f9ea68ade5a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -465,6 +465,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();
@@ -496,6 +510,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);
@@ -633,6 +652,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;
}