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_impl_linux.h" | 5 #include "content/browser/zygote_host_impl_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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 _exit(0); | 162 _exit(0); |
163 return false; | 163 return false; |
164 } | 164 } |
165 | 165 |
166 if (len == -1) { | 166 if (len == -1) { |
167 PLOG(ERROR) << "Error reading message from browser"; | 167 PLOG(ERROR) << "Error reading message from browser"; |
168 return false; | 168 return false; |
169 } | 169 } |
170 | 170 |
171 Pickle pickle(buf, len); | 171 Pickle pickle(buf, len); |
172 void* iter = NULL; | 172 PickleIterator iter(pickle); |
173 | 173 |
174 int kind; | 174 int kind; |
175 if (pickle.ReadInt(&iter, &kind)) { | 175 if (pickle.ReadInt(&iter, &kind)) { |
176 switch (kind) { | 176 switch (kind) { |
177 case ZygoteHostImpl::kCmdFork: | 177 case ZygoteHostImpl::kCmdFork: |
178 // This function call can return multiple times, once per fork(). | 178 // This function call can return multiple times, once per fork(). |
179 return HandleForkRequest(fd, pickle, iter, fds); | 179 return HandleForkRequest(fd, pickle, iter, fds); |
180 | 180 |
181 case ZygoteHostImpl::kCmdReap: | 181 case ZygoteHostImpl::kCmdReap: |
182 if (!fds.empty()) | 182 if (!fds.empty()) |
(...skipping 14 matching lines...) Expand all Loading... |
197 } | 197 } |
198 } | 198 } |
199 | 199 |
200 LOG(WARNING) << "Error parsing message from browser"; | 200 LOG(WARNING) << "Error parsing message from browser"; |
201 for (std::vector<int>::const_iterator | 201 for (std::vector<int>::const_iterator |
202 i = fds.begin(); i != fds.end(); ++i) | 202 i = fds.begin(); i != fds.end(); ++i) |
203 close(*i); | 203 close(*i); |
204 return false; | 204 return false; |
205 } | 205 } |
206 | 206 |
207 void HandleReapRequest(int fd, const Pickle& pickle, void* iter) { | 207 void HandleReapRequest(int fd, const Pickle& pickle, PickleIterator iter) { |
208 base::ProcessId child; | 208 base::ProcessId child; |
209 base::ProcessId actual_child; | 209 base::ProcessId actual_child; |
210 | 210 |
211 if (!pickle.ReadInt(&iter, &child)) { | 211 if (!pickle.ReadInt(&iter, &child)) { |
212 LOG(WARNING) << "Error parsing reap request from browser"; | 212 LOG(WARNING) << "Error parsing reap request from browser"; |
213 return; | 213 return; |
214 } | 214 } |
215 | 215 |
216 if (g_suid_sandbox_active) { | 216 if (g_suid_sandbox_active) { |
217 actual_child = real_pids_to_sandbox_pids[child]; | 217 actual_child = real_pids_to_sandbox_pids[child]; |
218 if (!actual_child) | 218 if (!actual_child) |
219 return; | 219 return; |
220 real_pids_to_sandbox_pids.erase(child); | 220 real_pids_to_sandbox_pids.erase(child); |
221 } else { | 221 } else { |
222 actual_child = child; | 222 actual_child = child; |
223 } | 223 } |
224 | 224 |
225 base::EnsureProcessTerminated(actual_child); | 225 base::EnsureProcessTerminated(actual_child); |
226 } | 226 } |
227 | 227 |
228 void HandleGetTerminationStatus(int fd, const Pickle& pickle, void* iter) { | 228 void HandleGetTerminationStatus(int fd, |
| 229 const Pickle& pickle, |
| 230 PickleIterator iter) { |
229 base::ProcessHandle child; | 231 base::ProcessHandle child; |
230 | 232 |
231 if (!pickle.ReadInt(&iter, &child)) { | 233 if (!pickle.ReadInt(&iter, &child)) { |
232 LOG(WARNING) << "Error parsing GetTerminationStatus request " | 234 LOG(WARNING) << "Error parsing GetTerminationStatus request " |
233 << "from browser"; | 235 << "from browser"; |
234 return; | 236 return; |
235 } | 237 } |
236 | 238 |
237 base::TerminationStatus status; | 239 base::TerminationStatus status; |
238 int exit_code; | 240 int exit_code; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 | 342 |
341 const ssize_t r = UnixDomainSocket::SendRecvMsg( | 343 const ssize_t r = UnixDomainSocket::SendRecvMsg( |
342 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, | 344 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, |
343 request); | 345 request); |
344 if (r == -1) { | 346 if (r == -1) { |
345 LOG(ERROR) << "Failed to get child process's real PID"; | 347 LOG(ERROR) << "Failed to get child process's real PID"; |
346 goto error; | 348 goto error; |
347 } | 349 } |
348 | 350 |
349 Pickle reply(reinterpret_cast<char*>(reply_buf), r); | 351 Pickle reply(reinterpret_cast<char*>(reply_buf), r); |
350 void* iter = NULL; | 352 PickleIterator iter(reply); |
351 if (!reply.ReadInt(&iter, &real_pid)) | 353 if (!reply.ReadInt(&iter, &real_pid)) |
352 goto error; | 354 goto error; |
353 if (real_pid <= 0) { | 355 if (real_pid <= 0) { |
354 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? | 356 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? |
355 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; | 357 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; |
356 goto error; | 358 goto error; |
357 } | 359 } |
358 real_pids_to_sandbox_pids[real_pid] = pid; | 360 real_pids_to_sandbox_pids[real_pid] = pid; |
359 } | 361 } |
360 if (use_helper) { | 362 if (use_helper) { |
(...skipping 25 matching lines...) Expand all Loading... |
386 close(pipe_fds[0]); | 388 close(pipe_fds[0]); |
387 if (pipe_fds[1] >= 0) | 389 if (pipe_fds[1] >= 0) |
388 close(pipe_fds[1]); | 390 close(pipe_fds[1]); |
389 return -1; | 391 return -1; |
390 } | 392 } |
391 | 393 |
392 // Unpacks process type and arguments from |pickle| and forks a new process. | 394 // Unpacks process type and arguments from |pickle| and forks a new process. |
393 // Returns -1 on error, otherwise returns twice, returning 0 to the child | 395 // Returns -1 on error, otherwise returns twice, returning 0 to the child |
394 // process and the child process ID to the parent process, like fork(). | 396 // process and the child process ID to the parent process, like fork(). |
395 base::ProcessId ReadArgsAndFork(const Pickle& pickle, | 397 base::ProcessId ReadArgsAndFork(const Pickle& pickle, |
396 void* iter, | 398 PickleIterator iter, |
397 std::vector<int>& fds, | 399 std::vector<int>& fds, |
398 std::string* uma_name, | 400 std::string* uma_name, |
399 int* uma_sample, | 401 int* uma_sample, |
400 int* uma_boundary_value) { | 402 int* uma_boundary_value) { |
401 std::vector<std::string> args; | 403 std::vector<std::string> args; |
402 int argc = 0; | 404 int argc = 0; |
403 int numfds = 0; | 405 int numfds = 0; |
404 base::GlobalDescriptors::Mapping mapping; | 406 base::GlobalDescriptors::Mapping mapping; |
405 std::string process_type; | 407 std::string process_type; |
406 std::string channel_id; | 408 std::string channel_id; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 << " numfds " << numfds << " child_pid " << child_pid; | 481 << " numfds " << numfds << " child_pid " << child_pid; |
480 } | 482 } |
481 return child_pid; | 483 return child_pid; |
482 } | 484 } |
483 | 485 |
484 // Handle a 'fork' request from the browser: this means that the browser | 486 // Handle a 'fork' request from the browser: this means that the browser |
485 // wishes to start a new renderer. Returns true if we are in a new process, | 487 // wishes to start a new renderer. Returns true if we are in a new process, |
486 // otherwise writes the child_pid back to the browser via |fd|. Writes a | 488 // otherwise writes the child_pid back to the browser via |fd|. Writes a |
487 // child_pid of -1 on error. | 489 // child_pid of -1 on error. |
488 bool HandleForkRequest(int fd, const Pickle& pickle, | 490 bool HandleForkRequest(int fd, const Pickle& pickle, |
489 void* iter, std::vector<int>& fds) { | 491 PickleIterator iter, std::vector<int>& fds) { |
490 std::string uma_name; | 492 std::string uma_name; |
491 int uma_sample; | 493 int uma_sample; |
492 int uma_boundary_value; | 494 int uma_boundary_value; |
493 base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds, | 495 base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds, |
494 &uma_name, &uma_sample, | 496 &uma_name, &uma_sample, |
495 &uma_boundary_value); | 497 &uma_boundary_value); |
496 if (child_pid == 0) | 498 if (child_pid == 0) |
497 return true; | 499 return true; |
498 for (std::vector<int>::const_iterator | 500 for (std::vector<int>::const_iterator |
499 i = fds.begin(); i != fds.end(); ++i) | 501 i = fds.begin(); i != fds.end(); ++i) |
(...skipping 14 matching lines...) Expand all Loading... |
514 if (!uma_name.empty()) { | 516 if (!uma_name.empty()) { |
515 reply_pickle.WriteInt(uma_sample); | 517 reply_pickle.WriteInt(uma_sample); |
516 reply_pickle.WriteInt(uma_boundary_value); | 518 reply_pickle.WriteInt(uma_boundary_value); |
517 } | 519 } |
518 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) != | 520 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) != |
519 static_cast<ssize_t> (reply_pickle.size())) | 521 static_cast<ssize_t> (reply_pickle.size())) |
520 PLOG(ERROR) << "write"; | 522 PLOG(ERROR) << "write"; |
521 return false; | 523 return false; |
522 } | 524 } |
523 | 525 |
524 bool HandleGetSandboxStatus(int fd, const Pickle& pickle, void* iter) { | 526 bool HandleGetSandboxStatus(int fd, |
| 527 const Pickle& pickle, |
| 528 PickleIterator iter) { |
525 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_)) != | 529 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_)) != |
526 sizeof(sandbox_flags_))) { | 530 sizeof(sandbox_flags_))) { |
527 PLOG(ERROR) << "write"; | 531 PLOG(ERROR) << "write"; |
528 } | 532 } |
529 | 533 |
530 return false; | 534 return false; |
531 } | 535 } |
532 | 536 |
533 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs | 537 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs |
534 // fork() returns are not the real PIDs, so we need to map the Real PIDS | 538 // fork() returns are not the real PIDs, so we need to map the Real PIDS |
(...skipping 25 matching lines...) Expand all Loading... |
560 | 564 |
561 uint8_t reply_buf[512]; | 565 uint8_t reply_buf[512]; |
562 const ssize_t r = UnixDomainSocket::SendRecvMsg( | 566 const ssize_t r = UnixDomainSocket::SendRecvMsg( |
563 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, request); | 567 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, request); |
564 if (r == -1) { | 568 if (r == -1) { |
565 memset(output, 0, sizeof(struct tm)); | 569 memset(output, 0, sizeof(struct tm)); |
566 return; | 570 return; |
567 } | 571 } |
568 | 572 |
569 Pickle reply(reinterpret_cast<char*>(reply_buf), r); | 573 Pickle reply(reinterpret_cast<char*>(reply_buf), r); |
570 void* iter = NULL; | 574 PickleIterator iter(reply); |
571 std::string result, timezone; | 575 std::string result, timezone; |
572 if (!reply.ReadString(&iter, &result) || | 576 if (!reply.ReadString(&iter, &result) || |
573 !reply.ReadString(&iter, &timezone) || | 577 !reply.ReadString(&iter, &timezone) || |
574 result.size() != sizeof(struct tm)) { | 578 result.size() != sizeof(struct tm)) { |
575 memset(output, 0, sizeof(struct tm)); | 579 memset(output, 0, sizeof(struct tm)); |
576 return; | 580 return; |
577 } | 581 } |
578 | 582 |
579 memcpy(output, result.data(), sizeof(struct tm)); | 583 memcpy(output, result.data(), sizeof(struct tm)); |
580 if (timezone_out_len) { | 584 if (timezone_out_len) { |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 VLOG(1) << "Enabling experimental Seccomp sandbox."; | 873 VLOG(1) << "Enabling experimental Seccomp sandbox."; |
870 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; | 874 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; |
871 } | 875 } |
872 } | 876 } |
873 #endif // SECCOMP_SANDBOX | 877 #endif // SECCOMP_SANDBOX |
874 | 878 |
875 Zygote zygote(sandbox_flags, forkdelegate); | 879 Zygote zygote(sandbox_flags, forkdelegate); |
876 // This function call can return multiple times, once per fork(). | 880 // This function call can return multiple times, once per fork(). |
877 return zygote.ProcessRequests(); | 881 return zygote.ProcessRequests(); |
878 } | 882 } |
OLD | NEW |