Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: chrome/app/nacl_fork_delegate_linux.cc

Issue 21031004: Move zygote related files to components/nacl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move nacl_fork_delegate_linux.h to components/nacl/zygote Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/app/nacl_fork_delegate_linux.h ('k') | chrome/nacl.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #include "chrome/app/nacl_fork_delegate_linux.h"
6
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <sys/resource.h>
10 #include <sys/socket.h>
11
12 #include <set>
13
14 #include "base/basictypes.h"
15 #include "base/command_line.h"
16 #include "base/cpu.h"
17 #include "base/files/file_path.h"
18 #include "base/logging.h"
19 #include "base/path_service.h"
20 #include "base/posix/eintr_wrapper.h"
21 #include "base/posix/unix_domain_socket_linux.h"
22 #include "base/process/launch.h"
23 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "components/nacl/common/nacl_helper_linux.h"
26 #include "components/nacl/common/nacl_paths.h"
27 #include "components/nacl/common/nacl_switches.h"
28
29 namespace {
30
31 // Note these need to match up with their counterparts in nacl_helper_linux.c
32 // and nacl_helper_bootstrap_linux.c.
33 const char kNaClHelperReservedAtZero[] =
34 "--reserved_at_zero=0xXXXXXXXXXXXXXXXX";
35 const char kNaClHelperRDebug[] = "--r_debug=0xXXXXXXXXXXXXXXXX";
36
37 #if defined(ARCH_CPU_X86)
38 bool NonZeroSegmentBaseIsSlow() {
39 base::CPU cpuid;
40 // Using a non-zero segment base is known to be very slow on Intel
41 // Atom CPUs. See "Segmentation-based Memory Protection Mechanism
42 // on Intel Atom Microarchitecture: Coding Optimizations" (Leonardo
43 // Potenza, Intel).
44 //
45 // The following list of CPU model numbers is taken from:
46 // "Intel 64 and IA-32 Architectures Software Developer's Manual"
47 // (http://download.intel.com/products/processor/manual/325462.pdf),
48 // "Table 35-1. CPUID Signature Values of DisplayFamily_DisplayModel"
49 // (Volume 3C, 35-1), which contains:
50 // "06_36H - Intel Atom S Processor Family
51 // 06_1CH, 06_26H, 06_27H, 06_35, 06_36 - Intel Atom Processor Family"
52 if (cpuid.family() == 6) {
53 switch (cpuid.model()) {
54 case 0x1c:
55 case 0x26:
56 case 0x27:
57 case 0x35:
58 case 0x36:
59 return true;
60 }
61 }
62 return false;
63 }
64 #endif
65
66 }
67
68 NaClForkDelegate::NaClForkDelegate()
69 : status_(kNaClHelperUnused),
70 fd_(-1) {}
71
72 void NaClForkDelegate::Init(const int sandboxdesc) {
73 VLOG(1) << "NaClForkDelegate::Init()";
74 int fds[2];
75
76 // Confirm a hard-wired assumption.
77 // The NaCl constant is from chrome/nacl/nacl_linux_helper.h
78 DCHECK(kNaClSandboxDescriptor == sandboxdesc);
79
80 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
81 base::FileHandleMappingVector fds_to_map;
82 fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor));
83 fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor));
84
85 // Using nacl_helper_bootstrap is not necessary on x86-64 because
86 // NaCl's x86-64 sandbox is not zero-address-based. Starting
87 // nacl_helper through nacl_helper_bootstrap works on x86-64, but it
88 // leaves nacl_helper_bootstrap mapped at a fixed address at the
89 // bottom of the address space, which is undesirable because it
90 // effectively defeats ASLR.
91 #if defined(ARCH_CPU_X86_64)
92 bool kUseNaClBootstrap = false;
93 #elif defined(ARCH_CPU_X86)
94 // Performance vs. security trade-off: We prefer using a
95 // non-zero-address-based sandbox on x86-32 because it provides some
96 // ASLR and so is more secure. However, on Atom CPUs, using a
97 // non-zero segment base is very slow, so we use a zero-based
98 // sandbox on those.
99 bool kUseNaClBootstrap = NonZeroSegmentBaseIsSlow();
100 #else
101 bool kUseNaClBootstrap = true;
102 #endif
103
104 status_ = kNaClHelperUnused;
105 base::FilePath helper_exe;
106 base::FilePath helper_bootstrap_exe;
107 if (!PathService::Get(nacl::FILE_NACL_HELPER, &helper_exe)) {
108 status_ = kNaClHelperMissing;
109 } else if (kUseNaClBootstrap &&
110 !PathService::Get(nacl::FILE_NACL_HELPER_BOOTSTRAP,
111 &helper_bootstrap_exe)) {
112 status_ = kNaClHelperBootstrapMissing;
113 } else if (RunningOnValgrind()) {
114 status_ = kNaClHelperValgrind;
115 } else {
116 CommandLine cmd_line(CommandLine::NO_PROGRAM);
117 if (kUseNaClBootstrap) {
118 cmd_line.SetProgram(helper_bootstrap_exe);
119 cmd_line.AppendArgPath(helper_exe);
120 cmd_line.AppendArgNative(kNaClHelperReservedAtZero);
121 cmd_line.AppendArgNative(kNaClHelperRDebug);
122 } else {
123 cmd_line.SetProgram(helper_exe);
124 }
125 base::LaunchOptions options;
126 options.fds_to_remap = &fds_to_map;
127 options.clone_flags = CLONE_FS | SIGCHLD;
128
129 // The NaCl processes spawned may need to exceed the ambient soft limit
130 // on RLIMIT_AS to allocate the untrusted address space and its guard
131 // regions. The nacl_helper itself cannot just raise its own limit,
132 // because the existing limit may prevent the initial exec of
133 // nacl_helper_bootstrap from succeeding, with its large address space
134 // reservation.
135 std::set<int> max_these_limits;
136 max_these_limits.insert(RLIMIT_AS);
137 options.maximize_rlimits = &max_these_limits;
138
139 if (!base::LaunchProcess(cmd_line.argv(), options, NULL))
140 status_ = kNaClHelperLaunchFailed;
141 // parent and error cases are handled below
142 }
143 if (HANDLE_EINTR(close(fds[1])) != 0)
144 LOG(ERROR) << "close(fds[1]) failed";
145 if (status_ == kNaClHelperUnused) {
146 const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck);
147 char buf[kExpectedLength];
148
149 // Wait for ack from nacl_helper, indicating it is ready to help
150 const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
151 if (nread == kExpectedLength &&
152 memcmp(buf, kNaClHelperStartupAck, nread) == 0) {
153 // all is well
154 status_ = kNaClHelperSuccess;
155 fd_ = fds[0];
156 return;
157 }
158
159 status_ = kNaClHelperAckFailed;
160 LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)";
161 }
162 // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
163 // becomes the default.
164 fd_ = -1;
165 if (HANDLE_EINTR(close(fds[0])) != 0)
166 LOG(ERROR) << "close(fds[0]) failed";
167 }
168
169 void NaClForkDelegate::InitialUMA(std::string* uma_name,
170 int* uma_sample,
171 int* uma_boundary_value) {
172 *uma_name = "NaCl.Client.Helper.InitState";
173 *uma_sample = status_;
174 *uma_boundary_value = kNaClHelperStatusBoundary;
175 }
176
177 NaClForkDelegate::~NaClForkDelegate() {
178 // side effect of close: delegate process will terminate
179 if (status_ == kNaClHelperSuccess) {
180 if (HANDLE_EINTR(close(fd_)) != 0)
181 LOG(ERROR) << "close(fd_) failed";
182 }
183 }
184
185 bool NaClForkDelegate::CanHelp(const std::string& process_type,
186 std::string* uma_name,
187 int* uma_sample,
188 int* uma_boundary_value) {
189 if (process_type != switches::kNaClLoaderProcess)
190 return false;
191 *uma_name = "NaCl.Client.Helper.StateOnFork";
192 *uma_sample = status_;
193 *uma_boundary_value = kNaClHelperStatusBoundary;
194 return status_ == kNaClHelperSuccess;
195 }
196
197 pid_t NaClForkDelegate::Fork(const std::vector<int>& fds) {
198 base::ProcessId naclchild;
199 VLOG(1) << "NaClForkDelegate::Fork";
200
201 DCHECK(fds.size() == kNaClParentFDIndex + 1);
202 if (!UnixDomainSocket::SendMsg(fd_, kNaClForkRequest,
203 strlen(kNaClForkRequest), fds)) {
204 LOG(ERROR) << "NaClForkDelegate::Fork: SendMsg failed";
205 return -1;
206 }
207 int nread = HANDLE_EINTR(read(fd_, &naclchild, sizeof(naclchild)));
208 if (nread != sizeof(naclchild)) {
209 LOG(ERROR) << "NaClForkDelegate::Fork: read failed";
210 return -1;
211 }
212 VLOG(1) << "nacl_child is " << naclchild << " (" << nread << " bytes)";
213 return naclchild;
214 }
215
216 bool NaClForkDelegate::AckChild(const int fd,
217 const std::string& channel_switch) {
218 int nwritten = HANDLE_EINTR(write(fd, channel_switch.c_str(),
219 channel_switch.length()));
220 if (nwritten != static_cast<int>(channel_switch.length())) {
221 return false;
222 }
223 return true;
224 }
OLDNEW
« no previous file with comments | « chrome/app/nacl_fork_delegate_linux.h ('k') | chrome/nacl.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698