diff options
Diffstat (limited to 'core/jni/com_android_internal_os_Zygote.cpp')
-rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index b431a3f..a1fef4a 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -16,6 +16,8 @@ #define LOG_TAG "Zygote" +#include <sstream> + // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc #include <sys/mount.h> #include <linux/fs.h> @@ -53,6 +55,7 @@ #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" #include "ScopedUtfChars.h" +#include "fd_utils-inl.h" #include "nativebridge/native_bridge.h" @@ -78,6 +81,12 @@ static void RuntimeAbort(JNIEnv* env) { env->FatalError("RuntimeAbort"); } +static void RuntimeAbort(JNIEnv* env, int line, const char* msg) { + std::ostringstream oss; + oss << __FILE__ << ":" << line << ": " << msg; + env->FatalError(oss.str().c_str()); +} + // This signal handler is for zygote mode, since the zygote must reap its children static void SigChldHandler(int /*signal_number*/) { pid_t pid; @@ -439,6 +448,9 @@ static void SetForkLoad(bool boost) { } #endif +// The list of open zygote file descriptors. +static FileDescriptorTable* gOpenFdTable = NULL; + // Utility routine to fork zygote and specialize the child process. static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, @@ -453,6 +465,22 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetForkLoad(true); #endif + // Close any logging related FDs before we start evaluating the list of + // file descriptors. + __android_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). + if (gOpenFdTable == NULL) { + gOpenFdTable = FileDescriptorTable::Create(); + if (gOpenFdTable == NULL) { + RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table."); + } + } else if (!gOpenFdTable->Restat()) { + RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table."); + } + pid_t pid = fork(); if (pid == 0) { @@ -462,6 +490,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra // Clean up any descriptors which must be closed immediately DetachDescriptors(env, fdsToClose); + // Re-open all remaining open file descriptors so that they aren't shared + // with the zygote across a fork. + if (!gOpenFdTable->ReopenOrDetach()) { + RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors."); + } + // Keep capabilities across UID change, unless we're staying root. if (uid != 0) { EnableKeepCapabilities(env); |