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

Side by Side Diff: content/zygote/zygote_linux.cc

Issue 258543006: Change UnixDomainSocket::RecvMsg to return ScopedVector<base::ScopedFD> (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix #include directives for IWYU Created 6 years, 8 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/zygote/zygote_linux.h" 5 #include "content/zygote/zygote_linux.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <string.h> 8 #include <string.h>
9 #include <sys/socket.h> 9 #include <sys/socket.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
11 #include <sys/wait.h> 11 #include <sys/wait.h>
12 12
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "base/file_util.h" 15 #include "base/file_util.h"
16 #include "base/linux_util.h" 16 #include "base/linux_util.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/macros.h"
18 #include "base/pickle.h" 19 #include "base/pickle.h"
19 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
20 #include "base/posix/global_descriptors.h" 21 #include "base/posix/global_descriptors.h"
21 #include "base/posix/unix_domain_socket_linux.h" 22 #include "base/posix/unix_domain_socket_linux.h"
22 #include "base/process/kill.h" 23 #include "base/process/kill.h"
23 #include "content/common/child_process_sandbox_support_impl_linux.h" 24 #include "content/common/child_process_sandbox_support_impl_linux.h"
24 #include "content/common/sandbox_linux/sandbox_linux.h" 25 #include "content/common/sandbox_linux/sandbox_linux.h"
25 #include "content/common/set_process_title.h" 26 #include "content/common/set_process_title.h"
26 #include "content/common/zygote_commands_linux.h" 27 #include "content/common/zygote_commands_linux.h"
27 #include "content/public/common/content_descriptors.h" 28 #include "content/public/common/content_descriptors.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 } 116 }
116 *process_info = it->second; 117 *process_info = it->second;
117 return true; 118 return true;
118 } 119 }
119 120
120 bool Zygote::UsingSUIDSandbox() const { 121 bool Zygote::UsingSUIDSandbox() const {
121 return sandbox_flags_ & kSandboxLinuxSUID; 122 return sandbox_flags_ & kSandboxLinuxSUID;
122 } 123 }
123 124
124 bool Zygote::HandleRequestFromBrowser(int fd) { 125 bool Zygote::HandleRequestFromBrowser(int fd) {
125 std::vector<int> fds; 126 ScopedVector<base::ScopedFD> fds;
126 char buf[kZygoteMaxMessageLength]; 127 char buf[kZygoteMaxMessageLength];
127 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds); 128 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
128 129
129 if (len == 0 || (len == -1 && errno == ECONNRESET)) { 130 if (len == 0 || (len == -1 && errno == ECONNRESET)) {
130 // EOF from the browser. We should die. 131 // EOF from the browser. We should die.
131 _exit(0); 132 _exit(0);
132 return false; 133 return false;
133 } 134 }
134 135
135 if (len == -1) { 136 if (len == -1) {
136 PLOG(ERROR) << "Error reading message from browser"; 137 PLOG(ERROR) << "Error reading message from browser";
137 return false; 138 return false;
138 } 139 }
139 140
140 Pickle pickle(buf, len); 141 Pickle pickle(buf, len);
141 PickleIterator iter(pickle); 142 PickleIterator iter(pickle);
142 143
143 int kind; 144 int kind;
144 if (pickle.ReadInt(&iter, &kind)) { 145 if (pickle.ReadInt(&iter, &kind)) {
145 switch (kind) { 146 switch (kind) {
146 case kZygoteCommandFork: 147 case kZygoteCommandFork:
147 // This function call can return multiple times, once per fork(). 148 // This function call can return multiple times, once per fork().
148 return HandleForkRequest(fd, pickle, iter, fds); 149 return HandleForkRequest(fd, pickle, iter, fds.Pass());
149 150
150 case kZygoteCommandReap: 151 case kZygoteCommandReap:
151 if (!fds.empty()) 152 if (!fds.empty())
152 break; 153 break;
153 HandleReapRequest(fd, pickle, iter); 154 HandleReapRequest(fd, pickle, iter);
154 return false; 155 return false;
155 case kZygoteCommandGetTerminationStatus: 156 case kZygoteCommandGetTerminationStatus:
156 if (!fds.empty()) 157 if (!fds.empty())
157 break; 158 break;
158 HandleGetTerminationStatus(fd, pickle, iter); 159 HandleGetTerminationStatus(fd, pickle, iter);
159 return false; 160 return false;
160 case kZygoteCommandGetSandboxStatus: 161 case kZygoteCommandGetSandboxStatus:
161 HandleGetSandboxStatus(fd, pickle, iter); 162 HandleGetSandboxStatus(fd, pickle, iter);
162 return false; 163 return false;
163 default: 164 default:
164 NOTREACHED(); 165 NOTREACHED();
165 break; 166 break;
166 } 167 }
167 } 168 }
168 169
169 LOG(WARNING) << "Error parsing message from browser"; 170 LOG(WARNING) << "Error parsing message from browser";
170 for (std::vector<int>::const_iterator
171 i = fds.begin(); i != fds.end(); ++i)
172 close(*i);
173 return false; 171 return false;
174 } 172 }
175 173
176 // TODO(jln): remove callers to this broken API. See crbug.com/274855. 174 // TODO(jln): remove callers to this broken API. See crbug.com/274855.
177 void Zygote::HandleReapRequest(int fd, 175 void Zygote::HandleReapRequest(int fd,
178 const Pickle& pickle, 176 const Pickle& pickle,
179 PickleIterator iter) { 177 PickleIterator iter) {
180 base::ProcessId child; 178 base::ProcessId child;
181 179
182 if (!pickle.ReadInt(&iter, &child)) { 180 if (!pickle.ReadInt(&iter, &child)) {
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 close(dummy_fd); 430 close(dummy_fd);
433 if (pipe_fds[0] >= 0) 431 if (pipe_fds[0] >= 0)
434 close(pipe_fds[0]); 432 close(pipe_fds[0]);
435 if (pipe_fds[1] >= 0) 433 if (pipe_fds[1] >= 0)
436 close(pipe_fds[1]); 434 close(pipe_fds[1]);
437 return -1; 435 return -1;
438 } 436 }
439 437
440 base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle, 438 base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle,
441 PickleIterator iter, 439 PickleIterator iter,
442 std::vector<int>& fds, 440 ScopedVector<base::ScopedFD> fds,
443 std::string* uma_name, 441 std::string* uma_name,
444 int* uma_sample, 442 int* uma_sample,
445 int* uma_boundary_value) { 443 int* uma_boundary_value) {
446 std::vector<std::string> args; 444 std::vector<std::string> args;
447 int argc = 0; 445 int argc = 0;
448 int numfds = 0; 446 int numfds = 0;
449 base::GlobalDescriptors::Mapping mapping; 447 base::GlobalDescriptors::Mapping mapping;
450 std::string process_type; 448 std::string process_type;
451 std::string channel_id; 449 std::string channel_id;
452 const std::string channel_id_prefix = std::string("--") 450 const std::string channel_id_prefix = std::string("--")
(...skipping 15 matching lines...) Expand all
468 466
469 if (!pickle.ReadInt(&iter, &numfds)) 467 if (!pickle.ReadInt(&iter, &numfds))
470 return -1; 468 return -1;
471 if (numfds != static_cast<int>(fds.size())) 469 if (numfds != static_cast<int>(fds.size()))
472 return -1; 470 return -1;
473 471
474 for (int i = 0; i < numfds; ++i) { 472 for (int i = 0; i < numfds; ++i) {
475 base::GlobalDescriptors::Key key; 473 base::GlobalDescriptors::Key key;
476 if (!pickle.ReadUInt32(&iter, &key)) 474 if (!pickle.ReadUInt32(&iter, &key))
477 return -1; 475 return -1;
478 mapping.push_back(std::make_pair(key, fds[i])); 476 mapping.push_back(std::make_pair(key, fds[i]->get()));
479 } 477 }
480 478
481 mapping.push_back(std::make_pair( 479 mapping.push_back(std::make_pair(
482 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); 480 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
483 481
484 // Returns twice, once per process. 482 // Returns twice, once per process.
485 base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id, 483 base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id,
486 uma_name, uma_sample, 484 uma_name, uma_sample,
487 uma_boundary_value); 485 uma_boundary_value);
488 if (!child_pid) { 486 if (!child_pid) {
489 // This is the child process. 487 // This is the child process.
490 488
491 close(kZygoteSocketPairFd); // Our socket from the browser. 489 close(kZygoteSocketPairFd); // Our socket from the browser.
492 if (UsingSUIDSandbox()) 490 if (UsingSUIDSandbox())
493 close(kZygoteIdFd); // Another socket from the browser. 491 close(kZygoteIdFd); // Another socket from the browser.
492
493 // Pass ownership of file descriptors from fds to GlobalDescriptors.
494 for (ScopedVector<base::ScopedFD>::iterator i = fds.begin(); i != fds.end();
495 ++i)
496 ignore_result((*i)->release());
494 base::GlobalDescriptors::GetInstance()->Reset(mapping); 497 base::GlobalDescriptors::GetInstance()->Reset(mapping);
495 498
496 // Reset the process-wide command line to our new command line. 499 // Reset the process-wide command line to our new command line.
497 CommandLine::Reset(); 500 CommandLine::Reset();
498 CommandLine::Init(0, NULL); 501 CommandLine::Init(0, NULL);
499 CommandLine::ForCurrentProcess()->InitFromArgv(args); 502 CommandLine::ForCurrentProcess()->InitFromArgv(args);
500 503
501 // Update the process title. The argv was already cached by the call to 504 // Update the process title. The argv was already cached by the call to
502 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here 505 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
503 // (we don't have the original argv at this point). 506 // (we don't have the original argv at this point).
504 SetProcessTitleFromCommandLine(NULL); 507 SetProcessTitleFromCommandLine(NULL);
505 } else if (child_pid < 0) { 508 } else if (child_pid < 0) {
506 LOG(ERROR) << "Zygote could not fork: process_type " << process_type 509 LOG(ERROR) << "Zygote could not fork: process_type " << process_type
507 << " numfds " << numfds << " child_pid " << child_pid; 510 << " numfds " << numfds << " child_pid " << child_pid;
508 } 511 }
509 return child_pid; 512 return child_pid;
510 } 513 }
511 514
512 bool Zygote::HandleForkRequest(int fd, 515 bool Zygote::HandleForkRequest(int fd,
513 const Pickle& pickle, 516 const Pickle& pickle,
514 PickleIterator iter, 517 PickleIterator iter,
515 std::vector<int>& fds) { 518 ScopedVector<base::ScopedFD> fds) {
516 std::string uma_name; 519 std::string uma_name;
517 int uma_sample; 520 int uma_sample;
518 int uma_boundary_value; 521 int uma_boundary_value;
519 base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds, 522 base::ProcessId child_pid = ReadArgsAndFork(
520 &uma_name, &uma_sample, 523 pickle, iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value);
521 &uma_boundary_value);
522 if (child_pid == 0) 524 if (child_pid == 0)
523 return true; 525 return true;
524 for (std::vector<int>::const_iterator
525 i = fds.begin(); i != fds.end(); ++i)
526 close(*i);
527 if (uma_name.empty()) { 526 if (uma_name.empty()) {
528 // There is no UMA report from this particular fork. 527 // There is no UMA report from this particular fork.
529 // Use the initial UMA report if any, and clear that record for next time. 528 // Use the initial UMA report if any, and clear that record for next time.
530 // Note the swap method here is the efficient way to do this, since 529 // Note the swap method here is the efficient way to do this, since
531 // we know uma_name is empty. 530 // we know uma_name is empty.
532 uma_name.swap(initial_uma_name_); 531 uma_name.swap(initial_uma_name_);
533 uma_sample = initial_uma_sample_; 532 uma_sample = initial_uma_sample_;
534 uma_boundary_value = initial_uma_boundary_value_; 533 uma_boundary_value = initial_uma_boundary_value_;
535 } 534 }
536 // Must always send reply, as ZygoteHost blocks while waiting for it. 535 // Must always send reply, as ZygoteHost blocks while waiting for it.
(...skipping 15 matching lines...) Expand all
552 PickleIterator iter) { 551 PickleIterator iter) {
553 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != 552 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
554 sizeof(sandbox_flags_)) { 553 sizeof(sandbox_flags_)) {
555 PLOG(ERROR) << "write"; 554 PLOG(ERROR) << "write";
556 } 555 }
557 556
558 return false; 557 return false;
559 } 558 }
560 559
561 } // namespace content 560 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698