| 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 |