OLD | NEW |
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 "content/browser/zygote_host/zygote_host_impl_linux.h" | 5 #include "content/browser/zygote_host/zygote_host_impl_linux.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 #include <sys/socket.h> | 8 #include <sys/socket.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 } else { | 214 } else { |
215 // Not using the SUID sandbox. | 215 // Not using the SUID sandbox. |
216 // Note that ~base::Process() will reset the internal value, but there's no | 216 // Note that ~base::Process() will reset the internal value, but there's no |
217 // real "handle" on POSIX so that is safe. | 217 // real "handle" on POSIX so that is safe. |
218 pid_ = process.Pid(); | 218 pid_ = process.Pid(); |
219 } | 219 } |
220 | 220 |
221 close(fds[1]); | 221 close(fds[1]); |
222 control_fd_ = fds[0]; | 222 control_fd_ = fds[0]; |
223 | 223 |
224 Pickle pickle; | 224 base::Pickle pickle; |
225 pickle.WriteInt(kZygoteCommandGetSandboxStatus); | 225 pickle.WriteInt(kZygoteCommandGetSandboxStatus); |
226 if (!SendMessage(pickle, NULL)) | 226 if (!SendMessage(pickle, NULL)) |
227 LOG(FATAL) << "Cannot communicate with zygote"; | 227 LOG(FATAL) << "Cannot communicate with zygote"; |
228 // We don't wait for the reply. We'll read it in ReadReply. | 228 // We don't wait for the reply. We'll read it in ReadReply. |
229 } | 229 } |
230 | 230 |
231 void ZygoteHostImpl::TearDownAfterLastChild() { | 231 void ZygoteHostImpl::TearDownAfterLastChild() { |
232 bool do_teardown = false; | 232 bool do_teardown = false; |
233 { | 233 { |
234 base::AutoLock lock(child_tracking_lock_); | 234 base::AutoLock lock(child_tracking_lock_); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 size_t num_erased = list_of_running_zygote_children_.erase(process); | 268 size_t num_erased = list_of_running_zygote_children_.erase(process); |
269 DCHECK_EQ(1U, num_erased); | 269 DCHECK_EQ(1U, num_erased); |
270 do_teardown = should_teardown_after_last_child_exits_ && | 270 do_teardown = should_teardown_after_last_child_exits_ && |
271 list_of_running_zygote_children_.empty(); | 271 list_of_running_zygote_children_.empty(); |
272 } | 272 } |
273 if (do_teardown) { | 273 if (do_teardown) { |
274 TearDown(); | 274 TearDown(); |
275 } | 275 } |
276 } | 276 } |
277 | 277 |
278 bool ZygoteHostImpl::SendMessage(const Pickle& data, | 278 bool ZygoteHostImpl::SendMessage(const base::Pickle& data, |
279 const std::vector<int>* fds) { | 279 const std::vector<int>* fds) { |
280 DCHECK_NE(-1, control_fd_); | 280 DCHECK_NE(-1, control_fd_); |
281 CHECK(data.size() <= kZygoteMaxMessageLength) | 281 CHECK(data.size() <= kZygoteMaxMessageLength) |
282 << "Trying to send too-large message to zygote (sending " << data.size() | 282 << "Trying to send too-large message to zygote (sending " << data.size() |
283 << " bytes, max is " << kZygoteMaxMessageLength << ")"; | 283 << " bytes, max is " << kZygoteMaxMessageLength << ")"; |
284 CHECK(!fds || fds->size() <= UnixDomainSocket::kMaxFileDescriptors) | 284 CHECK(!fds || fds->size() <= UnixDomainSocket::kMaxFileDescriptors) |
285 << "Trying to send message with too many file descriptors to zygote " | 285 << "Trying to send message with too many file descriptors to zygote " |
286 << "(sending " << fds->size() << ", max is " | 286 << "(sending " << fds->size() << ", max is " |
287 << UnixDomainSocket::kMaxFileDescriptors << ")"; | 287 << UnixDomainSocket::kMaxFileDescriptors << ")"; |
288 | 288 |
(...skipping 18 matching lines...) Expand all Loading... |
307 UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_); | 307 UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_); |
308 } | 308 } |
309 | 309 |
310 return HANDLE_EINTR(read(control_fd_, buf, buf_len)); | 310 return HANDLE_EINTR(read(control_fd_, buf, buf_len)); |
311 } | 311 } |
312 | 312 |
313 pid_t ZygoteHostImpl::ForkRequest(const std::vector<std::string>& argv, | 313 pid_t ZygoteHostImpl::ForkRequest(const std::vector<std::string>& argv, |
314 scoped_ptr<FileDescriptorInfo> mapping, | 314 scoped_ptr<FileDescriptorInfo> mapping, |
315 const std::string& process_type) { | 315 const std::string& process_type) { |
316 DCHECK(init_); | 316 DCHECK(init_); |
317 Pickle pickle; | 317 base::Pickle pickle; |
318 | 318 |
319 int raw_socks[2]; | 319 int raw_socks[2]; |
320 PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks)); | 320 PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks)); |
321 base::ScopedFD my_sock(raw_socks[0]); | 321 base::ScopedFD my_sock(raw_socks[0]); |
322 base::ScopedFD peer_sock(raw_socks[1]); | 322 base::ScopedFD peer_sock(raw_socks[1]); |
323 CHECK(UnixDomainSocket::EnableReceiveProcessId(my_sock.get())); | 323 CHECK(UnixDomainSocket::EnableReceiveProcessId(my_sock.get())); |
324 | 324 |
325 pickle.WriteInt(kZygoteCommandFork); | 325 pickle.WriteInt(kZygoteCommandFork); |
326 pickle.WriteString(process_type); | 326 pickle.WriteString(process_type); |
327 pickle.WriteInt(argv.size()); | 327 pickle.WriteInt(argv.size()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 sizeof(kZygoteChildPingMessage))) { | 371 sizeof(kZygoteChildPingMessage))) { |
372 // Zygote children should still be trustworthy when they're supposed to | 372 // Zygote children should still be trustworthy when they're supposed to |
373 // ping us, so something's broken if we don't receive a valid ping. | 373 // ping us, so something's broken if we don't receive a valid ping. |
374 LOG(ERROR) << "Did not receive ping from zygote child"; | 374 LOG(ERROR) << "Did not receive ping from zygote child"; |
375 NOTREACHED(); | 375 NOTREACHED(); |
376 real_pid = -1; | 376 real_pid = -1; |
377 } | 377 } |
378 my_sock.reset(); | 378 my_sock.reset(); |
379 | 379 |
380 // Always send PID back to zygote. | 380 // Always send PID back to zygote. |
381 Pickle pid_pickle; | 381 base::Pickle pid_pickle; |
382 pid_pickle.WriteInt(kZygoteCommandForkRealPID); | 382 pid_pickle.WriteInt(kZygoteCommandForkRealPID); |
383 pid_pickle.WriteInt(real_pid); | 383 pid_pickle.WriteInt(real_pid); |
384 if (!SendMessage(pid_pickle, NULL)) | 384 if (!SendMessage(pid_pickle, NULL)) |
385 return base::kNullProcessHandle; | 385 return base::kNullProcessHandle; |
386 } | 386 } |
387 | 387 |
388 // Read the reply, which pickles the PID and an optional UMA enumeration. | 388 // Read the reply, which pickles the PID and an optional UMA enumeration. |
389 static const unsigned kMaxReplyLength = 2048; | 389 static const unsigned kMaxReplyLength = 2048; |
390 char buf[kMaxReplyLength]; | 390 char buf[kMaxReplyLength]; |
391 const ssize_t len = ReadReply(buf, sizeof(buf)); | 391 const ssize_t len = ReadReply(buf, sizeof(buf)); |
392 | 392 |
393 Pickle reply_pickle(buf, len); | 393 base::Pickle reply_pickle(buf, len); |
394 PickleIterator iter(reply_pickle); | 394 base::PickleIterator iter(reply_pickle); |
395 if (len <= 0 || !iter.ReadInt(&pid)) | 395 if (len <= 0 || !iter.ReadInt(&pid)) |
396 return base::kNullProcessHandle; | 396 return base::kNullProcessHandle; |
397 | 397 |
398 // If there is a nonempty UMA name string, then there is a UMA | 398 // If there is a nonempty UMA name string, then there is a UMA |
399 // enumeration to record. | 399 // enumeration to record. |
400 std::string uma_name; | 400 std::string uma_name; |
401 int uma_sample; | 401 int uma_sample; |
402 int uma_boundary_value; | 402 int uma_boundary_value; |
403 if (iter.ReadString(&uma_name) && | 403 if (iter.ReadString(&uma_name) && |
404 !uma_name.empty() && | 404 !uma_name.empty() && |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 base::EnsureProcessGetsReaped(sandbox_helper_process.Pid()); | 506 base::EnsureProcessGetsReaped(sandbox_helper_process.Pid()); |
507 } else if (!use_suid_sandbox_for_adj_oom_score_) { | 507 } else if (!use_suid_sandbox_for_adj_oom_score_) { |
508 if (!base::AdjustOOMScore(pid, score)) | 508 if (!base::AdjustOOMScore(pid, score)) |
509 PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid; | 509 PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid; |
510 } | 510 } |
511 } | 511 } |
512 #endif | 512 #endif |
513 | 513 |
514 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) { | 514 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) { |
515 DCHECK(init_); | 515 DCHECK(init_); |
516 Pickle pickle; | 516 base::Pickle pickle; |
517 | 517 |
518 pickle.WriteInt(kZygoteCommandReap); | 518 pickle.WriteInt(kZygoteCommandReap); |
519 pickle.WriteInt(process); | 519 pickle.WriteInt(process); |
520 if (!SendMessage(pickle, NULL)) | 520 if (!SendMessage(pickle, NULL)) |
521 LOG(ERROR) << "Failed to send Reap message to zygote"; | 521 LOG(ERROR) << "Failed to send Reap message to zygote"; |
522 ZygoteChildDied(process); | 522 ZygoteChildDied(process); |
523 } | 523 } |
524 | 524 |
525 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus( | 525 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus( |
526 base::ProcessHandle handle, | 526 base::ProcessHandle handle, |
527 bool known_dead, | 527 bool known_dead, |
528 int* exit_code) { | 528 int* exit_code) { |
529 DCHECK(init_); | 529 DCHECK(init_); |
530 Pickle pickle; | 530 base::Pickle pickle; |
531 pickle.WriteInt(kZygoteCommandGetTerminationStatus); | 531 pickle.WriteInt(kZygoteCommandGetTerminationStatus); |
532 pickle.WriteBool(known_dead); | 532 pickle.WriteBool(known_dead); |
533 pickle.WriteInt(handle); | 533 pickle.WriteInt(handle); |
534 | 534 |
535 static const unsigned kMaxMessageLength = 128; | 535 static const unsigned kMaxMessageLength = 128; |
536 char buf[kMaxMessageLength]; | 536 char buf[kMaxMessageLength]; |
537 ssize_t len; | 537 ssize_t len; |
538 { | 538 { |
539 base::AutoLock lock(control_lock_); | 539 base::AutoLock lock(control_lock_); |
540 if (!SendMessage(pickle, NULL)) | 540 if (!SendMessage(pickle, NULL)) |
541 LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote"; | 541 LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote"; |
542 len = ReadReply(buf, sizeof(buf)); | 542 len = ReadReply(buf, sizeof(buf)); |
543 } | 543 } |
544 | 544 |
545 // Set this now to handle the error cases. | 545 // Set this now to handle the error cases. |
546 if (exit_code) | 546 if (exit_code) |
547 *exit_code = RESULT_CODE_NORMAL_EXIT; | 547 *exit_code = RESULT_CODE_NORMAL_EXIT; |
548 int status = base::TERMINATION_STATUS_NORMAL_TERMINATION; | 548 int status = base::TERMINATION_STATUS_NORMAL_TERMINATION; |
549 | 549 |
550 if (len == -1) { | 550 if (len == -1) { |
551 LOG(WARNING) << "Error reading message from zygote: " << errno; | 551 LOG(WARNING) << "Error reading message from zygote: " << errno; |
552 } else if (len == 0) { | 552 } else if (len == 0) { |
553 LOG(WARNING) << "Socket closed prematurely."; | 553 LOG(WARNING) << "Socket closed prematurely."; |
554 } else { | 554 } else { |
555 Pickle read_pickle(buf, len); | 555 base::Pickle read_pickle(buf, len); |
556 int tmp_status, tmp_exit_code; | 556 int tmp_status, tmp_exit_code; |
557 PickleIterator iter(read_pickle); | 557 base::PickleIterator iter(read_pickle); |
558 if (!iter.ReadInt(&tmp_status) || !iter.ReadInt(&tmp_exit_code)) { | 558 if (!iter.ReadInt(&tmp_status) || !iter.ReadInt(&tmp_exit_code)) { |
559 LOG(WARNING) | 559 LOG(WARNING) |
560 << "Error parsing GetTerminationStatus response from zygote."; | 560 << "Error parsing GetTerminationStatus response from zygote."; |
561 } else { | 561 } else { |
562 if (exit_code) | 562 if (exit_code) |
563 *exit_code = tmp_exit_code; | 563 *exit_code = tmp_exit_code; |
564 status = tmp_status; | 564 status = tmp_status; |
565 } | 565 } |
566 } | 566 } |
567 | 567 |
(...skipping 25 matching lines...) Expand all Loading... |
593 } | 593 } |
594 | 594 |
595 if (!sandbox::Credentials::CanCreateProcessInNewUserNS()) { | 595 if (!sandbox::Credentials::CanCreateProcessInNewUserNS()) { |
596 return false; | 596 return false; |
597 } | 597 } |
598 | 598 |
599 return true; | 599 return true; |
600 } | 600 } |
601 | 601 |
602 } // namespace content | 602 } // namespace content |
OLD | NEW |