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

Side by Side Diff: content/browser/zygote_main_linux.cc

Issue 6995121: New NaCl zygote implementation 2 (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Fixing includes for Windows bots Created 9 years, 6 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
« no previous file with comments | « content/browser/zygote_host_linux.cc ('k') | content/common/content_switches.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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 "content/browser/zygote_host_linux.h" 5 #include "content/browser/zygote_host_linux.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <pthread.h> 9 #include <pthread.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 19 matching lines...) Expand all
30 #include "content/common/chrome_descriptors.h" 30 #include "content/common/chrome_descriptors.h"
31 #include "content/common/content_switches.h" 31 #include "content/common/content_switches.h"
32 #include "content/common/font_config_ipc_linux.h" 32 #include "content/common/font_config_ipc_linux.h"
33 #include "content/common/main_function_params.h" 33 #include "content/common/main_function_params.h"
34 #include "content/common/pepper_plugin_registry.h" 34 #include "content/common/pepper_plugin_registry.h"
35 #include "content/common/process_watcher.h" 35 #include "content/common/process_watcher.h"
36 #include "content/common/result_codes.h" 36 #include "content/common/result_codes.h"
37 #include "content/common/sandbox_methods_linux.h" 37 #include "content/common/sandbox_methods_linux.h"
38 #include "content/common/set_process_title.h" 38 #include "content/common/set_process_title.h"
39 #include "content/common/unix_domain_socket_posix.h" 39 #include "content/common/unix_domain_socket_posix.h"
40 #include "content/common/zygote_fork_delegate_linux.h"
40 #include "seccompsandbox/sandbox.h" 41 #include "seccompsandbox/sandbox.h"
41 #include "skia/ext/SkFontHost_fontconfig_control.h" 42 #include "skia/ext/SkFontHost_fontconfig_control.h"
42 #include "unicode/timezone.h" 43 #include "unicode/timezone.h"
44 #include "ipc/ipc_switches.h"
43 45
44 #if defined(OS_LINUX) 46 #if defined(OS_LINUX)
45 #include <sys/epoll.h> 47 #include <sys/epoll.h>
46 #include <sys/prctl.h> 48 #include <sys/prctl.h>
47 #include <sys/signal.h> 49 #include <sys/signal.h>
48 #else 50 #else
49 #include <signal.h> 51 #include <signal.h>
50 #endif 52 #endif
51 53
52 #if defined(CHROMIUM_SELINUX) 54 #if defined(CHROMIUM_SELINUX)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 "the policies haven't been loaded into the kernel?)"; 92 "the policies haven't been loaded into the kernel?)";
91 } 93 }
92 } 94 }
93 #endif // CHROMIUM_SELINUX 95 #endif // CHROMIUM_SELINUX
94 96
95 // This is the object which implements the zygote. The ZygoteMain function, 97 // This is the object which implements the zygote. The ZygoteMain function,
96 // which is called from ChromeMain, simply constructs one of these objects and 98 // which is called from ChromeMain, simply constructs one of these objects and
97 // runs it. 99 // runs it.
98 class Zygote { 100 class Zygote {
99 public: 101 public:
100 explicit Zygote(int sandbox_flags) 102 explicit Zygote(int sandbox_flags, ZygoteForkDelegate* helper)
101 : sandbox_flags_(sandbox_flags) { 103 : sandbox_flags_(sandbox_flags),
104 helper_(helper) {
102 } 105 }
103 106
104 bool ProcessRequests() { 107 bool ProcessRequests() {
105 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the 108 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
106 // browser on it. 109 // browser on it.
107 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel. 110 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
108 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC 111 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
109 112
110 // We need to accept SIGCHLD, even though our handler is a no-op because 113 // We need to accept SIGCHLD, even though our handler is a no-op because
111 // otherwise we cannot wait on children. (According to POSIX 2001.) 114 // otherwise we cannot wait on children. (According to POSIX 2001.)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 161
159 Pickle pickle(buf, len); 162 Pickle pickle(buf, len);
160 void* iter = NULL; 163 void* iter = NULL;
161 164
162 int kind; 165 int kind;
163 if (pickle.ReadInt(&iter, &kind)) { 166 if (pickle.ReadInt(&iter, &kind)) {
164 switch (kind) { 167 switch (kind) {
165 case ZygoteHost::kCmdFork: 168 case ZygoteHost::kCmdFork:
166 // This function call can return multiple times, once per fork(). 169 // This function call can return multiple times, once per fork().
167 return HandleForkRequest(fd, pickle, iter, fds); 170 return HandleForkRequest(fd, pickle, iter, fds);
171
168 case ZygoteHost::kCmdReap: 172 case ZygoteHost::kCmdReap:
169 if (!fds.empty()) 173 if (!fds.empty())
170 break; 174 break;
171 HandleReapRequest(fd, pickle, iter); 175 HandleReapRequest(fd, pickle, iter);
172 return false; 176 return false;
173 case ZygoteHost::kCmdGetTerminationStatus: 177 case ZygoteHost::kCmdGetTerminationStatus:
174 if (!fds.empty()) 178 if (!fds.empty())
175 break; 179 break;
176 HandleGetTerminationStatus(fd, pickle, iter); 180 HandleGetTerminationStatus(fd, pickle, iter);
177 return false; 181 return false;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 ssize_t written = 244 ssize_t written =
241 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); 245 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
242 if (written != static_cast<ssize_t>(write_pickle.size())) 246 if (written != static_cast<ssize_t>(write_pickle.size()))
243 PLOG(ERROR) << "write"; 247 PLOG(ERROR) << "write";
244 } 248 }
245 249
246 // This is equivalent to fork(), except that, when using the SUID 250 // This is equivalent to fork(), except that, when using the SUID
247 // sandbox, it returns the real PID of the child process as it 251 // sandbox, it returns the real PID of the child process as it
248 // appears outside the sandbox, rather than returning the PID inside 252 // appears outside the sandbox, rather than returning the PID inside
249 // the sandbox. 253 // the sandbox.
250 int ForkWithRealPid() { 254 int ForkWithRealPid(const std::string& process_type, std::vector<int>& fds,
251 if (!g_suid_sandbox_active) 255 const std::string& channel_switch) {
256 const bool use_helper = (helper_ && helper_->CanHelp(process_type));
257 if (!(use_helper || g_suid_sandbox_active)) {
252 return fork(); 258 return fork();
259 }
253 260
254 int dummy_fd; 261 int dummy_fd;
255 ino_t dummy_inode; 262 ino_t dummy_inode;
256 int pipe_fds[2] = { -1, -1 }; 263 int pipe_fds[2] = { -1, -1 };
257 base::ProcessId pid = 0; 264 base::ProcessId pid = 0;
258 265
259 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); 266 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0);
260 if (dummy_fd < 0) { 267 if (dummy_fd < 0) {
261 LOG(ERROR) << "Failed to create dummy FD"; 268 LOG(ERROR) << "Failed to create dummy FD";
262 goto error; 269 goto error;
263 } 270 }
264 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { 271 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) {
265 LOG(ERROR) << "Failed to get inode for dummy FD"; 272 LOG(ERROR) << "Failed to get inode for dummy FD";
266 goto error; 273 goto error;
267 } 274 }
268 if (pipe(pipe_fds) != 0) { 275 if (pipe(pipe_fds) != 0) {
269 LOG(ERROR) << "Failed to create pipe"; 276 LOG(ERROR) << "Failed to create pipe";
270 goto error; 277 goto error;
271 } 278 }
272 279
273 pid = fork(); 280 if (use_helper) {
281 fds.push_back(dummy_fd);
282 fds.push_back(pipe_fds[0]);
283 pid = helper_->Fork(fds);
284 } else {
285 pid = fork();
286 }
274 if (pid < 0) { 287 if (pid < 0) {
275 goto error; 288 goto error;
276 } else if (pid == 0) { 289 } else if (pid == 0) {
277 // In the child process. 290 // In the child process.
278 close(pipe_fds[1]); 291 close(pipe_fds[1]);
279 char buffer[1]; 292 char buffer[1];
280 // Wait until the parent process has discovered our PID. We 293 // Wait until the parent process has discovered our PID. We
281 // should not fork any child processes (which the seccomp 294 // should not fork any child processes (which the seccomp
282 // sandbox does) until then, because that can interfere with the 295 // sandbox does) until then, because that can interfere with the
283 // parent's discovery of our PID. 296 // parent's discovery of our PID.
284 if (HANDLE_EINTR(read(pipe_fds[0], buffer, 1)) != 1 || 297 if (HANDLE_EINTR(read(pipe_fds[0], buffer, 1)) != 1 ||
285 buffer[0] != 'x') { 298 buffer[0] != 'x') {
286 LOG(FATAL) << "Failed to synchronise with parent zygote process"; 299 LOG(FATAL) << "Failed to synchronise with parent zygote process";
287 } 300 }
288 close(pipe_fds[0]); 301 close(pipe_fds[0]);
289 close(dummy_fd); 302 close(dummy_fd);
290 return 0; 303 return 0;
291 } else { 304 } else {
292 // In the parent process. 305 // In the parent process.
293 close(dummy_fd); 306 close(dummy_fd);
294 dummy_fd = -1; 307 dummy_fd = -1;
295 close(pipe_fds[0]); 308 close(pipe_fds[0]);
296 pipe_fds[0] = -1; 309 pipe_fds[0] = -1;
297 uint8_t reply_buf[512]; 310 base::ProcessId real_pid;
298 Pickle request; 311 if (g_suid_sandbox_active) {
299 request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE); 312 uint8_t reply_buf[512];
300 request.WriteUInt64(dummy_inode); 313 Pickle request;
314 request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE);
315 request.WriteUInt64(dummy_inode);
301 316
302 const ssize_t r = UnixDomainSocket::SendRecvMsg( 317 const ssize_t r = UnixDomainSocket::SendRecvMsg(
303 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, 318 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL,
304 request); 319 request);
305 if (r == -1) { 320 if (r == -1) {
306 LOG(ERROR) << "Failed to get child process's real PID"; 321 LOG(ERROR) << "Failed to get child process's real PID";
307 goto error; 322 goto error;
323 }
324
325 Pickle reply(reinterpret_cast<char*>(reply_buf), r);
326 void* iter = NULL;
327 if (!reply.ReadInt(&iter, &real_pid))
328 goto error;
329 if (real_pid <= 0) {
330 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already?
331 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed";
332 goto error;
333 }
334 real_pids_to_sandbox_pids[real_pid] = pid;
308 } 335 }
309 336 if (use_helper) {
310 base::ProcessId real_pid; 337 real_pid = pid;
311 Pickle reply(reinterpret_cast<char*>(reply_buf), r); 338 if (!helper_->AckChild(pipe_fds[1], channel_switch)) {
312 void* iter2 = NULL; 339 LOG(ERROR) << "Failed to synchronise with NaCl child process";
313 if (!reply.ReadInt(&iter2, &real_pid)) 340 goto error;
314 goto error; 341 }
315 if (real_pid <= 0) { 342 } else {
316 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? 343 if (HANDLE_EINTR(write(pipe_fds[1], "x", 1)) != 1) {
317 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; 344 LOG(ERROR) << "Failed to synchronise with child process";
318 goto error; 345 goto error;
319 } 346 }
320 real_pids_to_sandbox_pids[real_pid] = pid;
321 if (HANDLE_EINTR(write(pipe_fds[1], "x", 1)) != 1) {
322 LOG(ERROR) << "Failed to synchronise with child process";
323 goto error;
324 } 347 }
325 close(pipe_fds[1]); 348 close(pipe_fds[1]);
326 return real_pid; 349 return real_pid;
327 } 350 }
328 351
329 error: 352 error:
330 if (pid > 0) { 353 if (pid > 0) {
331 if (waitpid(pid, NULL, WNOHANG) == -1) 354 if (waitpid(pid, NULL, WNOHANG) == -1)
332 LOG(ERROR) << "Failed to wait for process"; 355 LOG(ERROR) << "Failed to wait for process";
333 } 356 }
334 if (dummy_fd >= 0) 357 if (dummy_fd >= 0)
335 close(dummy_fd); 358 close(dummy_fd);
336 if (pipe_fds[0] >= 0) 359 if (pipe_fds[0] >= 0)
337 close(pipe_fds[0]); 360 close(pipe_fds[0]);
338 if (pipe_fds[1] >= 0) 361 if (pipe_fds[1] >= 0)
339 close(pipe_fds[1]); 362 close(pipe_fds[1]);
340 return -1; 363 return -1;
341 } 364 }
342 365
343 // Handle a 'fork' request from the browser: this means that the browser 366 // Handle a 'fork' request from the browser: this means that the browser
344 // wishes to start a new renderer. 367 // wishes to start a new renderer.
345 bool HandleForkRequest(int fd, const Pickle& pickle, void* iter, 368 bool HandleForkRequest(int fd, const Pickle& pickle,
346 std::vector<int>& fds) { 369 void* iter, std::vector<int>& fds) {
347 std::vector<std::string> args; 370 std::vector<std::string> args;
348 int argc, numfds; 371 int argc, numfds;
349 base::GlobalDescriptors::Mapping mapping; 372 base::GlobalDescriptors::Mapping mapping;
350 base::ProcessId child; 373 base::ProcessId child;
374 std::string process_type;
375 std::string channel_id;
376 const std::string channel_id_prefix = std::string("--")
377 + switches::kProcessChannelID + std::string("=");
378
379 if (!pickle.ReadString(&iter, &process_type))
380 goto error;
351 381
352 if (!pickle.ReadInt(&iter, &argc)) 382 if (!pickle.ReadInt(&iter, &argc))
353 goto error; 383 goto error;
354 384
355 for (int i = 0; i < argc; ++i) { 385 for (int i = 0; i < argc; ++i) {
356 std::string arg; 386 std::string arg;
357 if (!pickle.ReadString(&iter, &arg)) 387 if (!pickle.ReadString(&iter, &arg))
358 goto error; 388 goto error;
359 args.push_back(arg); 389 args.push_back(arg);
390 if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0)
391 channel_id = arg;
360 } 392 }
361 393
362 if (!pickle.ReadInt(&iter, &numfds)) 394 if (!pickle.ReadInt(&iter, &numfds))
363 goto error; 395 goto error;
364 if (numfds != static_cast<int>(fds.size())) 396 if (numfds != static_cast<int>(fds.size()))
365 goto error; 397 goto error;
366 398
367 for (int i = 0; i < numfds; ++i) { 399 for (int i = 0; i < numfds; ++i) {
368 base::GlobalDescriptors::Key key; 400 base::GlobalDescriptors::Key key;
369 if (!pickle.ReadUInt32(&iter, &key)) 401 if (!pickle.ReadUInt32(&iter, &key))
370 goto error; 402 goto error;
371 mapping.push_back(std::make_pair(key, fds[i])); 403 mapping.push_back(std::make_pair(key, fds[i]));
372 } 404 }
373 405
374 mapping.push_back(std::make_pair( 406 mapping.push_back(std::make_pair(
375 static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor)); 407 static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor));
376 408
377 child = ForkWithRealPid(); 409 child = ForkWithRealPid(process_type, fds, channel_id);
378 410
379 if (!child) { 411 if (!child) {
380 #if defined(SECCOMP_SANDBOX) 412 #if defined(SECCOMP_SANDBOX)
381 // Try to open /proc/self/maps as the seccomp sandbox needs access to it 413 // Try to open /proc/self/maps as the seccomp sandbox needs access to it
382 if (g_proc_fd >= 0) { 414 if (g_proc_fd >= 0) {
383 int proc_self_maps = openat(g_proc_fd, "self/maps", O_RDONLY); 415 int proc_self_maps = openat(g_proc_fd, "self/maps", O_RDONLY);
384 if (proc_self_maps >= 0) { 416 if (proc_self_maps >= 0) {
385 SeccompSandboxSetProcSelfMaps(proc_self_maps); 417 SeccompSandboxSetProcSelfMaps(proc_self_maps);
386 } 418 }
387 close(g_proc_fd); 419 close(g_proc_fd);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 return false; 472 return false;
441 } 473 }
442 474
443 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs 475 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs
444 // fork() returns are not the real PIDs, so we need to map the Real PIDS 476 // fork() returns are not the real PIDs, so we need to map the Real PIDS
445 // into the sandbox PID namespace. 477 // into the sandbox PID namespace.
446 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap; 478 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap;
447 ProcessMap real_pids_to_sandbox_pids; 479 ProcessMap real_pids_to_sandbox_pids;
448 480
449 const int sandbox_flags_; 481 const int sandbox_flags_;
482 ZygoteForkDelegate* helper_;
450 }; 483 };
451 484
452 // With SELinux we can carve out a precise sandbox, so we don't have to play 485 // With SELinux we can carve out a precise sandbox, so we don't have to play
453 // with intercepting libc calls. 486 // with intercepting libc calls.
454 #if !defined(CHROMIUM_SELINUX) 487 #if !defined(CHROMIUM_SELINUX)
455 488
456 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, 489 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
457 char* timezone_out, 490 char* timezone_out,
458 size_t timezone_out_len) { 491 size_t timezone_out_len) {
459 Pickle request; 492 Pickle request;
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
698 #else // CHROMIUM_SELINUX 731 #else // CHROMIUM_SELINUX
699 732
700 static bool EnterSandbox() { 733 static bool EnterSandbox() {
701 PreSandboxInit(); 734 PreSandboxInit();
702 SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor); 735 SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor);
703 return true; 736 return true;
704 } 737 }
705 738
706 #endif // CHROMIUM_SELINUX 739 #endif // CHROMIUM_SELINUX
707 740
708 bool ZygoteMain(const MainFunctionParams& params) { 741 bool ZygoteMain(const MainFunctionParams& params,
742 ZygoteForkDelegate* forkdelegate) {
709 #if !defined(CHROMIUM_SELINUX) 743 #if !defined(CHROMIUM_SELINUX)
710 g_am_zygote_or_renderer = true; 744 g_am_zygote_or_renderer = true;
711 #endif 745 #endif
712 746
713 #if defined(SECCOMP_SANDBOX) 747 #if defined(SECCOMP_SANDBOX)
714 // The seccomp sandbox needs access to files in /proc, which might be denied 748 // The seccomp sandbox needs access to files in /proc, which might be denied
715 // after one of the other sandboxes have been started. So, obtain a suitable 749 // after one of the other sandboxes have been started. So, obtain a suitable
716 // file handle in advance. 750 // file handle in advance.
717 if (CommandLine::ForCurrentProcess()->HasSwitch( 751 if (CommandLine::ForCurrentProcess()->HasSwitch(
718 switches::kEnableSeccompSandbox)) { 752 switches::kEnableSeccompSandbox)) {
719 g_proc_fd = open("/proc", O_DIRECTORY | O_RDONLY); 753 g_proc_fd = open("/proc", O_DIRECTORY | O_RDONLY);
720 if (g_proc_fd < 0) { 754 if (g_proc_fd < 0) {
721 LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp " 755 LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp "
722 "sandboxing."; 756 "sandboxing.";
723 } 757 }
724 } 758 }
725 #endif // SECCOMP_SANDBOX 759 #endif // SECCOMP_SANDBOX
726 760
761 VLOG(1) << "initializing fork delegate";
762 forkdelegate->Init(getenv("SBX_D") != NULL, // g_suid_sandbox_active,
763 kBrowserDescriptor, kMagicSandboxIPCDescriptor);
764
727 // Turn on the SELinux or SUID sandbox 765 // Turn on the SELinux or SUID sandbox
728 if (!EnterSandbox()) { 766 if (!EnterSandbox()) {
729 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " 767 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: "
730 << errno << ")"; 768 << errno << ")";
731 return false; 769 return false;
732 } 770 }
733 771
734 int sandbox_flags = 0; 772 int sandbox_flags = 0;
735 if (getenv("SBX_D")) 773 if (getenv("SBX_D"))
736 sandbox_flags |= ZygoteHost::kSandboxSUID; 774 sandbox_flags |= ZygoteHost::kSandboxSUID;
(...skipping 16 matching lines...) Expand all
753 LOG(ERROR) << "WARNING! This machine lacks support needed for the " 791 LOG(ERROR) << "WARNING! This machine lacks support needed for the "
754 "Seccomp sandbox. Running renderers with Seccomp " 792 "Seccomp sandbox. Running renderers with Seccomp "
755 "sandboxing disabled."; 793 "sandboxing disabled.";
756 } else { 794 } else {
757 VLOG(1) << "Enabling experimental Seccomp sandbox."; 795 VLOG(1) << "Enabling experimental Seccomp sandbox.";
758 sandbox_flags |= ZygoteHost::kSandboxSeccomp; 796 sandbox_flags |= ZygoteHost::kSandboxSeccomp;
759 } 797 }
760 } 798 }
761 #endif // SECCOMP_SANDBOX 799 #endif // SECCOMP_SANDBOX
762 800
763 Zygote zygote(sandbox_flags); 801 Zygote zygote(sandbox_flags, forkdelegate);
764 // This function call can return multiple times, once per fork(). 802 // This function call can return multiple times, once per fork().
765 return zygote.ProcessRequests(); 803 return zygote.ProcessRequests();
766 } 804 }
OLDNEW
« no previous file with comments | « content/browser/zygote_host_linux.cc ('k') | content/common/content_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698