diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 3381959667bfe..9067c664be2f3 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -220,9 +220,37 @@ boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { 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) { @@ -875,6 +903,12 @@ private void handleChildProc(Arguments parsedArgs, 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 36e0d4c29ccd6..8f4d7132da463 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -201,6 +201,16 @@ static void closeServerSocket() { 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;