OSDN Git Service

Zygote: Add fdsToIgnore
authorAndreas Gampe <agampe@google.com>
Thu, 5 Jan 2017 20:45:58 +0000 (12:45 -0800)
committerAndreas Gampe <agampe@google.com>
Wed, 11 Jan 2017 00:55:34 +0000 (16:55 -0800)
Add file descriptors that should be ignored in the file descriptor
table check.

Use this to ignore the pipe file descriptors when starting an app
with invoke-with (wrapper).

Bug: 32607405
Test: m
Test: Device boots
Test: Apps start
Test: adb root && adb shell setprop wrap.com.android.calculator2 logwrapper && adb shell am start -S -n com.android.calculator2/.Calculator
Change-Id: I4a30dfc9382d3172cc815bd41b17a123799354f6

core/java/com/android/internal/os/Zygote.java
core/java/com/android/internal/os/ZygoteConnection.java
core/jni/com_android_internal_os_Zygote.cpp
core/jni/fd_utils.cpp
core/jni/fd_utils.h

index 293de3d..e1e0a21 100644 (file)
@@ -85,6 +85,9 @@ public final class Zygote {
      * file descriptor numbers that are to be closed by the child
      * (and replaced by /dev/null) after forking.  An integer value
      * of -1 in any entry in the array means "ignore this one".
+     * @param fdsToIgnore null-ok an array of ints, either null or holding
+     * one or more POSIX file descriptor numbers that are to be ignored
+     * in the file descriptor table check.
      * @param instructionSet null-ok the instruction set to use.
      * @param appDataDir null-ok the data directory of the app.
      *
@@ -93,11 +96,11 @@ public final class Zygote {
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          String instructionSet, String appDataDir) {
+          int[] fdsToIgnore, String instructionSet, String appDataDir) {
         VM_HOOKS.preFork();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
-                  instructionSet, appDataDir);
+                  fdsToIgnore, instructionSet, appDataDir);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Trace.setTracingEnabled(true);
@@ -111,7 +114,7 @@ public final class Zygote {
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
-          String instructionSet, String appDataDir);
+          int[] fdsToIgnore, String instructionSet, String appDataDir);
 
     /**
      * Special method to start the system server process. In addition to the
index 44c6e85..ec80303 100644 (file)
@@ -193,11 +193,14 @@ class ZygoteConnection {
                 rlimits = parsedArgs.rlimits.toArray(intArray2d);
             }
 
+            int[] fdsToIgnore = null;
+
             if (parsedArgs.invokeWith != null) {
                 FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
                 childPipeFd = pipeFds[1];
                 serverPipeFd = pipeFds[0];
                 Os.fcntlInt(childPipeFd, F_SETFD, 0);
+                fdsToIgnore = new int[] { childPipeFd.getInt$(), serverPipeFd.getInt$() };
             }
 
             /**
@@ -230,7 +233,7 @@ class ZygoteConnection {
 
             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                     parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
-                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
+                    parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                     parsedArgs.appDataDir);
         } catch (ErrnoException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
index 94935cc..a32dbad 100644 (file)
@@ -43,6 +43,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include "android-base/logging.h"
 #include <cutils/fs.h>
 #include <cutils/multiuser.h>
 #include <cutils/sched_policy.h>
@@ -440,6 +441,22 @@ void SetThreadName(const char* thread_name) {
 // The list of open zygote file descriptors.
 static FileDescriptorTable* gOpenFdTable = NULL;
 
+static void FillFileDescriptorVector(JNIEnv* env,
+                                     jintArray java_fds,
+                                     std::vector<int>* fds) {
+  CHECK(fds != nullptr);
+  if (java_fds != nullptr) {
+    ScopedIntArrayRO ar(env, java_fds);
+    if (ar.get() == nullptr) {
+      RuntimeAbort(env, __LINE__, "Bad fd array");
+    }
+    fds->reserve(ar.size());
+    for (size_t i = 0; i < ar.size(); ++i) {
+      fds->push_back(ar[i]);
+    }
+  }
+}
+
 // 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,
@@ -447,6 +464,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
                                      bool is_system_server, jintArray fdsToClose,
+                                     jintArray fdsToIgnore,
                                      jstring instructionSet, jstring dataDir) {
   SetSigChldHandler();
 
@@ -457,12 +475,14 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
   // 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).
+  std::vector<int> fds_to_ignore;
+  FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
   if (gOpenFdTable == NULL) {
-    gOpenFdTable = FileDescriptorTable::Create();
+    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
     if (gOpenFdTable == NULL) {
       RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
     }
-  } else if (!gOpenFdTable->Restat()) {
+  } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
     RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
   }
 
@@ -621,7 +641,9 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint debug_flags, jobjectArray rlimits,
         jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose, jstring instructionSet, jstring appDataDir) {
+        jintArray fdsToClose,
+        jintArray fdsToIgnore,
+        jstring instructionSet, jstring appDataDir) {
     jlong capabilities = 0;
 
     // Grant CAP_WAKE_ALARM to the Bluetooth process.
@@ -656,7 +678,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
 
     return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
             rlimits, capabilities, capabilities, mount_external, se_info,
-            se_name, false, fdsToClose, instructionSet, appDataDir);
+            se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -667,7 +689,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer(
                                       debug_flags, rlimits,
                                       permittedCapabilities, effectiveCapabilities,
                                       MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
-                                      NULL, NULL);
+                                      NULL, NULL, NULL);
   if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -734,7 +756,7 @@ static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* en
 
 static const JNINativeMethod gMethods[] = {
     { "nativeForkAndSpecialize",
-      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[ILjava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
index 969d336..59a536b 100644 (file)
@@ -381,7 +381,7 @@ bool FileDescriptorInfo::DetachSocket() const {
 }
 
 // static
-FileDescriptorTable* FileDescriptorTable::Create() {
+FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
   DIR* d = opendir(kFdPath);
   if (d == NULL) {
     ALOGE("Unable to open directory %s: %s", kFdPath, strerror(errno));
@@ -396,6 +396,10 @@ FileDescriptorTable* FileDescriptorTable::Create() {
     if (fd == -1) {
       continue;
     }
+    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
+      ALOGI("Ignoring open file descriptor %d", fd);
+      continue;
+    }
 
     FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
     if (info == NULL) {
@@ -414,7 +418,7 @@ FileDescriptorTable* FileDescriptorTable::Create() {
   return new FileDescriptorTable(open_fd_map);
 }
 
-bool FileDescriptorTable::Restat() {
+bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
   std::set<int> open_fds;
 
   // First get the list of open descriptors.
@@ -431,6 +435,10 @@ bool FileDescriptorTable::Restat() {
     if (fd == -1) {
       continue;
     }
+    if (std::find(fds_to_ignore.begin(), fds_to_ignore.end(), fd) != fds_to_ignore.end()) {
+      ALOGI("Ignoring open file descriptor %d", fd);
+      continue;
+    }
 
     open_fds.insert(fd);
   }
index 9e3afd9..03298c3 100644 (file)
@@ -122,9 +122,9 @@ class FileDescriptorTable {
   // Creates a new FileDescriptorTable. This function scans
   // /proc/self/fd for the list of open file descriptors and collects
   // information about them. Returns NULL if an error occurs.
-  static FileDescriptorTable* Create();
+  static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore);
 
-  bool Restat();
+  bool Restat(const std::vector<int>& fds_to_ignore);
 
   // Reopens all file descriptors that are contained in the table. Returns true
   // if all descriptors were successfully re-opened or detached, and false if an