Merge "Zygote: Add fdsToIgnore"
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user