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

Side by Side Diff: content/browser/zygote_host/zygote_host_impl_linux.cc

Issue 11108019: linux: Crash browser on too-big messages to zygote. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update CHECKs Created 8 years, 2 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 "content/browser/zygote_host/zygote_host_impl_linux.h" 5 #include "content/browser/zygote_host/zygote_host_impl_linux.h"
6 6
7 #include <sys/socket.h> 7 #include <sys/socket.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include "base/base_switches.h" 12 #include "base/base_switches.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/eintr_wrapper.h" 14 #include "base/eintr_wrapper.h"
15 #include "base/environment.h" 15 #include "base/environment.h"
16 #include "base/file_util.h" 16 #include "base/file_util.h"
17 #include "base/linux_util.h" 17 #include "base/linux_util.h"
18 #include "base/logging.h" 18 #include "base/logging.h"
19 #include "base/memory/linked_ptr.h" 19 #include "base/memory/linked_ptr.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/metrics/histogram.h" 21 #include "base/metrics/histogram.h"
22 #include "base/path_service.h" 22 #include "base/path_service.h"
23 #include "base/pickle.h"
24 #include "base/posix/unix_domain_socket.h" 23 #include "base/posix/unix_domain_socket.h"
25 #include "base/process_util.h" 24 #include "base/process_util.h"
26 #include "base/string_number_conversions.h" 25 #include "base/string_number_conversions.h"
27 #include "base/string_util.h" 26 #include "base/string_util.h"
28 #include "base/time.h" 27 #include "base/time.h"
29 #include "base/utf_string_conversions.h" 28 #include "base/utf_string_conversions.h"
30 #include "content/browser/renderer_host/render_sandbox_host_linux.h" 29 #include "content/browser/renderer_host/render_sandbox_host_linux.h"
31 #include "content/common/zygote_commands_linux.h" 30 #include "content/common/zygote_commands_linux.h"
32 #include "content/public/browser/content_browser_client.h" 31 #include "content/public/browser/content_browser_client.h"
33 #include "content/public/common/content_switches.h" 32 #include "content/public/common/content_switches.h"
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 153
155 // Start up the sandbox host process and get the file descriptor for the 154 // Start up the sandbox host process and get the file descriptor for the
156 // renderers to talk to it. 155 // renderers to talk to it.
157 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); 156 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
158 fds_to_map.push_back(std::make_pair(sfd, content::kZygoteRendererSocketFd)); 157 fds_to_map.push_back(std::make_pair(sfd, content::kZygoteRendererSocketFd));
159 158
160 int dummy_fd = -1; 159 int dummy_fd = -1;
161 if (using_suid_sandbox_) { 160 if (using_suid_sandbox_) {
162 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); 161 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0);
163 CHECK(dummy_fd >= 0); 162 CHECK(dummy_fd >= 0);
164 fds_to_map.push_back(std::make_pair(dummy_fd, 163 fds_to_map.push_back(std::make_pair(dummy_fd, content::kZygoteIdFd));
165 content::kZygoteIdFd));
166 } 164 }
167 165
168 base::ProcessHandle process = -1; 166 base::ProcessHandle process = -1;
169 base::LaunchOptions options; 167 base::LaunchOptions options;
170 options.fds_to_remap = &fds_to_map; 168 options.fds_to_remap = &fds_to_map;
171 base::LaunchProcess(cmd_line.argv(), options, &process); 169 base::LaunchProcess(cmd_line.argv(), options, &process);
172 CHECK(process != -1) << "Failed to launch zygote process"; 170 CHECK(process != -1) << "Failed to launch zygote process";
173 171
174 if (using_suid_sandbox_) { 172 if (using_suid_sandbox_) {
175 // In the SUID sandbox, the real zygote is forked from the sandbox. 173 // In the SUID sandbox, the real zygote is forked from the sandbox.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 } else { 208 } else {
211 // Not using the SUID sandbox. 209 // Not using the SUID sandbox.
212 pid_ = process; 210 pid_ = process;
213 } 211 }
214 212
215 close(fds[1]); 213 close(fds[1]);
216 control_fd_ = fds[0]; 214 control_fd_ = fds[0];
217 215
218 Pickle pickle; 216 Pickle pickle;
219 pickle.WriteInt(content::kZygoteCommandGetSandboxStatus); 217 pickle.WriteInt(content::kZygoteCommandGetSandboxStatus);
220 std::vector<int> empty_fds; 218 if (!SendMessage(pickle, NULL))
221 if (!UnixDomainSocket::SendMsg(control_fd_, pickle.data(), pickle.size(),
222 empty_fds))
223 LOG(FATAL) << "Cannot communicate with zygote"; 219 LOG(FATAL) << "Cannot communicate with zygote";
224 // We don't wait for the reply. We'll read it in ReadReply. 220 // We don't wait for the reply. We'll read it in ReadReply.
225 } 221 }
226 222
223 bool ZygoteHostImpl::SendMessage(const Pickle& data,
224 const std::vector<int>* fds) {
225 CHECK(data.size() <= content::kZygoteMaxMessageLength)
226 << "Trying to send too-large message to zygote (sending " << data.size()
227 << " bytes, max is " << content::kZygoteMaxMessageLength << ")";
228 CHECK(!fds || fds->size() <= UnixDomainSocket::kMaxFileDescriptors)
229 << "Trying to send message with too many file descriptors to zygote "
230 << "(sending " << fds->size() << ", max is "
231 << UnixDomainSocket::kMaxFileDescriptors << ")";
232
233 return UnixDomainSocket::SendMsg(control_fd_,
234 data.data(), data.size(),
235 fds ? *fds : std::vector<int>());
236 }
237
227 ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) { 238 ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) {
228 // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote, 239 // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
229 // but don't wait for the reply. Thus, the first time that we read from the 240 // but don't wait for the reply. Thus, the first time that we read from the
230 // zygote, we get the reply to that request. 241 // zygote, we get the reply to that request.
231 if (!have_read_sandbox_status_word_) { 242 if (!have_read_sandbox_status_word_) {
232 if (HANDLE_EINTR(read(control_fd_, &sandbox_status_, 243 if (HANDLE_EINTR(read(control_fd_, &sandbox_status_,
233 sizeof(sandbox_status_))) != 244 sizeof(sandbox_status_))) !=
234 sizeof(sandbox_status_)) { 245 sizeof(sandbox_status_)) {
235 return -1; 246 return -1;
236 } 247 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 // to the other process. 280 // to the other process.
270 linked_ptr<file_util::ScopedFD> ptr( 281 linked_ptr<file_util::ScopedFD> ptr(
271 new file_util::ScopedFD(&(fds.back()))); 282 new file_util::ScopedFD(&(fds.back())));
272 autodelete_fds.push_back(ptr); 283 autodelete_fds.push_back(ptr);
273 } 284 }
274 } 285 }
275 286
276 pid_t pid; 287 pid_t pid;
277 { 288 {
278 base::AutoLock lock(control_lock_); 289 base::AutoLock lock(control_lock_);
279 if (!UnixDomainSocket::SendMsg(control_fd_, pickle.data(), pickle.size(), 290 if (!SendMessage(pickle, &fds))
280 fds))
281 return base::kNullProcessHandle; 291 return base::kNullProcessHandle;
282 292
283 // Read the reply, which pickles the PID and an optional UMA enumeration. 293 // Read the reply, which pickles the PID and an optional UMA enumeration.
284 static const unsigned kMaxReplyLength = 2048; 294 static const unsigned kMaxReplyLength = 2048;
285 char buf[kMaxReplyLength]; 295 char buf[kMaxReplyLength];
286 const ssize_t len = ReadReply(buf, sizeof(buf)); 296 const ssize_t len = ReadReply(buf, sizeof(buf));
287 297
288 Pickle reply_pickle(buf, len); 298 Pickle reply_pickle(buf, len);
289 PickleIterator iter(reply_pickle); 299 PickleIterator iter(reply_pickle);
290 if (len <= 0 || !reply_pickle.ReadInt(&iter, &pid)) 300 if (len <= 0 || !reply_pickle.ReadInt(&iter, &pid))
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 #endif // defined(OS_CHROMEOS) 441 #endif // defined(OS_CHROMEOS)
432 } 442 }
433 443
434 444
435 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) { 445 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
436 DCHECK(init_); 446 DCHECK(init_);
437 Pickle pickle; 447 Pickle pickle;
438 448
439 pickle.WriteInt(content::kZygoteCommandReap); 449 pickle.WriteInt(content::kZygoteCommandReap);
440 pickle.WriteInt(process); 450 pickle.WriteInt(process);
441 451 if (!SendMessage(pickle, NULL))
442 if (HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size())) < 0) 452 LOG(ERROR) << "Failed to send Reap message to zygote";
443 PLOG(ERROR) << "write";
444 } 453 }
445 454
446 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus( 455 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus(
447 base::ProcessHandle handle, 456 base::ProcessHandle handle,
448 int* exit_code) { 457 int* exit_code) {
449 DCHECK(init_); 458 DCHECK(init_);
450 Pickle pickle; 459 Pickle pickle;
451 pickle.WriteInt(content::kZygoteCommandGetTerminationStatus); 460 pickle.WriteInt(content::kZygoteCommandGetTerminationStatus);
452 pickle.WriteInt(handle); 461 pickle.WriteInt(handle);
453 462
454 // Set this now to handle the early termination cases. 463 // Set this now to handle the early termination cases.
455 if (exit_code) 464 if (exit_code)
456 *exit_code = content::RESULT_CODE_NORMAL_EXIT; 465 *exit_code = content::RESULT_CODE_NORMAL_EXIT;
457 466
458 static const unsigned kMaxMessageLength = 128; 467 static const unsigned kMaxMessageLength = 128;
459 char buf[kMaxMessageLength]; 468 char buf[kMaxMessageLength];
460 ssize_t len; 469 ssize_t len;
461 { 470 {
462 base::AutoLock lock(control_lock_); 471 base::AutoLock lock(control_lock_);
463 if (HANDLE_EINTR(write(control_fd_, pickle.data(), pickle.size())) < 0) 472 if (!SendMessage(pickle, NULL))
464 PLOG(ERROR) << "write"; 473 LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote";
465
466 len = ReadReply(buf, sizeof(buf)); 474 len = ReadReply(buf, sizeof(buf));
467 } 475 }
468 476
469 if (len == -1) { 477 if (len == -1) {
470 LOG(WARNING) << "Error reading message from zygote: " << errno; 478 LOG(WARNING) << "Error reading message from zygote: " << errno;
471 return base::TERMINATION_STATUS_NORMAL_TERMINATION; 479 return base::TERMINATION_STATUS_NORMAL_TERMINATION;
472 } else if (len == 0) { 480 } else if (len == 0) {
473 LOG(WARNING) << "Socket closed prematurely."; 481 LOG(WARNING) << "Socket closed prematurely.";
474 return base::TERMINATION_STATUS_NORMAL_TERMINATION; 482 return base::TERMINATION_STATUS_NORMAL_TERMINATION;
475 } 483 }
(...skipping 19 matching lines...) Expand all
495 503
496 pid_t ZygoteHostImpl::GetSandboxHelperPid() const { 504 pid_t ZygoteHostImpl::GetSandboxHelperPid() const {
497 return RenderSandboxHostLinux::GetInstance()->pid(); 505 return RenderSandboxHostLinux::GetInstance()->pid();
498 } 506 }
499 507
500 int ZygoteHostImpl::GetSandboxStatus() const { 508 int ZygoteHostImpl::GetSandboxStatus() const {
501 if (have_read_sandbox_status_word_) 509 if (have_read_sandbox_status_word_)
502 return sandbox_status_; 510 return sandbox_status_;
503 return 0; 511 return 0;
504 } 512 }
OLDNEW
« no previous file with comments | « content/browser/zygote_host/zygote_host_impl_linux.h ('k') | content/common/zygote_commands_linux.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698