OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |