diff options
author | Dave Platt <dplatt@google.com> | 2014-02-05 17:03:52 -0800 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2014-02-19 23:17:46 -0800 |
commit | 0ba2fc83a4d25ee8781ca5030a365231cf46c5b9 (patch) | |
tree | 8d729ad3cfb29a6d6d30de6e91072c007444128a /vm | |
parent | bbe2d7a66c3678f5514c73c8e18ebffadf889431 (diff) | |
download | android_dalvik-0ba2fc83a4d25ee8781ca5030a365231cf46c5b9.tar.gz android_dalvik-0ba2fc83a4d25ee8781ca5030a365231cf46c5b9.tar.bz2 android_dalvik-0ba2fc83a4d25ee8781ca5030a365231cf46c5b9.zip |
Finish fixing Zygote descriptor leakage problem
In order to prevent Zygote descriptors from leaking into the child
environment, they should be closed by the forked-off child process
before the child switches to the application UID. These changes close
the descriptors via dup2(), substituting a descriptor open to
/dev/null in their place; this allows the Zygote Java code to close
the FileDescriptor objects cleanly.
This is a multi-project change: dalvik, art, libcore, frameworks/base,
and external/sepolicy are affected. The CLs need to be approved
together, lest the build break or the software fail to boot.
Round 2: whitespace
Bug: 12114500
Change-Id: I989c83291d0c42d4cad63f24a3e98a93e231c9d3
Diffstat (limited to 'vm')
-rw-r--r-- | vm/native/dalvik_system_Zygote.cpp | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/vm/native/dalvik_system_Zygote.cpp b/vm/native/dalvik_system_Zygote.cpp index 995268c3f..fa0cb51fa 100644 --- a/vm/native/dalvik_system_Zygote.cpp +++ b/vm/native/dalvik_system_Zygote.cpp @@ -34,6 +34,8 @@ #include <grp.h> #include <errno.h> #include <paths.h> +#include <fcntl.h> +#include <unistd.h> #include <sys/personality.h> #include <sys/stat.h> #include <sys/mount.h> @@ -504,6 +506,45 @@ static bool needsNoRandomizeWorkaround() { #endif } +#ifdef HAVE_ANDROID_OS + +// Utility to close down the Zygote socket file descriptors while +// the child is still running as root with Zygote's privileges. Each +// descriptor (if any) is closed via dup2(), replacing it with a valid +// (open) descriptor to /dev/null. + +static void detachDescriptors(ArrayObject* fdsToClose) { + if (!fdsToClose) { + return; + } + size_t count = fdsToClose->length; + int *ar = (int *) (void *) fdsToClose->contents; + if (!ar) { + ALOG(LOG_ERROR, ZYGOTE_LOG_TAG, "Bad fd array"); + dvmAbort(); + } + size_t i; + int devnull; + for (i = 0; i < count; i++) { + if (ar[1] < 0) { + continue; + } + devnull = open("/dev/null", O_RDWR); + if (devnull < 0) { + ALOG(LOG_ERROR, ZYGOTE_LOG_TAG, "Failed to open /dev/null"); + dvmAbort(); + } + ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, "Switching descriptor %d to /dev/null", ar[i]); + if (dup2(devnull, ar[i]) < 0) { + ALOG(LOG_ERROR, ZYGOTE_LOG_TAG, "Failed dup2() on descriptor %d", ar[i]); + dvmAbort(); + } + close(devnull); + } +} + +#endif + /* * Basic KSM Support */ @@ -565,7 +606,7 @@ static inline void pushAnonymousPagesToKSM(void) /* * Utility routine to fork zygote and specialize the child process. */ -static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) +static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer, bool legacyFork) { pid_t pid; @@ -574,6 +615,7 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) ArrayObject* gids = (ArrayObject *)args[2]; u4 debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; + ArrayObject *fdsToClose = NULL; u4 mountMode = MOUNT_EXTERNAL_NONE; int64_t permittedCapabilities, effectiveCapabilities; char *seInfo = NULL; @@ -608,6 +650,9 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) dvmAbort(); } } + if (!legacyFork) { + fdsToClose = (ArrayObject *)args[8]; + } } if (!gDvm.zygote) { @@ -635,6 +680,10 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) extern int gMallocLeakZygoteChild; gMallocLeakZygoteChild = 1; + // Unhook from the Zygote sockets immediately + + detachDescriptors(fdsToClose); + /* keep caps across UID change, unless we're staying root */ if (uid != 0) { err = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); @@ -768,6 +817,28 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) } /* + * We must expose both flavors of the native forking code for a while, + * as this Dalvik change must be reviewed and checked in before the + * libcore and frameworks changes. The legacy fork API function and + * registration can be removed later. + */ + +/* + * native public static int nativeForkAndSpecialize(int uid, int gid, + * int[] gids, int debugFlags, int[][] rlimits, int mountExternal, + * String seInfo, String niceName, int[] fdsToClose); + */ +static void Dalvik_dalvik_system_Zygote_forkAndSpecialize_new(const u4* args, + JValue* pResult) +{ + pid_t pid; + + pid = forkAndSpecializeCommon(args, false, false); + + RETURN_INT(pid); +} + +/* * native public static int nativeForkAndSpecialize(int uid, int gid, * int[] gids, int debugFlags, int[][] rlimits, int mountExternal, * String seInfo, String niceName); @@ -777,7 +848,7 @@ static void Dalvik_dalvik_system_Zygote_forkAndSpecialize(const u4* args, { pid_t pid; - pid = forkAndSpecializeCommon(args, false); + pid = forkAndSpecializeCommon(args, false, true); RETURN_INT(pid); } @@ -791,7 +862,7 @@ static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult) { pid_t pid; - pid = forkAndSpecializeCommon(args, true); + pid = forkAndSpecializeCommon(args, true, true); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) { @@ -814,6 +885,8 @@ static void Dalvik_dalvik_system_Zygote_forkSystemServer( const DalvikNativeMethod dvm_dalvik_system_Zygote[] = { { "nativeFork", "()I", Dalvik_dalvik_system_Zygote_fork }, + { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I", + Dalvik_dalvik_system_Zygote_forkAndSpecialize_new }, { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I", Dalvik_dalvik_system_Zygote_forkAndSpecialize }, { "nativeForkSystemServer", "(II[II[[IJJ)I", |