Skip to content

Commit b8be33b

Browse files
narayankgitbuildkicker
authored andcommitted
Backport changes to whitelist sockets opened by the zygote.
This is the backport of the following commits : Commit c5f27a7: ----------------------------------------------- Reopen whitelisted zygote file descriptors after a fork. We don't want these descriptors to be shared post-fork, so we'll have to close and reopen them when the zygote forks. The set of open descriptors is checked against a whitelist and it is a fatal error if a non whitelisted FD is opened. It is also a fatal error if anything other than a regular file / character device or socket is opened at the time of forking. This work is done in two stages : - An initial list of FDs is constructed and cached prior to the first zygote fork. - On each subsequent fork, we check whether the list of open FDs has changed. We are currently tolerant of changes, but in the longer term, it should be a fatal error if the set of open file descriptors in the zygote changes. - Post fork, we traverse the list of open descriptors and reopen them if necessary. bug: 30963384 Commit 3764a26: ----------------------------------------------- Add a whitelist of sockets on fork. Maintain a whitelist of AF_UNIX sockets that are permitted to exist at the time of forking. If an open socket does not belong to the whitelist (or is not AF_UNIX), the process will abort. If an open socket is whitelisted, it will be redirected to /dev/null after a sucessful fork. This allows us to unify our handling of the special zygote sockets (/dev/socket/zygote[_secondary]) with the existing whitelist of non socket file descriptors. This change also removes non-fatal ALOGW messages since they have the side effect of reopening the logging socket. bug: 30963384 Commit 0b76d6a: ----------------------------------------------- fd_utils: Fix broken usage of iterators. There were two separate issues here : - RestatInternal was using an iterator after a call to erase(). This will not work because it will be invalidated. - The "standard" for loop idiom for iterating over a map while making structural changes to it is broken. Switch to a while loop and treat cases where elements are erased differently from cases where they aren't. bug: 31092930 bug: 30963384 Plus additional changes: ----------------------------------------------- - add /dev/__properties__ to the whitelist. Change-Id: I709a7f4913e807a8fec8a58c81e98fe5b5222820 (cherry picked from commit 41ca1bc)
1 parent f1e3170 commit b8be33b

2 files changed

Lines changed: 586 additions & 0 deletions

File tree

core/jni/com_android_internal_os_Zygote.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#define LOG_TAG "Zygote"
1818

19+
#include <sstream>
20+
1921
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
2022
#include <sys/mount.h>
2123
#include <linux/fs.h>
@@ -53,6 +55,7 @@
5355
#include "ScopedLocalRef.h"
5456
#include "ScopedPrimitiveArray.h"
5557
#include "ScopedUtfChars.h"
58+
#include "fd_utils-inl.h"
5659

5760
#include "nativebridge/native_bridge.h"
5861

@@ -78,6 +81,12 @@ static void RuntimeAbort(JNIEnv* env) {
7881
env->FatalError("RuntimeAbort");
7982
}
8083

84+
static void RuntimeAbort(JNIEnv* env, int line, const char* msg) {
85+
std::ostringstream oss;
86+
oss << __FILE__ << ":" << line << ": " << msg;
87+
env->FatalError(oss.str().c_str());
88+
}
89+
8190
// This signal handler is for zygote mode, since the zygote must reap its children
8291
static void SigChldHandler(int /*signal_number*/) {
8392
pid_t pid;
@@ -439,6 +448,9 @@ static void SetForkLoad(bool boost) {
439448
}
440449
#endif
441450

451+
// The list of open zygote file descriptors.
452+
static FileDescriptorTable* gOpenFdTable = NULL;
453+
442454
// Utility routine to fork zygote and specialize the child process.
443455
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
444456
jint debug_flags, jobjectArray javaRlimits,
@@ -453,6 +465,22 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
453465
SetForkLoad(true);
454466
#endif
455467

468+
// Close any logging related FDs before we start evaluating the list of
469+
// file descriptors.
470+
__android_log_close();
471+
472+
// If this is the first fork for this zygote, create the open FD table.
473+
// If it isn't, we just need to check whether the list of open files has
474+
// changed (and it shouldn't in the normal case).
475+
if (gOpenFdTable == NULL) {
476+
gOpenFdTable = FileDescriptorTable::Create();
477+
if (gOpenFdTable == NULL) {
478+
RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
479+
}
480+
} else if (!gOpenFdTable->Restat()) {
481+
RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
482+
}
483+
456484
pid_t pid = fork();
457485

458486
if (pid == 0) {
@@ -462,6 +490,12 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
462490
// Clean up any descriptors which must be closed immediately
463491
DetachDescriptors(env, fdsToClose);
464492

493+
// Re-open all remaining open file descriptors so that they aren't shared
494+
// with the zygote across a fork.
495+
if (!gOpenFdTable->ReopenOrDetach()) {
496+
RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
497+
}
498+
465499
// Keep capabilities across UID change, unless we're staying root.
466500
if (uid != 0) {
467501
EnableKeepCapabilities(env);

0 commit comments

Comments
 (0)