OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 PickleReader 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, PickleReader 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, const Pickle& pickle, PickleReader ite
r) { |
229 base::ProcessHandle child; | 229 base::ProcessHandle child; |
230 | 230 |
231 if (!pickle.ReadInt(&iter, &child)) { | 231 if (!pickle.ReadInt(&iter, &child)) { |
232 LOG(WARNING) << "Error parsing GetTerminationStatus request " | 232 LOG(WARNING) << "Error parsing GetTerminationStatus request " |
233 << "from browser"; | 233 << "from browser"; |
234 return; | 234 return; |
235 } | 235 } |
236 | 236 |
237 base::TerminationStatus status; | 237 base::TerminationStatus status; |
238 int exit_code; | 238 int exit_code; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 | 340 |
341 const ssize_t r = UnixDomainSocket::SendRecvMsg( | 341 const ssize_t r = UnixDomainSocket::SendRecvMsg( |
342 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, | 342 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, |
343 request); | 343 request); |
344 if (r == -1) { | 344 if (r == -1) { |
345 LOG(ERROR) << "Failed to get child process's real PID"; | 345 LOG(ERROR) << "Failed to get child process's real PID"; |
346 goto error; | 346 goto error; |
347 } | 347 } |
348 | 348 |
349 Pickle reply(reinterpret_cast<char*>(reply_buf), r); | 349 Pickle reply(reinterpret_cast<char*>(reply_buf), r); |
350 void* iter = NULL; | 350 PickleReader iter(reply); |
351 if (!reply.ReadInt(&iter, &real_pid)) | 351 if (!reply.ReadInt(&iter, &real_pid)) |
352 goto error; | 352 goto error; |
353 if (real_pid <= 0) { | 353 if (real_pid <= 0) { |
354 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? | 354 // METHOD_GET_CHILD_WITH_INODE failed. Did the child die already? |
355 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; | 355 LOG(ERROR) << "METHOD_GET_CHILD_WITH_INODE failed"; |
356 goto error; | 356 goto error; |
357 } | 357 } |
358 real_pids_to_sandbox_pids[real_pid] = pid; | 358 real_pids_to_sandbox_pids[real_pid] = pid; |
359 } | 359 } |
360 if (use_helper) { | 360 if (use_helper) { |
(...skipping 25 matching lines...) Expand all Loading... |
386 close(pipe_fds[0]); | 386 close(pipe_fds[0]); |
387 if (pipe_fds[1] >= 0) | 387 if (pipe_fds[1] >= 0) |
388 close(pipe_fds[1]); | 388 close(pipe_fds[1]); |
389 return -1; | 389 return -1; |
390 } | 390 } |
391 | 391 |
392 // Unpacks process type and arguments from |pickle| and forks a new process. | 392 // 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 | 393 // 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(). | 394 // process and the child process ID to the parent process, like fork(). |
395 base::ProcessId ReadArgsAndFork(const Pickle& pickle, | 395 base::ProcessId ReadArgsAndFork(const Pickle& pickle, |
396 void* iter, | 396 PickleReader iter, |
397 std::vector<int>& fds, | 397 std::vector<int>& fds, |
398 std::string* uma_name, | 398 std::string* uma_name, |
399 int* uma_sample, | 399 int* uma_sample, |
400 int* uma_boundary_value) { | 400 int* uma_boundary_value) { |
401 std::vector<std::string> args; | 401 std::vector<std::string> args; |
402 int argc = 0; | 402 int argc = 0; |
403 int numfds = 0; | 403 int numfds = 0; |
404 base::GlobalDescriptors::Mapping mapping; | 404 base::GlobalDescriptors::Mapping mapping; |
405 std::string process_type; | 405 std::string process_type; |
406 std::string channel_id; | 406 std::string channel_id; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 << " numfds " << numfds << " child_pid " << child_pid; | 479 << " numfds " << numfds << " child_pid " << child_pid; |
480 } | 480 } |
481 return child_pid; | 481 return child_pid; |
482 } | 482 } |
483 | 483 |
484 // Handle a 'fork' request from the browser: this means that the browser | 484 // 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, | 485 // 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 | 486 // otherwise writes the child_pid back to the browser via |fd|. Writes a |
487 // child_pid of -1 on error. | 487 // child_pid of -1 on error. |
488 bool HandleForkRequest(int fd, const Pickle& pickle, | 488 bool HandleForkRequest(int fd, const Pickle& pickle, |
489 void* iter, std::vector<int>& fds) { | 489 PickleReader iter, std::vector<int>& fds) { |
490 std::string uma_name; | 490 std::string uma_name; |
491 int uma_sample; | 491 int uma_sample; |
492 int uma_boundary_value; | 492 int uma_boundary_value; |
493 base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds, | 493 base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds, |
494 &uma_name, &uma_sample, | 494 &uma_name, &uma_sample, |
495 &uma_boundary_value); | 495 &uma_boundary_value); |
496 if (child_pid == 0) | 496 if (child_pid == 0) |
497 return true; | 497 return true; |
498 for (std::vector<int>::const_iterator | 498 for (std::vector<int>::const_iterator |
499 i = fds.begin(); i != fds.end(); ++i) | 499 i = fds.begin(); i != fds.end(); ++i) |
(...skipping 14 matching lines...) Expand all Loading... |
514 if (!uma_name.empty()) { | 514 if (!uma_name.empty()) { |
515 reply_pickle.WriteInt(uma_sample); | 515 reply_pickle.WriteInt(uma_sample); |
516 reply_pickle.WriteInt(uma_boundary_value); | 516 reply_pickle.WriteInt(uma_boundary_value); |
517 } | 517 } |
518 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) != | 518 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) != |
519 static_cast<ssize_t> (reply_pickle.size())) | 519 static_cast<ssize_t> (reply_pickle.size())) |
520 PLOG(ERROR) << "write"; | 520 PLOG(ERROR) << "write"; |
521 return false; | 521 return false; |
522 } | 522 } |
523 | 523 |
524 bool HandleGetSandboxStatus(int fd, const Pickle& pickle, void* iter) { | 524 bool HandleGetSandboxStatus(int fd, const Pickle& pickle, PickleReader iter) { |
525 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_)) != | 525 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_)) != |
526 sizeof(sandbox_flags_))) { | 526 sizeof(sandbox_flags_))) { |
527 PLOG(ERROR) << "write"; | 527 PLOG(ERROR) << "write"; |
528 } | 528 } |
529 | 529 |
530 return false; | 530 return false; |
531 } | 531 } |
532 | 532 |
533 // In the SUID sandbox, we try to use a new PID namespace. Thus the PIDs | 533 // 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 | 534 // fork() returns are not the real PIDs, so we need to map the Real PIDS |
(...skipping 25 matching lines...) Expand all Loading... |
560 | 560 |
561 uint8_t reply_buf[512]; | 561 uint8_t reply_buf[512]; |
562 const ssize_t r = UnixDomainSocket::SendRecvMsg( | 562 const ssize_t r = UnixDomainSocket::SendRecvMsg( |
563 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, request); | 563 kMagicSandboxIPCDescriptor, reply_buf, sizeof(reply_buf), NULL, request); |
564 if (r == -1) { | 564 if (r == -1) { |
565 memset(output, 0, sizeof(struct tm)); | 565 memset(output, 0, sizeof(struct tm)); |
566 return; | 566 return; |
567 } | 567 } |
568 | 568 |
569 Pickle reply(reinterpret_cast<char*>(reply_buf), r); | 569 Pickle reply(reinterpret_cast<char*>(reply_buf), r); |
570 void* iter = NULL; | 570 PickleReader iter(reply); |
571 std::string result, timezone; | 571 std::string result, timezone; |
572 if (!reply.ReadString(&iter, &result) || | 572 if (!reply.ReadString(&iter, &result) || |
573 !reply.ReadString(&iter, &timezone) || | 573 !reply.ReadString(&iter, &timezone) || |
574 result.size() != sizeof(struct tm)) { | 574 result.size() != sizeof(struct tm)) { |
575 memset(output, 0, sizeof(struct tm)); | 575 memset(output, 0, sizeof(struct tm)); |
576 return; | 576 return; |
577 } | 577 } |
578 | 578 |
579 memcpy(output, result.data(), sizeof(struct tm)); | 579 memcpy(output, result.data(), sizeof(struct tm)); |
580 if (timezone_out_len) { | 580 if (timezone_out_len) { |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
869 VLOG(1) << "Enabling experimental Seccomp sandbox."; | 869 VLOG(1) << "Enabling experimental Seccomp sandbox."; |
870 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; | 870 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; |
871 } | 871 } |
872 } | 872 } |
873 #endif // SECCOMP_SANDBOX | 873 #endif // SECCOMP_SANDBOX |
874 | 874 |
875 Zygote zygote(sandbox_flags, forkdelegate); | 875 Zygote zygote(sandbox_flags, forkdelegate); |
876 // This function call can return multiple times, once per fork(). | 876 // This function call can return multiple times, once per fork(). |
877 return zygote.ProcessRequests(); | 877 return zygote.ProcessRequests(); |
878 } | 878 } |
OLD | NEW |