#include "base/base_switches.h"
#include "base/bind.h"
#include "base/command_line.h"
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
using content::ChildProcessHost;
using ppapi::proxy::SerializedHandle;
-#if defined(OS_WIN)
+namespace nacl {
+#if defined(OS_WIN)
namespace {
// Looks for the largest contiguous unallocated region of address
} // namespace
-namespace nacl {
-
// Allocates |size| bytes of address space in the given process at a
// randomised address.
void* AllocateAddressSpaceASLR(base::ProcessHandle process, size_t size) {
MEM_RESERVE, PAGE_NOACCESS);
}
-} // namespace nacl
-
-#endif // defined(OS_WIN)
-
namespace {
-#if defined(OS_WIN)
bool RunningOnWOW64() {
return (base::win::OSInfo::GetInstance()->wow64_status() ==
base::win::OSInfo::WOW64_ENABLED);
}
-#endif
+
+} // namespace
+
+#endif // defined(OS_WIN)
+
+namespace {
// NOTE: changes to this class need to be reviewed by the security team.
class NaClSandboxedProcessLauncherDelegate
} // namespace
-namespace nacl {
-
-struct NaClProcessHost::NaClInternal {
- NaClHandle socket_for_renderer;
- NaClHandle socket_for_sel_ldr;
-
- NaClInternal()
- : socket_for_renderer(NACL_INVALID_HANDLE),
- socket_for_sel_ldr(NACL_INVALID_HANDLE) { }
-};
-
-// -----------------------------------------------------------------------------
-
unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ =
ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds;
#if defined(OS_WIN)
debug_exception_handler_requested_(false),
#endif
- internal_(new NaClInternal()),
- weak_factory_(this),
uses_irt_(uses_irt),
uses_nonsfi_mode_(uses_nonsfi_mode),
enable_debug_stub_(false),
enable_crash_throttling_(enable_crash_throttling),
off_the_record_(off_the_record),
profile_directory_(profile_directory),
- render_view_id_(render_view_id) {
+ render_view_id_(render_view_id),
+ weak_factory_(this) {
process_.reset(content::BrowserChildProcessHost::Create(
PROCESS_TYPE_NACL_LOADER, this));
NaClBrowser::GetInstance()->OnProcessEnd(process_->GetData().id);
}
- if (internal_->socket_for_renderer != NACL_INVALID_HANDLE) {
- if (NaClClose(internal_->socket_for_renderer) != 0) {
- NOTREACHED() << "NaClClose() failed";
- }
- }
-
- if (internal_->socket_for_sel_ldr != NACL_INVALID_HANDLE) {
- if (NaClClose(internal_->socket_for_sel_ldr) != 0) {
- NOTREACHED() << "NaClClose() failed";
- }
- }
-
if (reply_msg_) {
// The process failed to launch for some reason.
// Don't keep the renderer hanging.
delete this;
return;
}
- internal_->socket_for_renderer = pair[0];
- internal_->socket_for_sel_ldr = pair[1];
+ socket_for_renderer_ = base::File(pair[0]);
+ socket_for_sel_ldr_ = base::File(pair[1]);
SetCloseOnExec(pair[0]);
SetCloseOnExec(pair[1]);
}
+ // Create a shared memory region that the renderer and plugin share for
+ // reporting crash information.
+ crash_info_shmem_.CreateAnonymous(kNaClCrashInfoShmemSize);
+
// Launch the process
if (!LaunchSelLdr()) {
delete this;
OnSetKnownToValidate)
IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_ResolveFileToken,
OnResolveFileToken)
+ IPC_MESSAGE_HANDLER(NaClProcessMsg_ResolveFileTokenAsync,
+ OnResolveFileTokenAsync)
+
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
NaClProcessMsg_AttachDebugExceptionHandler,
// Copy the handle into the renderer process.
HANDLE handle_in_renderer;
if (!DuplicateHandle(base::GetCurrentProcessHandle(),
- reinterpret_cast<HANDLE>(
- internal_->socket_for_renderer),
+ socket_for_renderer_.TakePlatformFile(),
nacl_host_message_filter_->PeerHandle(),
&handle_in_renderer,
0, // Unused given DUPLICATE_SAME_ACCESS.
// No need to dup the imc_handle - we don't pass it anywhere else so
// it cannot be closed.
FileDescriptor imc_handle;
- imc_handle.fd = internal_->socket_for_renderer;
+ imc_handle.fd = socket_for_renderer_.TakePlatformFile();
imc_handle.auto_close = true;
imc_handle_for_renderer = imc_handle;
#endif
const ChildProcessData& data = process_->GetData();
+ base::SharedMemoryHandle crash_info_shmem_renderer_handle;
+ if (!crash_info_shmem_.ShareToProcess(nacl_host_message_filter_->PeerHandle(),
+ &crash_info_shmem_renderer_handle)) {
+ SendErrorToRenderer("ShareToProcess() failed");
+ return false;
+ }
+
SendMessageToRenderer(
NaClLaunchResult(imc_handle_for_renderer,
ppapi_channel_handle,
trusted_channel_handle,
manifest_service_channel_handle,
base::GetProcId(data.handle),
- data.id),
+ data.id,
+ crash_info_shmem_renderer_handle),
std::string() /* error_message */);
- internal_->socket_for_renderer = NACL_INVALID_HANDLE;
+
+ // Now that the crash information shmem handles have been shared with the
+ // plugin and the renderer, the browser can close its handle.
+ crash_info_shmem_.Close();
return true;
}
void NaClProcessHost::SendMessageToRenderer(
const NaClLaunchResult& result,
const std::string& error_message) {
- DCHECK(nacl_host_message_filter_);
+ DCHECK(nacl_host_message_filter_.get());
DCHECK(reply_msg_);
- if (nacl_host_message_filter_ != NULL && reply_msg_ != NULL) {
+ if (nacl_host_message_filter_.get() != NULL && reply_msg_ != NULL) {
NaClHostMsg_LaunchNaCl::WriteReplyParams(
reply_msg_, result, error_message);
nacl_host_message_filter_->Send(reply_msg_);
#if defined(OS_LINUX)
// In non-SFI mode, we do not use SRPC. Make sure that the socketpair is
// not created.
- DCHECK_EQ(internal_->socket_for_sel_ldr, NACL_INVALID_HANDLE);
+ DCHECK(!socket_for_sel_ldr_.IsValid());
#endif
} else {
params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled();
const ChildProcessData& data = process_->GetData();
if (!ShareHandleToSelLdr(data.handle,
- internal_->socket_for_sel_ldr, true,
+ socket_for_sel_ldr_.TakePlatformFile(),
+ true,
¶ms.handles)) {
return false;
}
#endif
}
- if (!uses_nonsfi_mode_) {
- internal_->socket_for_sel_ldr = NACL_INVALID_HANDLE;
- }
-
params.nexe_file = IPC::TakeFileHandleForProcess(nexe_file_.Pass(),
process_->GetData().handle);
+ if (!crash_info_shmem_.ShareToProcess(process_->GetData().handle,
+ ¶ms.crash_info_shmem_handle)) {
+ DLOG(ERROR) << "Failed to ShareToProcess() a shared memory buffer";
+ return false;
+ }
process_->Send(new NaClProcessMsg_Start(params));
return true;
signature, off_the_record_);
}
-void NaClProcessHost::FileResolved(
- const base::FilePath& file_path,
- IPC::Message* reply_msg,
- base::File file) {
- if (file.IsValid()) {
- IPC::PlatformFileForTransit handle = IPC::TakeFileHandleForProcess(
- file.Pass(),
- process_->GetData().handle);
- NaClProcessMsg_ResolveFileToken::WriteReplyParams(
- reply_msg,
- handle,
- file_path);
- } else {
- NaClProcessMsg_ResolveFileToken::WriteReplyParams(
- reply_msg,
- IPC::InvalidPlatformFileForTransit(),
- base::FilePath());
- }
- Send(reply_msg);
-}
-
void NaClProcessHost::OnResolveFileToken(uint64 file_token_lo,
uint64 file_token_hi,
IPC::Message* reply_msg) {
}
}
+void NaClProcessHost::OnResolveFileTokenAsync(uint64 file_token_lo,
+ uint64 file_token_hi) {
+ // See the comment at OnResolveFileToken() for details of the file path cache
+ // behavior.
+ CHECK(!uses_nonsfi_mode_);
+ base::FilePath file_path;
+ if (!NaClBrowser::GetInstance()->GetFilePath(
+ file_token_lo, file_token_hi, &file_path)) {
+ Send(new NaClProcessMsg_ResolveFileTokenAsyncReply(
+ file_token_lo,
+ file_token_hi,
+ IPC::PlatformFileForTransit(),
+ base::FilePath()));
+ return;
+ }
+
+ // Open the file.
+ if (!base::PostTaskAndReplyWithResult(
+ content::BrowserThread::GetBlockingPool(),
+ FROM_HERE,
+ base::Bind(OpenNaClReadExecImpl, file_path, true /* is_executable */),
+ base::Bind(&NaClProcessHost::FileResolvedAsync,
+ weak_factory_.GetWeakPtr(),
+ file_token_lo,
+ file_token_hi,
+ file_path))) {
+ Send(new NaClProcessMsg_ResolveFileTokenAsyncReply(
+ file_token_lo,
+ file_token_hi,
+ IPC::PlatformFileForTransit(),
+ base::FilePath()));
+ }
+}
+
+void NaClProcessHost::FileResolved(
+ const base::FilePath& file_path,
+ IPC::Message* reply_msg,
+ base::File file) {
+ if (file.IsValid()) {
+ IPC::PlatformFileForTransit handle = IPC::TakeFileHandleForProcess(
+ file.Pass(),
+ process_->GetData().handle);
+ NaClProcessMsg_ResolveFileToken::WriteReplyParams(
+ reply_msg,
+ handle,
+ file_path);
+ } else {
+ NaClProcessMsg_ResolveFileToken::WriteReplyParams(
+ reply_msg,
+ IPC::InvalidPlatformFileForTransit(),
+ base::FilePath());
+ }
+ Send(reply_msg);
+}
+
+void NaClProcessHost::FileResolvedAsync(
+ uint64_t file_token_lo,
+ uint64_t file_token_hi,
+ const base::FilePath& file_path,
+ base::File file) {
+ base::FilePath out_file_path;
+ IPC::PlatformFileForTransit out_handle;
+ if (file.IsValid()) {
+ out_file_path = file_path;
+ out_handle = IPC::TakeFileHandleForProcess(
+ file.Pass(),
+ process_->GetData().handle);
+ } else {
+ out_handle = IPC::InvalidPlatformFileForTransit();
+ }
+ Send(new NaClProcessMsg_ResolveFileTokenAsyncReply(
+ file_token_lo,
+ file_token_hi,
+ out_handle,
+ out_file_path));
+}
+
#if defined(OS_WIN)
void NaClProcessHost::OnAttachDebugExceptionHandler(const std::string& info,
IPC::Message* reply_msg) {