Commit message: None
CVE: CVE-2019-5816
CWE: CWE-664
Vulnerability description: Process lifetime issue in Chrome in Google Chrome on Android prior to 74.0.3729.108 allowed a remote attacker to potentially persist an exploited process via a crafted HTML page.

Project: Chrome

void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
    const ChildProcessLauncherHelper::Process& process,
    const base::LaunchOptions& options) {
}

Project: Chrome

void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
  std::string process_type =
      command_line()->GetSwitchValueASCII(switches::kProcessType);
  CHECK(process_type == switches::kGpuProcess ||
        process_type == switches::kRendererProcess ||
        process_type == switches::kUtilityProcess)
      << "Unsupported process type: " << process_type;

  DCHECK(process_type == switches::kGpuProcess ||
         !command_line()->HasSwitch(service_manager::switches::kNoSandbox));
}

Project: Chrome

bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
    const PosixFileDescriptorInfo& files_to_register,
    base::LaunchOptions* options) {
  return true;
}

Project: Chrome

ChildProcessLauncherHelper::CreateNamedPlatformChannelOnClientThread() {
  return base::nullopt;
}

Project: Chrome

void ChildProcessLauncherHelper::DumpProcessStack(
    const base::Process& process) {
  JNIEnv* env = AttachCurrentThread();
  DCHECK(env);
  return Java_ChildProcessLauncherHelperImpl_dumpProcessStack(env, java_peer_,
                                                              process.Handle());
}

Project: Chrome

ChildProcessLauncherHelper::GetFilesToMap() {
  DCHECK(CurrentlyOnProcessLauncherTaskRunner());

  CHECK(!command_line()->HasSwitch(switches::kSingleProcess));

  std::unique_ptr<PosixFileDescriptorInfo> files_to_register =
      CreateDefaultPosixFilesToMap(child_process_id(),
                                   mojo_channel_->remote_endpoint(),
                                   true /* include_service_required_files */,
                                   GetProcessType(), command_line());

#if ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE
  base::MemoryMappedFile::Region icu_region;
  int fd = base::i18n::GetIcuDataFileHandle(&icu_region);
  files_to_register->ShareWithRegion(kAndroidICUDataDescriptor, fd, icu_region);
#endif  // ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE

  return files_to_register;
}

Project: Chrome

static void JNI_ChildProcessLauncherHelperImpl_SetTerminationInfo(
    JNIEnv* env,
    jlong termination_info_ptr,
    jint binding_state,
    jboolean killed_by_us,
    jboolean clean_exit,
    jint remaining_process_with_strong_binding,
    jint remaining_process_with_moderate_binding,
    jint remaining_process_with_waived_binding) {
  ChildProcessTerminationInfo* info =
      reinterpret_cast<ChildProcessTerminationInfo*>(termination_info_ptr);
  info->binding_state =
      static_cast<base::android::ChildBindingState>(binding_state);
  info->was_killed_intentionally_by_browser = killed_by_us;
  info->clean_exit = clean_exit;
  info->remaining_process_with_strong_binding =
      remaining_process_with_strong_binding;
  info->remaining_process_with_moderate_binding =
      remaining_process_with_moderate_binding;
  info->remaining_process_with_waived_binding =
      remaining_process_with_waived_binding;
}

Project: Chrome

ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
    const base::LaunchOptions& options,
    std::unique_ptr<PosixFileDescriptorInfo> files_to_register,
    bool* is_synchronous_launch,
    int* launch_result) {
  *is_synchronous_launch = false;

  JNIEnv* env = AttachCurrentThread();
  DCHECK(env);

  ScopedJavaLocalRef<jobjectArray> j_argv =
      ToJavaArrayOfStrings(env, command_line()->argv());

  size_t file_count = files_to_register->GetMappingSize();
  DCHECK(file_count > 0);

  ScopedJavaLocalRef<jclass> j_file_info_class = base::android::GetClass(
      env, "org/chromium/base/process_launcher/FileDescriptorInfo");
  ScopedJavaLocalRef<jobjectArray> j_file_infos(
      env, env->NewObjectArray(file_count, j_file_info_class.obj(), NULL));
  base::android::CheckException(env);

  for (size_t i = 0; i < file_count; ++i) {
    int fd = files_to_register->GetFDAt(i);
    PCHECK(0 <= fd);
    int id = files_to_register->GetIDAt(i);
    const auto& region = files_to_register->GetRegionAt(i);
    bool auto_close = files_to_register->OwnsFD(fd);
    if (auto_close) {
      ignore_result(files_to_register->ReleaseFD(fd).release());
    }

    ScopedJavaLocalRef<jobject> j_file_info =
        Java_ChildProcessLauncherHelperImpl_makeFdInfo(
            env, id, fd, auto_close, region.offset, region.size);
    PCHECK(j_file_info.obj());
    env->SetObjectArrayElement(j_file_infos.obj(), i, j_file_info.obj());
  }

  java_peer_.Reset(Java_ChildProcessLauncherHelperImpl_createAndStart(
      env, reinterpret_cast<intptr_t>(this), j_argv, j_file_infos));
  AddRef();  // Balanced by OnChildProcessStarted.
  base::PostTaskWithTraits(
      FROM_HERE, {client_thread_id_},
      base::BindOnce(
          &ChildProcessLauncherHelper::set_java_peer_available_on_client_thread,
          this));

  return Process();
}

Project: Chrome

void ChildProcessLauncherHelper::OnChildProcessStarted(
    JNIEnv*,
    const base::android::JavaParamRef<jobject>& obj,
    jint handle) {
  DCHECK(CurrentlyOnProcessLauncherTaskRunner());
  scoped_refptr<ChildProcessLauncherHelper> ref(this);
  Release();  // Balances with LaunchProcessOnLauncherThread.

  int launch_result = (handle == base::kNullProcessHandle)
                          ? LAUNCH_RESULT_FAILURE
                          : LAUNCH_RESULT_SUCCESS;

  ChildProcessLauncherHelper::Process process;
  process.process = base::Process(handle);
  PostLaunchOnLauncherThread(std::move(process), launch_result);
}

Project: Chrome

base::File OpenFileToShare(const base::FilePath& path,
                           base::MemoryMappedFile::Region* region) {
  return base::File(base::android::OpenApkAsset(path.value(), region));
}

Project: Chrome

void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
    base::Process process,
    const ChildProcessLauncherPriority& priority) {
  JNIEnv* env = AttachCurrentThread();
  DCHECK(env);
  return Java_ChildProcessLauncherHelperImpl_setPriority(
      env, java_peer_, process.Handle(), priority.visible,
      priority.has_media_stream, priority.has_foreground_service_worker,
      priority.frame_depth, priority.intersects_viewport,
      priority.boost_for_pending_views, static_cast<jint>(priority.importance));
}

Project: Chrome

void ChildProcessLauncherHelper::SetRegisteredFilesForService(
    const std::string& service_name,
    std::map<std::string, base::FilePath> required_files) {
  SetFilesToShareForServicePosix(service_name, std::move(required_files));
}

Project: Chrome

void StopChildProcess(base::ProcessHandle handle) {
  DCHECK(CurrentlyOnProcessLauncherTaskRunner());
  JNIEnv* env = AttachCurrentThread();
  DCHECK(env);
  Java_ChildProcessLauncherHelperImpl_stop(env, static_cast<jint>(handle));
}