Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1e03652 authored by David Sehr's avatar David Sehr Committed by android-build-merger
Browse files

Merge "Split fork and specialize in zygote" into stage-aosp-master

am: 3937fbb4

Change-Id: I129586249b68364b7813a146fc5b48936b948174
parents 55b29bae 3937fbb4
Loading
Loading
Loading
Loading
+220 −198
Original line number Diff line number Diff line
@@ -535,20 +535,14 @@ static bool FillFileDescriptorVector(JNIEnv* env,
  return true;
}

// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
// Utility routine to specialize a zygote child process.
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                             jint runtime_flags, jobjectArray javaRlimits,
                             jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jintArray fdsToIgnore, bool is_child_zygote,
                                     jstring instructionSet, jstring dataDir) {
  SetSignalHandlers();

  sigset_t sigchld;
  sigemptyset(&sigchld);
  sigaddset(&sigchld, SIGCHLD);
                             jint mount_external, jstring java_se_info, jstring java_se_name,
                             bool is_system_server, bool is_child_zygote, jstring instructionSet,
                             jstring dataDir) {
  std::string error_msg;

  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
      __attribute__ ((noreturn)) {
@@ -568,57 +562,6 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
    __builtin_unreachable();
  };

  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
  // log, which would result in the logging FDs we close being reopened.
  // This would cause failures because the FDs are not whitelisted.
  //
  // Note that the zygote process is single threaded at this point.
  if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
  }

  // Close any logging related FDs before we start evaluating the list of
  // file descriptors.
  __android_log_close();

  std::string error_msg;

  // 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;
  if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
    fail_fn(error_msg);
  }
  if (gOpenFdTable == NULL) {
    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
    if (gOpenFdTable == NULL) {
      fail_fn(error_msg);
    }
  } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
    fail_fn(error_msg);
  }

  pid_t pid = fork();

  if (pid == 0) {
    PreApplicationInit();

    // Clean up any descriptors which must be closed immediately
    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
      fail_fn(error_msg);
    }

    // Re-open all remaining open file descriptors so that they aren't shared
    // with the zygote across a fork.
    if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
      fail_fn(error_msg);
    }

    if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
      fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
    }

  // Keep capabilities across UID change, unless we're staying root.
  if (uid != 0) {
    if (!EnableKeepCapabilities(&error_msg)) {
@@ -669,12 +612,11 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
          if (rc == -EROFS) {
              ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
          } else {
                ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
              ALOGE("createProcessGroup(%d, %d) failed: %s", uid, 0/*pid*/, strerror(-rc));
          }
      }
  }

    std::string error_msg;
  if (!SetGids(env, javaGids, &error_msg)) {
    fail_fn(error_msg);
  }
@@ -788,14 +730,89 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra
  if (env->ExceptionCheck()) {
    fail_fn("Error calling post fork hooks.");
  }
  } else if (pid > 0) {
    // the parent process
}

// Utility routine to fork zygote and specialize the child process.
static pid_t ForkCommon(JNIEnv* env, jstring java_se_name, bool is_system_server,
                        jintArray fdsToClose, jintArray fdsToIgnore) {
  SetSignalHandlers();

  // Block SIGCHLD prior to fork.
  sigset_t sigchld;
  sigemptyset(&sigchld);
  sigaddset(&sigchld, SIGCHLD);

  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
      __attribute__ ((noreturn)) {
    const char* se_name_c_str = nullptr;
    std::unique_ptr<ScopedUtfChars> se_name;
    if (java_se_name != nullptr) {
      se_name.reset(new ScopedUtfChars(env, java_se_name));
      se_name_c_str = se_name->c_str();
    }
    if (se_name_c_str == nullptr && is_system_server) {
      se_name_c_str = "system_server";
    }
    const std::string& error_msg = (se_name_c_str == nullptr)
        ? msg
        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
    env->FatalError(error_msg.c_str());
    __builtin_unreachable();
  };

  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
  // log, which would result in the logging FDs we close being reopened.
  // This would cause failures because the FDs are not whitelisted.
  //
  // Note that the zygote process is single threaded at this point.
  if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
  }

  // Close any logging related FDs before we start evaluating the list of
  // file descriptors.
  __android_log_close();

  std::string error_msg;

  // 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;
  if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
    fail_fn(error_msg);
  }
  if (gOpenFdTable == NULL) {
    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
    if (gOpenFdTable == NULL) {
      fail_fn(error_msg);
    }
  } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
    fail_fn(error_msg);
  }

  pid_t pid = fork();

  if (pid == 0) {
    // The child process.
    PreApplicationInit();

    // Clean up any descriptors which must be closed immediately
    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
      fail_fn(error_msg);
    }

    // Re-open all remaining open file descriptors so that they aren't shared
    // with the zygote across a fork.
    if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
      fail_fn(error_msg);
    }
  }

  // We blocked SIGCHLD prior to a fork, we unblock it here.
  if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
  }
  }
  return pid;
}

@@ -881,22 +898,27 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
    // available.
    capabilities &= GetEffectiveCapabilityMask(env);

    return ForkAndSpecializeCommon(env, uid, gid, gids, runtime_flags,
            rlimits, capabilities, capabilities, mount_external, se_info,
            se_name, false, fdsToClose, fdsToIgnore, is_child_zygote == JNI_TRUE,
            instructionSet, appDataDir);
    pid_t pid = ForkCommon(env, se_name, false, fdsToClose, fdsToIgnore);
    if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       capabilities, capabilities,
                       mount_external, se_info, se_name, false,
                       is_child_zygote == JNI_TRUE, instructionSet, appDataDir);
    }
    return pid;
}

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      runtime_flags, rlimits,
  pid_t pid = ForkCommon(env, NULL, true, NULL, NULL);
  if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, false, NULL, NULL);
  if (pid > 0) {
                       MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true,
                       false, NULL, NULL);
  } else if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;