| 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/zygote_host_impl_linux.h" | 5 #include "content/browser/zygote_host/zygote_host_impl_linux.h" |
| 6 | 6 |
| 7 #include <string.h> |
| 7 #include <sys/socket.h> | 8 #include <sys/socket.h> |
| 8 #include <sys/stat.h> | 9 #include <sys/stat.h> |
| 9 #include <sys/types.h> | 10 #include <sys/types.h> |
| 10 #include <unistd.h> | 11 #include <unistd.h> |
| 11 | 12 |
| 12 #include "base/base_switches.h" | 13 #include "base/base_switches.h" |
| 13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 14 #include "base/environment.h" | 15 #include "base/environment.h" |
| 15 #include "base/file_util.h" | 16 #include "base/file_util.h" |
| 16 #include "base/files/file_enumerator.h" | 17 #include "base/files/file_enumerator.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 sandbox_binary_ = sandbox_cmd.c_str(); | 120 sandbox_binary_ = sandbox_cmd.c_str(); |
| 120 | 121 |
| 121 // A non empty sandbox_cmd means we want a SUID sandbox. | 122 // A non empty sandbox_cmd means we want a SUID sandbox. |
| 122 using_suid_sandbox_ = !sandbox_cmd.empty(); | 123 using_suid_sandbox_ = !sandbox_cmd.empty(); |
| 123 | 124 |
| 124 // Start up the sandbox host process and get the file descriptor for the | 125 // Start up the sandbox host process and get the file descriptor for the |
| 125 // renderers to talk to it. | 126 // renderers to talk to it. |
| 126 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); | 127 const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); |
| 127 fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD())); | 128 fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD())); |
| 128 | 129 |
| 129 int dummy_fd = -1; | 130 base::ScopedFD dummy_fd; |
| 130 if (using_suid_sandbox_) { | 131 if (using_suid_sandbox_) { |
| 131 scoped_ptr<sandbox::SetuidSandboxClient> | 132 scoped_ptr<sandbox::SetuidSandboxClient> |
| 132 sandbox_client(sandbox::SetuidSandboxClient::Create()); | 133 sandbox_client(sandbox::SetuidSandboxClient::Create()); |
| 133 sandbox_client->PrependWrapper(&cmd_line, &options); | 134 sandbox_client->PrependWrapper(&cmd_line, &options); |
| 134 sandbox_client->SetupLaunchEnvironment(); | 135 sandbox_client->SetupLaunchEnvironment(); |
| 135 | 136 |
| 137 // We no longer need this dummy socket for discovering the zygote's PID, |
| 138 // but the sandbox is still hard-coded to expect a file descriptor at |
| 139 // kZygoteIdFd. Fixing this requires a sandbox API change. :( |
| 136 CHECK_EQ(kZygoteIdFd, sandbox_client->GetUniqueToChildFileDescriptor()); | 140 CHECK_EQ(kZygoteIdFd, sandbox_client->GetUniqueToChildFileDescriptor()); |
| 137 dummy_fd = socket(AF_UNIX, SOCK_DGRAM, 0); | 141 dummy_fd.reset(socket(AF_UNIX, SOCK_DGRAM, 0)); |
| 138 CHECK(dummy_fd >= 0); | 142 CHECK_GE(dummy_fd.get(), 0); |
| 139 fds_to_map.push_back(std::make_pair(dummy_fd, kZygoteIdFd)); | 143 fds_to_map.push_back(std::make_pair(dummy_fd.get(), kZygoteIdFd)); |
| 144 |
| 145 CHECK(UnixDomainSocket::EnableReceiveProcessId(fds[0])); |
| 140 } | 146 } |
| 141 | 147 |
| 142 base::ProcessHandle process = -1; | 148 base::ProcessHandle process = -1; |
| 143 options.fds_to_remap = &fds_to_map; | 149 options.fds_to_remap = &fds_to_map; |
| 144 base::LaunchProcess(cmd_line.argv(), options, &process); | 150 base::LaunchProcess(cmd_line.argv(), options, &process); |
| 145 CHECK(process != -1) << "Failed to launch zygote process"; | 151 CHECK(process != -1) << "Failed to launch zygote process"; |
| 146 | 152 |
| 153 dummy_fd.reset(); |
| 154 |
| 147 if (using_suid_sandbox_) { | 155 if (using_suid_sandbox_) { |
| 148 // In the SUID sandbox, the real zygote is forked from the sandbox. | |
| 149 // We need to look for it. | |
| 150 // But first, wait for the zygote to tell us it's running. | |
| 151 // The sending code is in content/browser/zygote_main_linux.cc. | 156 // The sending code is in content/browser/zygote_main_linux.cc. |
| 152 std::vector<int> fds_vec; | 157 std::vector<int> fds_vec; |
| 153 const int kExpectedLength = sizeof(kZygoteHelloMessage); | 158 const size_t kExpectedLength = sizeof(kZygoteHelloMessage); |
| 154 char buf[kExpectedLength]; | 159 char buf[kExpectedLength]; |
| 155 const ssize_t len = UnixDomainSocket::RecvMsg(fds[0], buf, sizeof(buf), | 160 const ssize_t len = UnixDomainSocket::RecvMsgWithPid( |
| 156 &fds_vec); | 161 fds[0], buf, sizeof(buf), &fds_vec, &pid_); |
| 157 CHECK_EQ(kExpectedLength, len) << "Incorrect zygote magic length"; | 162 CHECK_EQ(kExpectedLength, static_cast<size_t>(len)) |
| 158 CHECK(0 == strcmp(buf, kZygoteHelloMessage)) << "Incorrect zygote hello"; | 163 << "Incorrect zygote magic length"; |
| 164 CHECK_EQ(0, memcmp(buf, kZygoteHelloMessage, kExpectedLength)) |
| 165 << "Incorrect zygote hello"; |
| 166 CHECK_EQ(0U, fds_vec.size()) << "Zygote shouldn't send us any descriptors"; |
| 167 CHECK_GT(pid_, 1) << "Did not find zygote process"; |
| 159 | 168 |
| 160 std::string inode_output; | 169 // TODO(mdempsky): Sanity check that pid_ is valid for our namespace. Linux |
| 161 ino_t inode = 0; | 170 // kernels before 3.0 didn't translate across namespaces (crbug.com/357670). |
| 162 // Figure out the inode for |dummy_fd|, close |dummy_fd| on our end, | |
| 163 // and find the zygote process holding |dummy_fd|. | |
| 164 CHECK(base::FileDescriptorGetInode(&inode, dummy_fd)) | |
| 165 << "Cannot get inode for dummy_fd " << dummy_fd; | |
| 166 close(dummy_fd); | |
| 167 | |
| 168 std::vector<std::string> get_inode_cmdline; | |
| 169 get_inode_cmdline.push_back(sandbox_binary_); | |
| 170 get_inode_cmdline.push_back(base::kFindInodeSwitch); | |
| 171 get_inode_cmdline.push_back(base::Int64ToString(inode)); | |
| 172 CommandLine get_inode_cmd(get_inode_cmdline); | |
| 173 CHECK(base::GetAppOutput(get_inode_cmd, &inode_output)) | |
| 174 << "Find inode command failed for inode " << inode; | |
| 175 | |
| 176 base::TrimWhitespaceASCII(inode_output, base::TRIM_ALL, &inode_output); | |
| 177 CHECK(base::StringToInt(inode_output, &pid_)) | |
| 178 << "Invalid find inode output: " << inode_output; | |
| 179 CHECK(pid_ > 0) << "Did not find zygote process (using sandbox binary " | |
| 180 << sandbox_binary_ << ")"; | |
| 181 | 171 |
| 182 if (process != pid_) { | 172 if (process != pid_) { |
| 183 // Reap the sandbox. | 173 // Reap the sandbox. |
| 184 base::EnsureProcessGetsReaped(process); | 174 base::EnsureProcessGetsReaped(process); |
| 185 } | 175 } |
| 186 } else { | 176 } else { |
| 187 // Not using the SUID sandbox. | 177 // Not using the SUID sandbox. |
| 188 pid_ = process; | 178 pid_ = process; |
| 189 } | 179 } |
| 190 | 180 |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 return RenderSandboxHostLinux::GetInstance()->pid(); | 496 return RenderSandboxHostLinux::GetInstance()->pid(); |
| 507 } | 497 } |
| 508 | 498 |
| 509 int ZygoteHostImpl::GetSandboxStatus() const { | 499 int ZygoteHostImpl::GetSandboxStatus() const { |
| 510 if (have_read_sandbox_status_word_) | 500 if (have_read_sandbox_status_word_) |
| 511 return sandbox_status_; | 501 return sandbox_status_; |
| 512 return 0; | 502 return 0; |
| 513 } | 503 } |
| 514 | 504 |
| 515 } // namespace content | 505 } // namespace content |
| OLD | NEW |