summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java36
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java10
2 files changed, 45 insertions, 1 deletions
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 4f3b5b3..f9a1f89 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -224,9 +224,37 @@ class ZygoteConnection {
ZygoteInit.setCloseOnExec(serverPipeFd, true);
}
+ /**
+ * In order to avoid leaking descriptors to the Zygote child,
+ * the native code must close the two Zygote socket descriptors
+ * in the child process before it switches from Zygote-root to
+ * the UID and privileges of the application being launched.
+ *
+ * In order to avoid "bad file descriptor" errors when the
+ * two LocalSocket objects are closed, the Posix file
+ * descriptors are released via a dup2() call which closes
+ * the socket and substitutes an open descriptor to /dev/null.
+ */
+
+ int [] fdsToClose = { -1, -1 };
+
+ FileDescriptor fd = mSocket.getFileDescriptor();
+
+ if (fd != null) {
+ fdsToClose[0] = fd.getInt$();
+ }
+
+ fd = ZygoteInit.getServerSocketFileDescriptor();
+
+ if (fd != null) {
+ fdsToClose[1] = fd.getInt$();
+ }
+
+ fd = null;
+
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
- parsedArgs.niceName);
+ parsedArgs.niceName, fdsToClose);
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
@@ -814,6 +842,12 @@ class ZygoteConnection {
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
+ /**
+ * By the time we get here, the native code has closed the two actual Zygote
+ * socket connections, and substituted /dev/null in their place. The LocalSocket
+ * objects still need to be closed properly.
+ */
+
closeSocket();
ZygoteInit.closeServerSocket();
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 55d5513..4bf13fc 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -207,6 +207,16 @@ public class ZygoteInit {
sServerSocket = null;
}
+ /**
+ * Return the server socket's underlying file descriptor, so that
+ * ZygoteConnection can pass it to the native code for proper
+ * closure after a child process is forked off.
+ */
+
+ static FileDescriptor getServerSocketFileDescriptor() {
+ return sServerSocket.getFileDescriptor();
+ }
+
private static final int UNPRIVILEGED_UID = 9999;
private static final int UNPRIVILEGED_GID = 9999;