1616
1717#define LOG_TAG " Zygote"
1818
19+ #include < sstream>
20+
1921// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
2022#include < sys/mount.h>
2123#include < linux/fs.h>
5355#include " ScopedLocalRef.h"
5456#include " ScopedPrimitiveArray.h"
5557#include " ScopedUtfChars.h"
58+ #include " fd_utils-inl.h"
5659
5760#include " nativebridge/native_bridge.h"
5861
@@ -78,6 +81,12 @@ static void RuntimeAbort(JNIEnv* env) {
7881 env->FatalError (" RuntimeAbort" );
7982}
8083
84+ static void RuntimeAbort (JNIEnv* env, int line, const char * msg) {
85+ std::ostringstream oss;
86+ oss << __FILE__ << " :" << line << " : " << msg;
87+ env->FatalError (oss.str ().c_str ());
88+ }
89+
8190// This signal handler is for zygote mode, since the zygote must reap its children
8291static void SigChldHandler (int /* signal_number*/ ) {
8392 pid_t pid;
@@ -439,6 +448,9 @@ static void SetForkLoad(bool boost) {
439448}
440449#endif
441450
451+ // The list of open zygote file descriptors.
452+ static FileDescriptorTable* gOpenFdTable = NULL ;
453+
442454// Utility routine to fork zygote and specialize the child process.
443455static pid_t ForkAndSpecializeCommon (JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
444456 jint debug_flags, jobjectArray javaRlimits,
@@ -453,6 +465,22 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
453465 SetForkLoad (true );
454466#endif
455467
468+ // Close any logging related FDs before we start evaluating the list of
469+ // file descriptors.
470+ __android_log_close ();
471+
472+ // If this is the first fork for this zygote, create the open FD table.
473+ // If it isn't, we just need to check whether the list of open files has
474+ // changed (and it shouldn't in the normal case).
475+ if (gOpenFdTable == NULL ) {
476+ gOpenFdTable = FileDescriptorTable::Create ();
477+ if (gOpenFdTable == NULL ) {
478+ RuntimeAbort (env, __LINE__, " Unable to construct file descriptor table." );
479+ }
480+ } else if (!gOpenFdTable ->Restat ()) {
481+ RuntimeAbort (env, __LINE__, " Unable to restat file descriptor table." );
482+ }
483+
456484 pid_t pid = fork ();
457485
458486 if (pid == 0 ) {
@@ -462,6 +490,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
462490 // Clean up any descriptors which must be closed immediately
463491 DetachDescriptors (env, fdsToClose);
464492
493+ // Re-open all remaining open file descriptors so that they aren't shared
494+ // with the zygote across a fork.
495+ if (!gOpenFdTable ->ReopenOrDetach ()) {
496+ RuntimeAbort (env, __LINE__, " Unable to reopen whitelisted descriptors." );
497+ }
498+
465499 // Keep capabilities across UID change, unless we're staying root.
466500 if (uid != 0 ) {
467501 EnableKeepCapabilities (env);
0 commit comments