summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Narayan Kamath <narayan@google.com> 2016-11-10 11:17:48 +0000
committer android-build-merger <android-build-merger@google.com> 2016-11-10 11:17:48 +0000
commit50b0c3be577d3d702dd184c26f3a5a4326fbf7df (patch)
tree540c1c191d2e8b7149fc795ef0a60647064213ac
parent83b46a1590990922735b8aef5d5b87be33d62af3 (diff)
parent14bd75fa795fcf0f6aff59ea28f2d6352d852136 (diff)
Zygote : Block SIGCHLD during fork. am: b1f1209d9a am: 35b8453338
am: 14bd75fa79 Change-Id: I9b2acc6d40cc0f4724598f97b704c040bba15417
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp25
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 e7835db85793..6d40626c0a25 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -430,6 +430,20 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
jstring instructionSet, jstring dataDir) {
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();
@@ -461,6 +475,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);
@@ -592,6 +611,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;
}