Bug 1400051 - IPC: use process_util_linux on BSD and remove process_util_bsd. r=glandium

This change is mainly to avoid the use of SetAllFDsToCloseOnExec, which
has an unavoidable race condition that can leak file descriptors into
child processes.  The "Linux" implementation of child process creation,
now that B2G support has been removed, is essentially a generic Unix
fork+dup2+execve which works on BSD (and is already used on Solaris).
This commit is contained in:
Jed Davis 2018-09-20 19:53:31 -06:00
parent 42c96ee774
commit f2f934dc7e
4 changed files with 9 additions and 110 deletions

View File

@ -95,16 +95,9 @@ if os_macosx:
if os_bsd:
SOURCES += [
'src/base/atomicops_internals_x86_gcc.cc',
'src/base/process_util_linux.cc',
'src/base/time_posix.cc',
]
if CONFIG['OS_ARCH'] == 'GNU_kFreeBSD':
SOURCES += [
'src/base/process_util_linux.cc'
]
else:
SOURCES += [
'src/base/process_util_bsd.cc'
]
if os_linux:
SOURCES += [

View File

@ -121,7 +121,7 @@ struct LaunchOptions {
file_handle_mapping_vector fds_to_remap;
#endif
#if defined(OS_LINUX) || defined(OS_SOLARIS)
#if defined(OS_LINUX)
struct ForkDelegate {
virtual ~ForkDelegate() { }
virtual pid_t Fork() = 0;

View File

@ -1,101 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// derived from process_util_mac.cc
#include "base/process_util.h"
#include <fcntl.h>
#include <spawn.h>
#include <sys/wait.h>
#include <string>
#include "base/eintr_wrapper.h"
namespace {
static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
} // namespace
namespace base {
bool LaunchApp(const std::vector<std::string>& argv,
const LaunchOptions& options,
ProcessHandle* process_handle)
{
bool retval = true;
char* argv_copy[argv.size() + 1];
for (size_t i = 0; i < argv.size(); i++) {
argv_copy[i] = const_cast<char*>(argv[i].c_str());
}
argv_copy[argv.size()] = NULL;
// Make sure we don't leak any FDs to the child process by marking all FDs
// as close-on-exec.
SetAllFDsToCloseOnExec();
EnvironmentArray vars = BuildEnvironmentArray(options.env_map);
posix_spawn_file_actions_t file_actions;
if (posix_spawn_file_actions_init(&file_actions) != 0) {
return false;
}
// Turn fds_to_remap array into a set of dup2 calls.
for (const auto& fd_map : options.fds_to_remap) {
int src_fd = fd_map.first;
int dest_fd = fd_map.second;
if (src_fd == dest_fd) {
int flags = fcntl(src_fd, F_GETFD);
if (flags != -1) {
fcntl(src_fd, F_SETFD, flags & ~FD_CLOEXEC);
}
} else {
if (posix_spawn_file_actions_adddup2(&file_actions, src_fd, dest_fd) != 0) {
posix_spawn_file_actions_destroy(&file_actions);
return false;
}
}
}
pid_t pid = 0;
int spawn_succeeded = (posix_spawnp(&pid,
argv_copy[0],
&file_actions,
NULL,
argv_copy,
vars.get()) == 0);
posix_spawn_file_actions_destroy(&file_actions);
bool process_handle_valid = pid > 0;
if (!spawn_succeeded || !process_handle_valid) {
retval = false;
} else {
gProcessLog.print("==> process %d launched child process %d\n",
GetCurrentProcId(), pid);
if (options.wait)
HANDLE_EINTR(waitpid(pid, 0, 0));
if (process_handle)
*process_handle = pid;
}
return retval;
}
bool LaunchApp(const CommandLine& cl,
const LaunchOptions& options,
ProcessHandle* process_handle) {
return LaunchApp(cl.argv(), options, process_handle);
}
} // namespace base

View File

@ -16,6 +16,9 @@
#include "mozilla/ipc/FileDescriptorShuffle.h"
#include "mozilla/UniquePtr.h"
// WARNING: despite the name, this file is also used on the BSDs and
// Solaris (basically, Unixes that aren't Mac OS), not just Linux.
namespace {
static mozilla::EnvironmentLog gProcessLog("MOZ_PROCESS_LOG");
@ -36,12 +39,16 @@ bool LaunchApp(const std::vector<std::string>& argv,
return false;
}
#ifdef OS_LINUX
pid_t pid = options.fork_delegate ? options.fork_delegate->Fork() : fork();
// WARNING: if pid == 0, only async signal safe operations are permitted from
// here until exec or _exit.
//
// Specifically, heap allocation is not safe: the sandbox's fork substitute
// won't run the pthread_atfork handlers that fix up the malloc locks.
#else
pid_t pid = fork();
#endif
if (pid < 0)
return false;