Return backed up TemplateURL on default search change
[chromium-blink-merge.git] / chrome / app / nacl_fork_delegate_linux.cc
blob937f690a647775f67a768e738f3eec744eed18fe
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/app/nacl_fork_delegate_linux.h"
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <sys/resource.h>
10 #include <sys/socket.h>
12 #include "base/basictypes.h"
13 #include "base/command_line.h"
14 #include "base/eintr_wrapper.h"
15 #include "base/logging.h"
16 #include "base/file_path.h"
17 #include "base/path_service.h"
18 #include "base/process_util.h"
19 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
20 #include "content/common/unix_domain_socket_posix.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/nacl_helper_linux.h"
25 NaClForkDelegate::NaClForkDelegate()
26 : status_(kNaClHelperUnused),
27 sandboxed_(false),
28 fd_(-1) {}
31 * Note these need to match up with their counterparts in nacl_helper_linux.c
32 * and nacl_helper_bootstrap_linux.c.
34 const char kNaClHelperAtZero[] = "--at-zero";
35 const char kNaClHelperRDebug[] = "--r_debug=0xXXXXXXXXXXXXXXXX";
37 void NaClForkDelegate::Init(const bool sandboxed,
38 const int browserdesc,
39 const int sandboxdesc) {
40 VLOG(1) << "NaClForkDelegate::Init()";
41 int fds[2];
43 sandboxed_ = sandboxed;
44 // Confirm a couple hard-wired assumptions.
45 // The NaCl constants are from chrome/nacl/nacl_linux_helper.h
46 DCHECK(kNaClBrowserDescriptor == browserdesc);
47 DCHECK(kNaClSandboxDescriptor == sandboxdesc);
49 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
50 base::file_handle_mapping_vector fds_to_map;
51 fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor));
52 fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor));
54 status_ = kNaClHelperUnused;
55 FilePath helper_exe;
56 FilePath helper_bootstrap_exe;
57 if (!PathService::Get(chrome::FILE_NACL_HELPER, &helper_exe)) {
58 status_ = kNaClHelperMissing;
59 } else if (!PathService::Get(chrome::FILE_NACL_HELPER_BOOTSTRAP,
60 &helper_bootstrap_exe)) {
61 status_ = kNaClHelperBootstrapMissing;
62 } else if (RunningOnValgrind()) {
63 status_ = kNaClHelperValgrind;
64 } else {
65 CommandLine cmd_line(helper_bootstrap_exe);
66 cmd_line.AppendArgPath(helper_exe);
67 cmd_line.AppendArgNative(kNaClHelperAtZero);
68 cmd_line.AppendArgNative(kNaClHelperRDebug);
69 base::LaunchOptions options;
70 options.fds_to_remap = &fds_to_map;
71 options.clone_flags = CLONE_FS | SIGCHLD;
73 // The NaCl processes spawned may need to exceed the ambient soft limit
74 // on RLIMIT_AS to allocate the untrusted address space and its guard
75 // regions. The nacl_helper itself cannot just raise its own limit,
76 // because the existing limit may prevent the initial exec of
77 // nacl_helper_bootstrap from succeeding, with its large address space
78 // reservation.
79 std::set<int> max_these_limits;
80 max_these_limits.insert(RLIMIT_AS);
81 options.maximize_rlimits = &max_these_limits;
83 if (!base::LaunchProcess(cmd_line.argv(), options, NULL))
84 status_ = kNaClHelperLaunchFailed;
85 // parent and error cases are handled below
87 if (HANDLE_EINTR(close(fds[1])) != 0)
88 LOG(ERROR) << "close(fds[1]) failed";
89 if (status_ == kNaClHelperUnused) {
90 const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck);
91 char buf[kExpectedLength];
93 // Wait for ack from nacl_helper, indicating it is ready to help
94 const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
95 if (nread == kExpectedLength &&
96 memcmp(buf, kNaClHelperStartupAck, nread) == 0) {
97 // all is well
98 status_ = kNaClHelperSuccess;
99 fd_ = fds[0];
100 return;
103 status_ = kNaClHelperAckFailed;
104 LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)";
106 // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
107 // becomes the default.
108 fd_ = -1;
109 if (HANDLE_EINTR(close(fds[0])) != 0)
110 LOG(ERROR) << "close(fds[0]) failed";
113 void NaClForkDelegate::InitialUMA(std::string* uma_name,
114 int* uma_sample,
115 int* uma_boundary_value) {
116 *uma_name = "NaCl.Client.Helper.InitState";
117 *uma_sample = status_;
118 *uma_boundary_value = kNaClHelperStatusBoundary;
121 NaClForkDelegate::~NaClForkDelegate() {
122 // side effect of close: delegate process will terminate
123 if (status_ == kNaClHelperSuccess) {
124 if (HANDLE_EINTR(close(fd_)) != 0)
125 LOG(ERROR) << "close(fd_) failed";
129 bool NaClForkDelegate::CanHelp(const std::string& process_type,
130 std::string* uma_name,
131 int* uma_sample,
132 int* uma_boundary_value) {
133 if (process_type != switches::kNaClLoaderProcess)
134 return false;
135 *uma_name = "NaCl.Client.Helper.StateOnFork";
136 *uma_sample = status_;
137 *uma_boundary_value = kNaClHelperStatusBoundary;
138 return status_ == kNaClHelperSuccess;
141 pid_t NaClForkDelegate::Fork(const std::vector<int>& fds) {
142 base::ProcessId naclchild;
143 VLOG(1) << "NaClForkDelegate::Fork";
145 DCHECK(fds.size() == kNaClParentFDIndex + 1);
146 if (!UnixDomainSocket::SendMsg(fd_, kNaClForkRequest,
147 strlen(kNaClForkRequest), fds)) {
148 LOG(ERROR) << "NaClForkDelegate::Fork: SendMsg failed";
149 return -1;
151 int nread = HANDLE_EINTR(read(fd_, &naclchild, sizeof(naclchild)));
152 if (nread != sizeof(naclchild)) {
153 LOG(ERROR) << "NaClForkDelegate::Fork: read failed";
154 return -1;
156 VLOG(1) << "nacl_child is " << naclchild << " (" << nread << " bytes)";
157 return naclchild;
160 bool NaClForkDelegate::AckChild(const int fd,
161 const std::string& channel_switch) {
162 int nwritten = HANDLE_EINTR(write(fd, channel_switch.c_str(),
163 channel_switch.length()));
164 if (nwritten != static_cast<int>(channel_switch.length())) {
165 return false;
167 return true;