Merge "Zygote: Add fdsToIgnore"

am: 5b22a826d5

Change-Id: I458e354acf620cb434de41790ce94b814ff0a4ea
This commit is contained in:
Andreas Gampe
2017-01-11 02:33:05 +00:00
committed by android-build-merger
5 changed files with 50 additions and 14 deletions

View 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

View 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);

View 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 },

View 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);
}

View 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