Chromium Code Reviews| 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 freecon(security_context); | 87 freecon(security_context); |
| 86 | 88 |
| 87 if (r) { | 89 if (r) { |
| 88 LOG(FATAL) << "dynamic transition to type '" << type << "' failed. " | 90 LOG(FATAL) << "dynamic transition to type '" << type << "' failed. " |
| 89 "(this binary has been built with SELinux support, but maybe " | 91 "(this binary has been built with SELinux support, but maybe " |
| 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 |
| 97 // Search through string vector args for a string of the form | |
| 98 // --swtch=value. Return the string if found, else return the | |
| 99 // empty string. | |
|
Evan Martin
2011/06/27 18:49:32
I'm a little concerned that this is incorrect for
Brad Chen
2011/06/27 22:06:25
I never liked this code this much anyway. Realizin
| |
| 100 static std::string ExtractArg(std::vector<std::string>& args, | |
| 101 const std::string& swtch) { | |
| 102 const std::string key = "--" + swtch + "="; | |
| 103 int len = key.length(); | |
| 104 for (size_t i = 0; i < args.size(); i++) { | |
| 105 if (key.compare(0, len, args[i], 0, len) == 0) { | |
| 106 return args[i]; | |
| 107 } | |
| 108 } | |
| 109 return ""; | |
| 110 } | |
| 111 | |
| 95 // This is the object which implements the zygote. The ZygoteMain function, | 112 // This is the object which implements the zygote. The ZygoteMain function, |
| 96 // which is called from ChromeMain, simply constructs one of these objects and | 113 // which is called from ChromeMain, simply constructs one of these objects and |
| 97 // runs it. | 114 // runs it. |
| 98 class Zygote { | 115 class Zygote { |
| 99 public: | 116 public: |
| 100 explicit Zygote(int sandbox_flags) | 117 explicit Zygote(int sandbox_flags, ZygoteForkDelegate* helper) |
| 101 : sandbox_flags_(sandbox_flags) { | 118 : sandbox_flags_(sandbox_flags), |
| 119 helper_(helper) { | |
| 102 } | 120 } |
| 103 | 121 |
| 104 bool ProcessRequests() { | 122 bool ProcessRequests() { |
| 105 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the | 123 // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the |
| 106 // browser on it. | 124 // browser on it. |
| 107 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel. | 125 // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel. |
| 108 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC | 126 // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC |
| 109 | 127 |
| 110 // We need to accept SIGCHLD, even though our handler is a no-op because | 128 // 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.) | 129 // otherwise we cannot wait on children. (According to POSIX 2001.) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 | 176 |
| 159 Pickle pickle(buf, len); | 177 Pickle pickle(buf, len); |
| 160 void* iter = NULL; | 178 void* iter = NULL; |
| 161 | 179 |
| 162 int kind; | 180 int kind; |
| 163 if (pickle.ReadInt(&iter, &kind)) { | 181 if (pickle.ReadInt(&iter, &kind)) { |
| 164 switch (kind) { | 182 switch (kind) { |
| 165 case ZygoteHost::kCmdFork: | 183 case ZygoteHost::kCmdFork: |
| 166 // This function call can return multiple times, once per fork(). | 184 // This function call can return multiple times, once per fork(). |
| 167 return HandleForkRequest(fd, pickle, iter, fds); | 185 return HandleForkRequest(fd, pickle, iter, fds); |
| 186 | |
| 168 case ZygoteHost::kCmdReap: | 187 case ZygoteHost::kCmdReap: |
| 169 if (!fds.empty()) | 188 if (!fds.empty()) |
| 170 break; | 189 break; |
| 171 HandleReapRequest(fd, pickle, iter); | 190 HandleReapRequest(fd, pickle, iter); |
| 172 return false; | 191 return false; |
| 173 case ZygoteHost::kCmdGetTerminationStatus: | 192 case ZygoteHost::kCmdGetTerminationStatus: |
| 174 if (!fds.empty()) | 193 if (!fds.empty()) |
| 175 break; | 194 break; |
| 176 HandleGetTerminationStatus(fd, pickle, iter); | 195 HandleGetTerminationStatus(fd, pickle, iter); |
| 177 return false; | 196 return false; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 ssize_t written = | 259 ssize_t written = |
| 241 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); | 260 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); |
| 242 if (written != static_cast<ssize_t>(write_pickle.size())) | 261 if (written != static_cast<ssize_t>(write_pickle.size())) |
| 243 PLOG(ERROR) << "write"; | 262 PLOG(ERROR) << "write"; |
| 244 } | 263 } |
| 245 | 264 |
| 246 // This is equivalent to fork(), except that, when using the SUID | 265 // This is equivalent to fork(), except that, when using the SUID |
| 247 // sandbox, it returns the real PID of the child process as it | 266 // sandbox, it returns the real PID of the child process as it |
| 248 // appears outside the sandbox, rather than returning the PID inside | 267 // appears outside the sandbox, rather than returning the PID inside |
| 249 // the sandbox. | 268 // the sandbox. |
| 250 int ForkWithRealPid() { | 269 int ForkWithRealPid(const std::string process_type, std::vector<int>& fds, |
|
Evan Martin
2011/06/27 18:49:32
These should be const std::string&
Brad Chen
2011/06/27 22:06:25
Done.
| |
| 251 if (!g_suid_sandbox_active) | 270 const std::string channel_switch) { |
| 271 const bool use_helper = (helper_ && helper_->CanHelp(process_type)); | |
| 272 if (!(use_helper || g_suid_sandbox_active)) { | |
| 252 return fork(); | 273 return fork(); |
| 274 } | |
| 253 | 275 |
| 254 int dummy_fd; | 276 int dummy_fd; |
| 255 ino_t dummy_inode; | 277 ino_t dummy_inode; |
| 256 int pipe_fds[2] = { -1, -1 }; | 278 int pipe_fds[2] = { -1, -1 }; |
| 257 base::ProcessId pid = 0; | 279 base::ProcessId pid = 0; |
| 258 | 280 |
| 259 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); | 281 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
| 260 if (dummy_fd < 0) { | 282 if (dummy_fd < 0) { |
| 261 LOG(ERROR) << "Failed to create dummy FD"; | 283 LOG(ERROR) << "Failed to create dummy FD"; |
| 262 goto error; | 284 goto error; |
| 263 } | 285 } |
| 264 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { | 286 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { |
| 265 LOG(ERROR) << "Failed to get inode for dummy FD"; | 287 LOG(ERROR) << "Failed to get inode for dummy FD"; |
| 266 goto error; | 288 goto error; |
| 267 } | 289 } |
| 268 if (pipe(pipe_fds) != 0) { | 290 if (pipe(pipe_fds) != 0) { |
| 269 LOG(ERROR) << "Failed to create pipe"; | 291 LOG(ERROR) << "Failed to create pipe"; |
| 270 goto error; | 292 goto error; |
| 271 } | 293 } |
| 272 | 294 |
| 273 pid = fork(); | 295 if (use_helper) { |
| 296 fds.push_back(dummy_fd); | |
| 297 fds.push_back(pipe_fds[0]); | |
| 298 pid = helper_->Fork(fds); | |
| 299 } else { | |
| 300 pid = fork(); | |
| 301 } | |
| 274 if (pid < 0) { | 302 if (pid < 0) { |
| 275 goto error; | 303 goto error; |
| 276 } else if (pid == 0) { | 304 } else if (pid == 0) { |
| 277 // In the child process. | 305 // In the child process. |
| 278 close(pipe_fds[1]); | 306 close(pipe_fds[1]); |
| 279 char buffer[1]; | 307 char buffer[1]; |
| 280 // Wait until the parent process has discovered our PID. We | 308 // Wait until the parent process has discovered our PID. We |
| 281 // should not fork any child processes (which the seccomp | 309 // should not fork any child processes (which the seccomp |
| 282 // sandbox does) until then, because that can interfere with the | 310 // sandbox does) until then, because that can interfere with the |
| 283 // parent's discovery of our PID. | 311 // parent's discovery of our PID. |
| 284 if (HANDLE_EINTR(read(pipe_fds[0], buffer, 1)) != 1 || | 312 if (HANDLE_EINTR(read(pipe_fds[0], buffer, 1)) != 1 || |
| 285 buffer[0] != 'x') { | 313 buffer[0] != 'x') { |
| 286 LOG(FATAL) << "Failed to synchronise with parent zygote process"; | 314 LOG(FATAL) << "Failed to synchronise with parent zygote process"; |
| 287 } | 315 } |
| 288 close(pipe_fds[0]); | 316 close(pipe_fds[0]); |
| 289 close(dummy_fd); | 317 close(dummy_fd); |
| 290 return 0; | 318 return 0; |
| 291 } else { | 319 } else { |
| 292 // In the parent process. | 320 // In the parent process. |
| 293 close(dummy_fd); | 321 close(dummy_fd); |
| 294 dummy_fd = -1; | 322 dummy_fd = -1; |
| 295 close(pipe_fds[0]); | 323 close(pipe_fds[0]); |
| 296 pipe_fds[0] = -1; | 324 pipe_fds[0] = -1; |
| 297 uint8_t reply_buf[512]; | 325 base::ProcessId real_pid; |
| 298 Pickle request; | 326 if (g_suid_sandbox_active) { |
| 299 request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE); | 327 uint8_t reply_buf[512]; |
| 300 request.WriteUInt64(dummy_inode); | 328 Pickle request; |
| 329 request.WriteInt(LinuxSandbox::METHOD_GET_CHILD_WITH_INODE); | |
| 330 request.WriteUInt64(dummy_inode); | |
| 301 | 331 |
| 302 const ssize_t r = UnixDomainSocket::SendRecvMsg( | 332 const ssize_t r = UnixDomainSocket::SendRecvMsg( |
| 303 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, | 333 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, |
| 304 request); | 334 request); |
| 305 if (r == -1) { | 335 if (r == -1) { |
| 306 LOG(ERROR) << "Failed to get child process's real PID"; | 336 LOG(ERROR) << "Failed to get child process's real PID"; |
| 307 goto error; | 337 goto error; |
| 338 } | |
| 339 | |
| 340 Pickle reply(reinterpret_cast<char*>(reply_buf), r); | |
| 341 void* iter2 = NULL; | |
|
Evan Martin
2011/06/27 18:49:32
Why "iter2" and not just "iter"?
Brad Chen
2011/06/27 22:06:25
An irrelevant artifact; fixed.
On 2011/06/27 18:4
| |
| 342 if (!reply.ReadInt(&iter2, &real_pid)) | |
| 343 goto error; | |
| 344 if (real_pid <= 0) { | |
| 345 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? | |
| 346 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; | |
| 347 goto error; | |
| 348 } | |
| 349 real_pids_to_sandbox_pids[real_pid] = pid; | |
| 308 } | 350 } |
| 309 | 351 if (use_helper) { |
| 310 base::ProcessId real_pid; | 352 real_pid = pid; |
| 311 Pickle reply(reinterpret_cast<char*>(reply_buf), r); | 353 if (!helper_->AckChild(pipe_fds[1], channel_switch)) { |
| 312 void* iter2 = NULL; | 354 LOG(ERROR) << "Failed to synchronise with NaCl child process"; |
| 313 if (!reply.ReadInt(&iter2, &real_pid)) | 355 goto error; |
| 314 goto error; | 356 } |
| 315 if (real_pid <= 0) { | 357 } else { |
| 316 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? | 358 if (HANDLE_EINTR(write(pipe_fds[1], "x", 1)) != 1) { |
| 317 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; | 359 LOG(ERROR) << "Failed to synchronise with child process"; |
| 318 goto error; | 360 goto error; |
| 319 } | 361 } |
| 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 } | 362 } |
| 325 close(pipe_fds[1]); | 363 close(pipe_fds[1]); |
| 326 return real_pid; | 364 return real_pid; |
| 327 } | 365 } |
| 328 | 366 |
| 329 error: | 367 error: |
| 330 if (pid > 0) { | 368 if (pid > 0) { |
| 331 if (waitpid(pid, NULL, WNOHANG) == -1) | 369 if (waitpid(pid, NULL, WNOHANG) == -1) |
| 332 LOG(ERROR) << "Failed to wait for process"; | 370 LOG(ERROR) << "Failed to wait for process"; |
| 333 } | 371 } |
| 334 if (dummy_fd >= 0) | 372 if (dummy_fd >= 0) |
| 335 close(dummy_fd); | 373 close(dummy_fd); |
| 336 if (pipe_fds[0] >= 0) | 374 if (pipe_fds[0] >= 0) |
| 337 close(pipe_fds[0]); | 375 close(pipe_fds[0]); |
| 338 if (pipe_fds[1] >= 0) | 376 if (pipe_fds[1] >= 0) |
| 339 close(pipe_fds[1]); | 377 close(pipe_fds[1]); |
| 340 return -1; | 378 return -1; |
| 341 } | 379 } |
| 342 | 380 |
| 343 // Handle a 'fork' request from the browser: this means that the browser | 381 // Handle a 'fork' request from the browser: this means that the browser |
| 344 // wishes to start a new renderer. | 382 // wishes to start a new renderer. |
| 345 bool HandleForkRequest(int fd, const Pickle& pickle, void* iter, | 383 bool HandleForkRequest(int fd, const Pickle& pickle, |
| 346 std::vector<int>& fds) { | 384 void* iter, std::vector<int>& fds) { |
| 347 std::vector<std::string> args; | 385 std::vector<std::string> args; |
| 348 int argc, numfds; | 386 int argc, numfds; |
| 349 base::GlobalDescriptors::Mapping mapping; | 387 base::GlobalDescriptors::Mapping mapping; |
| 350 base::ProcessId child; | 388 base::ProcessId child; |
| 389 std::string process_type; | |
| 390 | |
| 391 if (!pickle.ReadString(&iter, &process_type)) | |
| 392 goto error; | |
| 351 | 393 |
| 352 if (!pickle.ReadInt(&iter, &argc)) | 394 if (!pickle.ReadInt(&iter, &argc)) |
| 353 goto error; | 395 goto error; |
| 354 | 396 |
| 355 for (int i = 0; i < argc; ++i) { | 397 for (int i = 0; i < argc; ++i) { |
| 356 std::string arg; | 398 std::string arg; |
| 357 if (!pickle.ReadString(&iter, &arg)) | 399 if (!pickle.ReadString(&iter, &arg)) |
| 358 goto error; | 400 goto error; |
| 359 args.push_back(arg); | 401 args.push_back(arg); |
| 360 } | 402 } |
| 361 | 403 |
| 362 if (!pickle.ReadInt(&iter, &numfds)) | 404 if (!pickle.ReadInt(&iter, &numfds)) |
| 363 goto error; | 405 goto error; |
| 364 if (numfds != static_cast<int>(fds.size())) | 406 if (numfds != static_cast<int>(fds.size())) |
| 365 goto error; | 407 goto error; |
| 366 | 408 |
| 367 for (int i = 0; i < numfds; ++i) { | 409 for (int i = 0; i < numfds; ++i) { |
| 368 base::GlobalDescriptors::Key key; | 410 base::GlobalDescriptors::Key key; |
| 369 if (!pickle.ReadUInt32(&iter, &key)) | 411 if (!pickle.ReadUInt32(&iter, &key)) |
| 370 goto error; | 412 goto error; |
| 371 mapping.push_back(std::make_pair(key, fds[i])); | 413 mapping.push_back(std::make_pair(key, fds[i])); |
| 372 } | 414 } |
| 373 | 415 |
| 374 mapping.push_back(std::make_pair( | 416 mapping.push_back(std::make_pair( |
| 375 static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor)); | 417 static_cast<uint32_t>(kSandboxIPCChannel), kMagicSandboxIPCDescriptor)); |
| 376 | 418 |
| 377 child = ForkWithRealPid(); | 419 child = ForkWithRealPid(process_type, fds, |
| 420 ExtractArg(args, switches::kProcessChannelID)); | |
| 378 | 421 |
| 379 if (!child) { | 422 if (!child) { |
| 380 #if defined(SECCOMP_SANDBOX) | 423 #if defined(SECCOMP_SANDBOX) |
| 381 // Try to open /proc/self/maps as the seccomp sandbox needs access to it | 424 // Try to open /proc/self/maps as the seccomp sandbox needs access to it |
| 382 if (g_proc_fd >= 0) { | 425 if (g_proc_fd >= 0) { |
| 383 int proc_self_maps = openat(g_proc_fd, "self/maps", O_RDONLY); | 426 int proc_self_maps = openat(g_proc_fd, "self/maps", O_RDONLY); |
| 384 if (proc_self_maps >= 0) { | 427 if (proc_self_maps >= 0) { |
| 385 SeccompSandboxSetProcSelfMaps(proc_self_maps); | 428 SeccompSandboxSetProcSelfMaps(proc_self_maps); |
| 386 } | 429 } |
| 387 close(g_proc_fd); | 430 close(g_proc_fd); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 return false; | 483 return false; |
| 441 } | 484 } |
| 442 | 485 |
| 443 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs | 486 // 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 | 487 // fork() returns are not the real PIDs, so we need to map the Real PIDS |
| 445 // into the sandbox PID namespace. | 488 // into the sandbox PID namespace. |
| 446 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap; | 489 typedef base::hash_map<base::ProcessHandle, base::ProcessHandle> ProcessMap; |
| 447 ProcessMap real_pids_to_sandbox_pids; | 490 ProcessMap real_pids_to_sandbox_pids; |
| 448 | 491 |
| 449 const int sandbox_flags_; | 492 const int sandbox_flags_; |
| 493 ZygoteForkDelegate* helper_; | |
| 450 }; | 494 }; |
| 451 | 495 |
| 452 // With SELinux we can carve out a precise sandbox, so we don't have to play | 496 // With SELinux we can carve out a precise sandbox, so we don't have to play |
| 453 // with intercepting libc calls. | 497 // with intercepting libc calls. |
| 454 #if !defined(CHROMIUM_SELINUX) | 498 #if !defined(CHROMIUM_SELINUX) |
| 455 | 499 |
| 456 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, | 500 static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output, |
| 457 char* timezone_out, | 501 char* timezone_out, |
| 458 size_t timezone_out_len) { | 502 size_t timezone_out_len) { |
| 459 Pickle request; | 503 Pickle request; |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 698 #else // CHROMIUM_SELINUX | 742 #else // CHROMIUM_SELINUX |
| 699 | 743 |
| 700 static bool EnterSandbox() { | 744 static bool EnterSandbox() { |
| 701 PreSandboxInit(); | 745 PreSandboxInit(); |
| 702 SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor); | 746 SkiaFontConfigUseIPCImplementation(kMagicSandboxIPCDescriptor); |
| 703 return true; | 747 return true; |
| 704 } | 748 } |
| 705 | 749 |
| 706 #endif // CHROMIUM_SELINUX | 750 #endif // CHROMIUM_SELINUX |
| 707 | 751 |
| 708 bool ZygoteMain(const MainFunctionParams& params) { | 752 bool ZygoteMain(const MainFunctionParams& params, |
| 753 ZygoteForkDelegate* forkdelegate) { | |
| 709 #if !defined(CHROMIUM_SELINUX) | 754 #if !defined(CHROMIUM_SELINUX) |
| 710 g_am_zygote_or_renderer = true; | 755 g_am_zygote_or_renderer = true; |
| 711 #endif | 756 #endif |
| 712 | 757 |
| 713 #if defined(SECCOMP_SANDBOX) | 758 #if defined(SECCOMP_SANDBOX) |
| 714 // The seccomp sandbox needs access to files in /proc, which might be denied | 759 // 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 | 760 // after one of the other sandboxes have been started. So, obtain a suitable |
| 716 // file handle in advance. | 761 // file handle in advance. |
| 717 if (CommandLine::ForCurrentProcess()->HasSwitch( | 762 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 718 switches::kEnableSeccompSandbox)) { | 763 switches::kEnableSeccompSandbox)) { |
| 719 g_proc_fd = open("/proc", O_DIRECTORY | O_RDONLY); | 764 g_proc_fd = open("/proc", O_DIRECTORY | O_RDONLY); |
| 720 if (g_proc_fd < 0) { | 765 if (g_proc_fd < 0) { |
| 721 LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp " | 766 LOG(ERROR) << "WARNING! Cannot access \"/proc\". Disabling seccomp " |
| 722 "sandboxing."; | 767 "sandboxing."; |
| 723 } | 768 } |
| 724 } | 769 } |
| 725 #endif // SECCOMP_SANDBOX | 770 #endif // SECCOMP_SANDBOX |
| 726 | 771 |
| 772 VLOG(1) << "initializing fork delegate"; | |
| 773 forkdelegate->Init(getenv("SBX_D") != NULL, // g_suid_sandbox_active, | |
| 774 kBrowserDescriptor, kMagicSandboxIPCDescriptor); | |
| 775 | |
| 727 // Turn on the SELinux or SUID sandbox | 776 // Turn on the SELinux or SUID sandbox |
| 728 if (!EnterSandbox()) { | 777 if (!EnterSandbox()) { |
| 729 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " | 778 LOG(FATAL) << "Failed to enter sandbox. Fail safe abort. (errno: " |
| 730 << errno << ")"; | 779 << errno << ")"; |
| 731 return false; | 780 return false; |
| 732 } | 781 } |
| 733 | 782 |
| 734 int sandbox_flags = 0; | 783 int sandbox_flags = 0; |
| 735 if (getenv("SBX_D")) | 784 if (getenv("SBX_D")) |
| 736 sandbox_flags |= ZygoteHost::kSandboxSUID; | 785 sandbox_flags |= ZygoteHost::kSandboxSUID; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 753 LOG(ERROR) << "WARNING! This machine lacks support needed for the " | 802 LOG(ERROR) << "WARNING! This machine lacks support needed for the " |
| 754 "Seccomp sandbox. Running renderers with Seccomp " | 803 "Seccomp sandbox. Running renderers with Seccomp " |
| 755 "sandboxing disabled."; | 804 "sandboxing disabled."; |
| 756 } else { | 805 } else { |
| 757 VLOG(1) << "Enabling experimental Seccomp sandbox."; | 806 VLOG(1) << "Enabling experimental Seccomp sandbox."; |
| 758 sandbox_flags |= ZygoteHost::kSandboxSeccomp; | 807 sandbox_flags |= ZygoteHost::kSandboxSeccomp; |
| 759 } | 808 } |
| 760 } | 809 } |
| 761 #endif // SECCOMP_SANDBOX | 810 #endif // SECCOMP_SANDBOX |
| 762 | 811 |
| 763 Zygote zygote(sandbox_flags); | 812 Zygote zygote(sandbox_flags, forkdelegate); |
| 764 // This function call can return multiple times, once per fork(). | 813 // This function call can return multiple times, once per fork(). |
| 765 return zygote.ProcessRequests(); | 814 return zygote.ProcessRequests(); |
| 766 } | 815 } |
| OLD | NEW |