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

Side by Side Diff: components/nacl/zygote/nacl_fork_delegate_linux.cc

Issue 279693002: Split NaCl SFI and non-SFI helpers into separate processes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Oops, forgot to "git add" new files Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/nacl/zygote/nacl_fork_delegate_linux.h" 5 #include "components/nacl/zygote/nacl_fork_delegate_linux.h"
6 6
7 #include <signal.h> 7 #include <signal.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <sys/resource.h> 9 #include <sys/resource.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
11 11
12 #include <set> 12 #include <set>
13 13
14 #include "base/basictypes.h" 14 #include "base/basictypes.h"
15 #include "base/command_line.h" 15 #include "base/command_line.h"
16 #include "base/cpu.h" 16 #include "base/cpu.h"
17 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
18 #include "base/files/scoped_file.h" 18 #include "base/files/scoped_file.h"
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/scoped_vector.h" 21 #include "base/memory/scoped_vector.h"
22 #include "base/path_service.h" 22 #include "base/path_service.h"
23 #include "base/pickle.h" 23 #include "base/pickle.h"
24 #include "base/posix/eintr_wrapper.h" 24 #include "base/posix/eintr_wrapper.h"
25 #include "base/posix/global_descriptors.h" 25 #include "base/posix/global_descriptors.h"
26 #include "base/posix/unix_domain_socket_linux.h" 26 #include "base/posix/unix_domain_socket_linux.h"
27 #include "base/process/kill.h" 27 #include "base/process/kill.h"
28 #include "base/process/launch.h" 28 #include "base/process/launch.h"
29 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 29 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
30 #include "build/build_config.h"
30 #include "components/nacl/common/nacl_paths.h" 31 #include "components/nacl/common/nacl_paths.h"
31 #include "components/nacl/common/nacl_switches.h" 32 #include "components/nacl/common/nacl_switches.h"
32 #include "components/nacl/loader/nacl_helper_linux.h" 33 #include "components/nacl/loader/nacl_helper_linux.h"
33 #include "content/public/common/content_descriptors.h" 34 #include "content/public/common/content_descriptors.h"
34 #include "content/public/common/content_switches.h" 35 #include "content/public/common/content_switches.h"
35 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" 36 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
36 37
37 namespace { 38 namespace {
38 39
39 // Note these need to match up with their counterparts in nacl_helper_linux.c 40 // Note these need to match up with their counterparts in nacl_helper_linux.c
40 // and nacl_helper_bootstrap_linux.c. 41 // and nacl_helper_bootstrap_linux.c.
41 const char kNaClHelperReservedAtZero[] = 42 const char kNaClHelperReservedAtZero[] =
42 "--reserved_at_zero=0xXXXXXXXXXXXXXXXX"; 43 "--reserved_at_zero=0xXXXXXXXXXXXXXXXX";
43 const char kNaClHelperRDebug[] = "--r_debug=0xXXXXXXXXXXXXXXXX"; 44 const char kNaClHelperRDebug[] = "--r_debug=0xXXXXXXXXXXXXXXXX";
44 45
46 // We only enable non-SFI mode by default on ChromeOS/ARMEL.
47 #if defined(OS_CHROMEOS) || defined(ARCH_CPU_ARMEL)
Mark Seaborn 2014/05/10 00:10:40 I think Julien wanted to de-duplicate this conditi
jln (very slow on Chromium) 2014/05/10 00:44:50 We could even make it a function that also queries
mdempsky 2014/05/10 01:58:52 Looking at Elijah's pending CL, it doesn't look st
mdempsky 2014/05/12 22:38:30 Done: I've moved the IsNonSFIModeEnabled() functio
48 const bool kEnableNonSFIByDefault = true;
49 #else
50 const bool kEnableNonSFIByDefault = false;
51 #endif
52
45 #if defined(ARCH_CPU_X86) 53 #if defined(ARCH_CPU_X86)
46 bool NonZeroSegmentBaseIsSlow() { 54 bool NonZeroSegmentBaseIsSlow() {
47 base::CPU cpuid; 55 base::CPU cpuid;
48 // Using a non-zero segment base is known to be very slow on Intel 56 // Using a non-zero segment base is known to be very slow on Intel
49 // Atom CPUs. See "Segmentation-based Memory Protection Mechanism 57 // Atom CPUs. See "Segmentation-based Memory Protection Mechanism
50 // on Intel Atom Microarchitecture: Coding Optimizations" (Leonardo 58 // on Intel Atom Microarchitecture: Coding Optimizations" (Leonardo
51 // Potenza, Intel). 59 // Potenza, Intel).
52 // 60 //
53 // The following list of CPU model numbers is taken from: 61 // The following list of CPU model numbers is taken from:
54 // "Intel 64 and IA-32 Architectures Software Developer's Manual" 62 // "Intel 64 and IA-32 Architectures Software Developer's Manual"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 if (msg_len <= 0) { 109 if (msg_len <= 0) {
102 LOG(ERROR) << "SendIPCRequestAndReadReply: RecvMsg failed"; 110 LOG(ERROR) << "SendIPCRequestAndReadReply: RecvMsg failed";
103 return false; 111 return false;
104 } 112 }
105 *reply_size = msg_len; 113 *reply_size = msg_len;
106 return true; 114 return true;
107 } 115 }
108 116
109 } // namespace. 117 } // namespace.
110 118
111 NaClForkDelegate::NaClForkDelegate() 119 NaClForkDelegate::NaClForkDelegate(bool nonsfi_mode)
112 : status_(kNaClHelperUnused), 120 : nonsfi_mode_(nonsfi_mode), status_(kNaClHelperUnused), fd_(-1) {
113 fd_(-1) {} 121 }
114 122
115 void NaClForkDelegate::Init(const int sandboxdesc, 123 void NaClForkDelegate::Init(const int sandboxdesc,
116 const bool enable_layer1_sandbox) { 124 const bool enable_layer1_sandbox) {
117 VLOG(1) << "NaClForkDelegate::Init()"; 125 VLOG(1) << "NaClForkDelegate::Init()";
118 int fds[2]; 126
127 if (nonsfi_mode_) {
128 // Only launch the non-SFI helper process if we support non-SFI by default
129 // for this build target, or it's explicitly enabled via the command line.
130 const bool enable_nonsfi = kEnableNonSFIByDefault ||
131 CommandLine::ForCurrentProcess()->HasSwitch(
132 switches::kEnableNaClNonSfiMode);
133 if (!enable_nonsfi) {
134 return;
135 }
136 }
119 137
120 scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client( 138 scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client(
121 sandbox::SetuidSandboxClient::Create()); 139 sandbox::SetuidSandboxClient::Create());
122 140
123 // For communications between the NaCl loader process and 141 // For communications between the NaCl loader process and
124 // the SUID sandbox. 142 // the SUID sandbox.
125 int nacl_sandbox_descriptor = 143 int nacl_sandbox_descriptor =
126 base::GlobalDescriptors::kBaseDescriptor + kSandboxIPCChannel; 144 base::GlobalDescriptors::kBaseDescriptor + kSandboxIPCChannel;
127 // Confirm a hard-wired assumption. 145 // Confirm a hard-wired assumption.
128 DCHECK_EQ(sandboxdesc, nacl_sandbox_descriptor); 146 DCHECK_EQ(sandboxdesc, nacl_sandbox_descriptor);
129 147
130 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); 148 int fds[2];
149 PCHECK(0 == socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds));
131 base::FileHandleMappingVector fds_to_map; 150 base::FileHandleMappingVector fds_to_map;
132 fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor)); 151 fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor));
133 fds_to_map.push_back(std::make_pair(sandboxdesc, nacl_sandbox_descriptor)); 152 fds_to_map.push_back(std::make_pair(sandboxdesc, nacl_sandbox_descriptor));
134 153
135 // Using nacl_helper_bootstrap is not necessary on x86-64 because 154 // Using nacl_helper_bootstrap is not necessary on x86-64 because
136 // NaCl's x86-64 sandbox is not zero-address-based. Starting 155 // NaCl's x86-64 sandbox is not zero-address-based. Starting
137 // nacl_helper through nacl_helper_bootstrap works on x86-64, but it 156 // nacl_helper through nacl_helper_bootstrap works on x86-64, but it
138 // leaves nacl_helper_bootstrap mapped at a fixed address at the 157 // leaves nacl_helper_bootstrap mapped at a fixed address at the
139 // bottom of the address space, which is undesirable because it 158 // bottom of the address space, which is undesirable because it
140 // effectively defeats ASLR. 159 // effectively defeats ASLR.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper 274 // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
256 // becomes the default. 275 // becomes the default.
257 fd_ = -1; 276 fd_ = -1;
258 if (IGNORE_EINTR(close(fds[0])) != 0) 277 if (IGNORE_EINTR(close(fds[0])) != 0)
259 LOG(ERROR) << "close(fds[0]) failed"; 278 LOG(ERROR) << "close(fds[0]) failed";
260 } 279 }
261 280
262 void NaClForkDelegate::InitialUMA(std::string* uma_name, 281 void NaClForkDelegate::InitialUMA(std::string* uma_name,
263 int* uma_sample, 282 int* uma_sample,
264 int* uma_boundary_value) { 283 int* uma_boundary_value) {
265 *uma_name = "NaCl.Client.Helper.InitState"; 284 *uma_name = nonsfi_mode_ ? "NaCl.Client.HelperNonSFI.InitState"
285 : "NaCl.Client.Helper.InitState";
266 *uma_sample = status_; 286 *uma_sample = status_;
267 *uma_boundary_value = kNaClHelperStatusBoundary; 287 *uma_boundary_value = kNaClHelperStatusBoundary;
268 } 288 }
269 289
270 NaClForkDelegate::~NaClForkDelegate() { 290 NaClForkDelegate::~NaClForkDelegate() {
271 // side effect of close: delegate process will terminate 291 // side effect of close: delegate process will terminate
272 if (status_ == kNaClHelperSuccess) { 292 if (status_ == kNaClHelperSuccess) {
273 if (IGNORE_EINTR(close(fd_)) != 0) 293 if (IGNORE_EINTR(close(fd_)) != 0)
274 LOG(ERROR) << "close(fd_) failed"; 294 LOG(ERROR) << "close(fd_) failed";
275 } 295 }
276 } 296 }
277 297
278 bool NaClForkDelegate::CanHelp(const std::string& process_type, 298 bool NaClForkDelegate::CanHelp(const std::string& process_type,
279 std::string* uma_name, 299 std::string* uma_name,
280 int* uma_sample, 300 int* uma_sample,
281 int* uma_boundary_value) { 301 int* uma_boundary_value) {
282 if (process_type != switches::kNaClLoaderProcess && 302 // We can only help with a specific process type depending on nonsfi_mode_.
283 process_type != switches::kNaClLoaderNonSfiProcess) 303 const char* helpable_process_type = nonsfi_mode_
304 ? switches::kNaClLoaderNonSfiProcess
305 : switches::kNaClLoaderProcess;
306 if (process_type != helpable_process_type)
284 return false; 307 return false;
285 *uma_name = "NaCl.Client.Helper.StateOnFork"; 308 *uma_name = nonsfi_mode_ ? "NaCl.Client.HelperNonSFI.StateOnFork"
309 : "NaCl.Client.Helper.StateOnFork";
286 *uma_sample = status_; 310 *uma_sample = status_;
287 *uma_boundary_value = kNaClHelperStatusBoundary; 311 *uma_boundary_value = kNaClHelperStatusBoundary;
288 return true; 312 return true;
289 } 313 }
290 314
291 pid_t NaClForkDelegate::Fork(const std::string& process_type, 315 pid_t NaClForkDelegate::Fork(const std::string& process_type,
292 const std::vector<int>& fds, 316 const std::vector<int>& fds,
293 const std::string& channel_id) { 317 const std::string& channel_id) {
294 VLOG(1) << "NaClForkDelegate::Fork"; 318 VLOG(1) << "NaClForkDelegate::Fork";
295 319
296 DCHECK(fds.size() == kNumPassedFDs); 320 DCHECK(fds.size() == kNumPassedFDs);
297 321
298 if (status_ != kNaClHelperSuccess) { 322 if (status_ != kNaClHelperSuccess) {
299 LOG(ERROR) << "Cannot launch NaCl process: nacl_helper failed to start"; 323 LOG(ERROR) << "Cannot launch NaCl process: nacl_helper failed to start";
300 return -1; 324 return -1;
301 } 325 }
302 326
303 // First, send a remote fork request. 327 // First, send a remote fork request.
304 Pickle write_pickle; 328 Pickle write_pickle;
305 write_pickle.WriteInt(nacl::kNaClForkRequest); 329 write_pickle.WriteInt(nacl::kNaClForkRequest);
306 // TODO(hamaji): When we split the helper binary for non-SFI mode 330 write_pickle.WriteBool(nonsfi_mode_);
307 // from nacl_helper, stop sending this information.
308 const bool uses_nonsfi_mode =
309 process_type == switches::kNaClLoaderNonSfiProcess;
310 write_pickle.WriteBool(uses_nonsfi_mode);
311 write_pickle.WriteString(channel_id); 331 write_pickle.WriteString(channel_id);
312 332
313 char reply_buf[kNaClMaxIPCMessageLength]; 333 char reply_buf[kNaClMaxIPCMessageLength];
314 ssize_t reply_size = 0; 334 ssize_t reply_size = 0;
315 bool got_reply = 335 bool got_reply =
316 SendIPCRequestAndReadReply(fd_, fds, write_pickle, 336 SendIPCRequestAndReadReply(fd_, fds, write_pickle,
317 reply_buf, sizeof(reply_buf), &reply_size); 337 reply_buf, sizeof(reply_buf), &reply_size);
318 if (!got_reply) { 338 if (!got_reply) {
319 LOG(ERROR) << "Could not perform remote fork."; 339 LOG(ERROR) << "Could not perform remote fork.";
320 return -1; 340 return -1;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 int remote_exit_code; 388 int remote_exit_code;
369 if (!iter.ReadInt(&remote_exit_code)) { 389 if (!iter.ReadInt(&remote_exit_code)) {
370 LOG(ERROR) << "GetTerminationStatus: pickle failed"; 390 LOG(ERROR) << "GetTerminationStatus: pickle failed";
371 return false; 391 return false;
372 } 392 }
373 393
374 *status = static_cast<base::TerminationStatus>(termination_status); 394 *status = static_cast<base::TerminationStatus>(termination_status);
375 *exit_code = remote_exit_code; 395 *exit_code = remote_exit_code;
376 return true; 396 return true;
377 } 397 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698