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

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

Issue 11235068: Move the remaning files in content\common to the content namespace. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: 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>
(...skipping 21 matching lines...) Expand all
32 #include "content/public/common/content_switches.h" 32 #include "content/public/common/content_switches.h"
33 #include "content/public/common/result_codes.h" 33 #include "content/public/common/result_codes.h"
34 #include "sandbox/linux/suid/client/setuid_sandbox_client.h" 34 #include "sandbox/linux/suid/client/setuid_sandbox_client.h"
35 #include "sandbox/linux/suid/common/sandbox.h" 35 #include "sandbox/linux/suid/common/sandbox.h"
36 #include "ui/base/ui_base_switches.h" 36 #include "ui/base/ui_base_switches.h"
37 37
38 #if defined(USE_TCMALLOC) 38 #if defined(USE_TCMALLOC)
39 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h" 39 #include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
40 #endif 40 #endif
41 41
42 namespace content {
43
42 // static 44 // static
43 content::ZygoteHost* content::ZygoteHost::GetInstance() { 45 ZygoteHost* ZygoteHost::GetInstance() {
44 return ZygoteHostImpl::GetInstance(); 46 return ZygoteHostImpl::GetInstance();
45 } 47 }
46 48
47 ZygoteHostImpl::ZygoteHostImpl() 49 ZygoteHostImpl::ZygoteHostImpl()
48 : control_fd_(-1), 50 : control_fd_(-1),
49 pid_(-1), 51 pid_(-1),
50 init_(false), 52 init_(false),
51 using_suid_sandbox_(false), 53 using_suid_sandbox_(false),
52 have_read_sandbox_status_word_(false), 54 have_read_sandbox_status_word_(false),
53 sandbox_status_(0) {} 55 sandbox_status_(0) {}
(...skipping 21 matching lines...) Expand all
75 int fds[2]; 77 int fds[2];
76 #if defined(OS_FREEBSD) || defined(OS_OPENBSD) 78 #if defined(OS_FREEBSD) || defined(OS_OPENBSD)
77 // The BSDs often don't support SOCK_SEQPACKET yet, so fall back to 79 // The BSDs often don't support SOCK_SEQPACKET yet, so fall back to
78 // SOCK_DGRAM if necessary. 80 // SOCK_DGRAM if necessary.
79 if (socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) != 0) 81 if (socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) != 0)
80 CHECK(socketpair(PF_UNIX, SOCK_DGRAM, 0, fds) == 0); 82 CHECK(socketpair(PF_UNIX, SOCK_DGRAM, 0, fds) == 0);
81 #else 83 #else
82 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); 84 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
83 #endif 85 #endif
84 base::FileHandleMappingVector fds_to_map; 86 base::FileHandleMappingVector fds_to_map;
85 fds_to_map.push_back(std::make_pair(fds[1], content::kZygoteSocketPairFd)); 87 fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
86 88
87 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 89 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
88 if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) { 90 if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
89 cmd_line.PrependWrapper( 91 cmd_line.PrependWrapper(
90 browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix)); 92 browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix));
91 } 93 }
92 // Append any switches from the browser process that need to be forwarded on 94 // Append any switches from the browser process that need to be forwarded on
93 // to the zygote/renderers. 95 // to the zygote/renderers.
94 // Should this list be obtained from browser_render_process_host.cc? 96 // Should this list be obtained from browser_render_process_host.cc?
95 static const char* kForwardSwitches[] = { 97 static const char* kForwardSwitches[] = {
(...skipping 14 matching lines...) Expand all
110 112
111 switches::kNoSandbox, 113 switches::kNoSandbox,
112 114
113 #if !defined(OS_CHROMEOS) 115 #if !defined(OS_CHROMEOS)
114 switches::kEnableTouchEvents, 116 switches::kEnableTouchEvents,
115 #endif 117 #endif
116 }; 118 };
117 cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches, 119 cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
118 arraysize(kForwardSwitches)); 120 arraysize(kForwardSwitches));
119 121
120 content::GetContentClient()->browser()->AppendExtraCommandLineSwitches( 122 GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1);
121 &cmd_line, -1);
122 123
123 sandbox_binary_ = sandbox_cmd.c_str(); 124 sandbox_binary_ = sandbox_cmd.c_str();
124 125
125 if (!sandbox_cmd.empty()) { 126 if (!sandbox_cmd.empty()) {
126 struct stat st; 127 struct stat st;
127 if (stat(sandbox_binary_.c_str(), &st) != 0) { 128 if (stat(sandbox_binary_.c_str(), &st) != 0) {
128 LOG(FATAL) << "The SUID sandbox helper binary is missing: " 129 LOG(FATAL) << "The SUID sandbox helper binary is missing: "
129 << sandbox_binary_ << " Aborting now."; 130 << sandbox_binary_ << " Aborting now.";
130 } 131 }
131 132
(...skipping 15 matching lines...) Expand all
147 } 148 }
148 } else { 149 } else {
149 LOG(WARNING) << "Running without the SUID sandbox! See " 150 LOG(WARNING) << "Running without the SUID sandbox! See "
150 "http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment " 151 "http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment "
151 "for more information on developing with the sandbox on."; 152 "for more information on developing with the sandbox on.";
152 } 153 }
153 154
154 // Start up the sandbox host process and get the file descriptor for the 155 // Start up the sandbox host process and get the file descriptor for the
155 // renderers to talk to it. 156 // renderers to talk to it.
156 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); 157 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
157 fds_to_map.push_back(std::make_pair(sfd, content::kZygoteRendererSocketFd)); 158 fds_to_map.push_back(std::make_pair(sfd, kZygoteRendererSocketFd));
158 159
159 int dummy_fd = -1; 160 int dummy_fd = -1;
160 if (using_suid_sandbox_) { 161 if (using_suid_sandbox_) {
161 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); 162 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0);
162 CHECK(dummy_fd >= 0); 163 CHECK(dummy_fd >= 0);
163 fds_to_map.push_back(std::make_pair(dummy_fd, content::kZygoteIdFd)); 164 fds_to_map.push_back(std::make_pair(dummy_fd, kZygoteIdFd));
164 } 165 }
165 166
166 base::ProcessHandle process = -1; 167 base::ProcessHandle process = -1;
167 base::LaunchOptions options; 168 base::LaunchOptions options;
168 options.fds_to_remap = &fds_to_map; 169 options.fds_to_remap = &fds_to_map;
169 base::LaunchProcess(cmd_line.argv(), options, &process); 170 base::LaunchProcess(cmd_line.argv(), options, &process);
170 CHECK(process != -1) << "Failed to launch zygote process"; 171 CHECK(process != -1) << "Failed to launch zygote process";
171 172
172 if (using_suid_sandbox_) { 173 if (using_suid_sandbox_) {
173 // In the SUID sandbox, the real zygote is forked from the sandbox. 174 // In the SUID sandbox, the real zygote is forked from the sandbox.
174 // We need to look for it. 175 // We need to look for it.
175 // But first, wait for the zygote to tell us it's running. 176 // But first, wait for the zygote to tell us it's running.
176 // The sending code is in content/browser/zygote_main_linux.cc. 177 // The sending code is in content/browser/zygote_main_linux.cc.
177 std::vector<int> fds_vec; 178 std::vector<int> fds_vec;
178 const int kExpectedLength = sizeof(content::kZygoteHelloMessage); 179 const int kExpectedLength = sizeof(kZygoteHelloMessage);
179 char buf[kExpectedLength]; 180 char buf[kExpectedLength];
180 const ssize_t len = UnixDomainSocket::RecvMsg(fds[0], buf, sizeof(buf), 181 const ssize_t len = UnixDomainSocket::RecvMsg(fds[0], buf, sizeof(buf),
181 &fds_vec); 182 &fds_vec);
182 CHECK(len == kExpectedLength) << "Incorrect zygote magic length"; 183 CHECK(len == kExpectedLength) << "Incorrect zygote magic length";
183 CHECK(0 == strcmp(buf, content::kZygoteHelloMessage)) 184 CHECK(0 == strcmp(buf, kZygoteHelloMessage))
184 << "Incorrect zygote hello"; 185 << "Incorrect zygote hello";
185 186
186 std::string inode_output; 187 std::string inode_output;
187 ino_t inode = 0; 188 ino_t inode = 0;
188 // Figure out the inode for |dummy_fd|, close |dummy_fd| on our end, 189 // Figure out the inode for |dummy_fd|, close |dummy_fd| on our end,
189 // and find the zygote process holding |dummy_fd|. 190 // and find the zygote process holding |dummy_fd|.
190 if (base::FileDescriptorGetInode(&inode, dummy_fd)) { 191 if (base::FileDescriptorGetInode(&inode, dummy_fd)) {
191 close(dummy_fd); 192 close(dummy_fd);
192 std::vector<std::string> get_inode_cmdline; 193 std::vector<std::string> get_inode_cmdline;
193 get_inode_cmdline.push_back(sandbox_binary_); 194 get_inode_cmdline.push_back(sandbox_binary_);
(...skipping 13 matching lines...) Expand all
207 } 208 }
208 } else { 209 } else {
209 // Not using the SUID sandbox. 210 // Not using the SUID sandbox.
210 pid_ = process; 211 pid_ = process;
211 } 212 }
212 213
213 close(fds[1]); 214 close(fds[1]);
214 control_fd_ = fds[0]; 215 control_fd_ = fds[0];
215 216
216 Pickle pickle; 217 Pickle pickle;
217 pickle.WriteInt(content::kZygoteCommandGetSandboxStatus); 218 pickle.WriteInt(kZygoteCommandGetSandboxStatus);
218 if (!SendMessage(pickle, NULL)) 219 if (!SendMessage(pickle, NULL))
219 LOG(FATAL) << "Cannot communicate with zygote"; 220 LOG(FATAL) << "Cannot communicate with zygote";
220 // We don't wait for the reply. We'll read it in ReadReply. 221 // We don't wait for the reply. We'll read it in ReadReply.
221 } 222 }
222 223
223 bool ZygoteHostImpl::SendMessage(const Pickle& data, 224 bool ZygoteHostImpl::SendMessage(const Pickle& data,
224 const std::vector<int>* fds) { 225 const std::vector<int>* fds) {
225 CHECK(data.size() <= content::kZygoteMaxMessageLength) 226 CHECK(data.size() <= kZygoteMaxMessageLength)
226 << "Trying to send too-large message to zygote (sending " << data.size() 227 << "Trying to send too-large message to zygote (sending " << data.size()
227 << " bytes, max is " << content::kZygoteMaxMessageLength << ")"; 228 << " bytes, max is " << kZygoteMaxMessageLength << ")";
228 CHECK(!fds || fds->size() <= UnixDomainSocket::kMaxFileDescriptors) 229 CHECK(!fds || fds->size() <= UnixDomainSocket::kMaxFileDescriptors)
229 << "Trying to send message with too many file descriptors to zygote " 230 << "Trying to send message with too many file descriptors to zygote "
230 << "(sending " << fds->size() << ", max is " 231 << "(sending " << fds->size() << ", max is "
231 << UnixDomainSocket::kMaxFileDescriptors << ")"; 232 << UnixDomainSocket::kMaxFileDescriptors << ")";
232 233
233 return UnixDomainSocket::SendMsg(control_fd_, 234 return UnixDomainSocket::SendMsg(control_fd_,
234 data.data(), data.size(), 235 data.data(), data.size(),
235 fds ? *fds : std::vector<int>()); 236 fds ? *fds : std::vector<int>());
236 } 237 }
237 238
238 ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) { 239 ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) {
239 // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote, 240 // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
240 // but don't wait for the reply. Thus, the first time that we read from the 241 // but don't wait for the reply. Thus, the first time that we read from the
241 // zygote, we get the reply to that request. 242 // zygote, we get the reply to that request.
242 if (!have_read_sandbox_status_word_) { 243 if (!have_read_sandbox_status_word_) {
243 if (HANDLE_EINTR(read(control_fd_, &sandbox_status_, 244 if (HANDLE_EINTR(read(control_fd_, &sandbox_status_,
244 sizeof(sandbox_status_))) != 245 sizeof(sandbox_status_))) !=
245 sizeof(sandbox_status_)) { 246 sizeof(sandbox_status_)) {
246 return -1; 247 return -1;
247 } 248 }
248 have_read_sandbox_status_word_ = true; 249 have_read_sandbox_status_word_ = true;
249 } 250 }
250 251
251 return HANDLE_EINTR(read(control_fd_, buf, buf_len)); 252 return HANDLE_EINTR(read(control_fd_, buf, buf_len));
252 } 253 }
253 254
254 pid_t ZygoteHostImpl::ForkRequest( 255 pid_t ZygoteHostImpl::ForkRequest(
255 const std::vector<std::string>& argv, 256 const std::vector<std::string>& argv,
256 const std::vector<content::FileDescriptorInfo>& mapping, 257 const std::vector<FileDescriptorInfo>& mapping,
257 const std::string& process_type) { 258 const std::string& process_type) {
258 DCHECK(init_); 259 DCHECK(init_);
259 Pickle pickle; 260 Pickle pickle;
260 261
261 pickle.WriteInt(content::kZygoteCommandFork); 262 pickle.WriteInt(kZygoteCommandFork);
262 pickle.WriteString(process_type); 263 pickle.WriteString(process_type);
263 pickle.WriteInt(argv.size()); 264 pickle.WriteInt(argv.size());
264 for (std::vector<std::string>::const_iterator 265 for (std::vector<std::string>::const_iterator
265 i = argv.begin(); i != argv.end(); ++i) 266 i = argv.begin(); i != argv.end(); ++i)
266 pickle.WriteString(*i); 267 pickle.WriteString(*i);
267 268
268 pickle.WriteInt(mapping.size()); 269 pickle.WriteInt(mapping.size());
269 270
270 std::vector<int> fds; 271 std::vector<int> fds;
271 // Scoped pointers cannot be stored in containers, so we have to use a 272 // Scoped pointers cannot be stored in containers, so we have to use a
272 // linked_ptr. 273 // linked_ptr.
273 std::vector<linked_ptr<file_util::ScopedFD> > autodelete_fds; 274 std::vector<linked_ptr<file_util::ScopedFD> > autodelete_fds;
274 for (std::vector<content::FileDescriptorInfo>::const_iterator 275 for (std::vector<FileDescriptorInfo>::const_iterator
275 i = mapping.begin(); i != mapping.end(); ++i) { 276 i = mapping.begin(); i != mapping.end(); ++i) {
276 pickle.WriteUInt32(i->id); 277 pickle.WriteUInt32(i->id);
277 fds.push_back(i->fd.fd); 278 fds.push_back(i->fd.fd);
278 if (i->fd.auto_close) { 279 if (i->fd.auto_close) {
279 // Auto-close means we need to close the FDs after they habe been passed 280 // Auto-close means we need to close the FDs after they habe been passed
280 // to the other process. 281 // to the other process.
281 linked_ptr<file_util::ScopedFD> ptr( 282 linked_ptr<file_util::ScopedFD> ptr(
282 new file_util::ScopedFD(&(fds.back()))); 283 new file_util::ScopedFD(&(fds.back())));
283 autodelete_fds.push_back(ptr); 284 autodelete_fds.push_back(ptr);
284 } 285 }
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 // Low memory notification is currently only implemented on ChromeOS. 440 // Low memory notification is currently only implemented on ChromeOS.
440 NOTREACHED() << "AdjustLowMemoryMargin not implemented"; 441 NOTREACHED() << "AdjustLowMemoryMargin not implemented";
441 #endif // defined(OS_CHROMEOS) 442 #endif // defined(OS_CHROMEOS)
442 } 443 }
443 444
444 445
445 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) { 446 void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
446 DCHECK(init_); 447 DCHECK(init_);
447 Pickle pickle; 448 Pickle pickle;
448 449
449 pickle.WriteInt(content::kZygoteCommandReap); 450 pickle.WriteInt(kZygoteCommandReap);
450 pickle.WriteInt(process); 451 pickle.WriteInt(process);
451 if (!SendMessage(pickle, NULL)) 452 if (!SendMessage(pickle, NULL))
452 LOG(ERROR) << "Failed to send Reap message to zygote"; 453 LOG(ERROR) << "Failed to send Reap message to zygote";
453 } 454 }
454 455
455 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus( 456 base::TerminationStatus ZygoteHostImpl::GetTerminationStatus(
456 base::ProcessHandle handle, 457 base::ProcessHandle handle,
457 int* exit_code) { 458 int* exit_code) {
458 DCHECK(init_); 459 DCHECK(init_);
459 Pickle pickle; 460 Pickle pickle;
460 pickle.WriteInt(content::kZygoteCommandGetTerminationStatus); 461 pickle.WriteInt(kZygoteCommandGetTerminationStatus);
461 pickle.WriteInt(handle); 462 pickle.WriteInt(handle);
462 463
463 // Set this now to handle the early termination cases. 464 // Set this now to handle the early termination cases.
464 if (exit_code) 465 if (exit_code)
465 *exit_code = content::RESULT_CODE_NORMAL_EXIT; 466 *exit_code = RESULT_CODE_NORMAL_EXIT;
466 467
467 static const unsigned kMaxMessageLength = 128; 468 static const unsigned kMaxMessageLength = 128;
468 char buf[kMaxMessageLength]; 469 char buf[kMaxMessageLength];
469 ssize_t len; 470 ssize_t len;
470 { 471 {
471 base::AutoLock lock(control_lock_); 472 base::AutoLock lock(control_lock_);
472 if (!SendMessage(pickle, NULL)) 473 if (!SendMessage(pickle, NULL))
473 LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote"; 474 LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote";
474 len = ReadReply(buf, sizeof(buf)); 475 len = ReadReply(buf, sizeof(buf));
475 } 476 }
(...skipping 27 matching lines...) Expand all
503 504
504 pid_t ZygoteHostImpl::GetSandboxHelperPid() const { 505 pid_t ZygoteHostImpl::GetSandboxHelperPid() const {
505 return RenderSandboxHostLinux::GetInstance()->pid(); 506 return RenderSandboxHostLinux::GetInstance()->pid();
506 } 507 }
507 508
508 int ZygoteHostImpl::GetSandboxStatus() const { 509 int ZygoteHostImpl::GetSandboxStatus() const {
509 if (have_read_sandbox_status_word_) 510 if (have_read_sandbox_status_word_)
510 return sandbox_status_; 511 return sandbox_status_;
511 return 0; 512 return 0;
512 } 513 }
514
515 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/zygote_host/zygote_host_impl_linux.h ('k') | content/common/content_param_traits.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698