| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/zygote_host_linux.h" | 5 #include "chrome/browser/zygote_host_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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 setenv(saved_envvar, value, 1 /* overwrite */); | 42 setenv(saved_envvar, value, 1 /* overwrite */); |
| 43 else | 43 else |
| 44 unsetenv(saved_envvar); | 44 unsetenv(saved_envvar); |
| 45 | 45 |
| 46 free(saved_envvar); | 46 free(saved_envvar); |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 | 49 |
| 50 ZygoteHost::ZygoteHost() | 50 ZygoteHost::ZygoteHost() |
| 51 : pid_(-1), | 51 : pid_(-1), |
| 52 init_(false) { | 52 init_(false), |
| 53 using_suid_sandbox_(false) { |
| 53 } | 54 } |
| 54 | 55 |
| 55 ZygoteHost::~ZygoteHost() { | 56 ZygoteHost::~ZygoteHost() { |
| 56 if (init_) | 57 if (init_) |
| 57 close(control_fd_); | 58 close(control_fd_); |
| 58 } | 59 } |
| 59 | 60 |
| 60 void ZygoteHost::Init(const std::string& sandbox_cmd) { | 61 void ZygoteHost::Init(const std::string& sandbox_cmd) { |
| 61 DCHECK(!init_); | 62 DCHECK(!init_); |
| 62 init_ = true; | 63 init_ = true; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 93 if (browser_command_line.HasSwitch(switches::kEnableLogging)) { | 94 if (browser_command_line.HasSwitch(switches::kEnableLogging)) { |
| 94 // Append with value to support --enable-logging=stderr. | 95 // Append with value to support --enable-logging=stderr. |
| 95 cmd_line.AppendSwitchWithValue(switches::kEnableLogging, | 96 cmd_line.AppendSwitchWithValue(switches::kEnableLogging, |
| 96 browser_command_line.GetSwitchValueASCII( | 97 browser_command_line.GetSwitchValueASCII( |
| 97 switches::kEnableLogging)); | 98 switches::kEnableLogging)); |
| 98 } | 99 } |
| 99 if (browser_command_line.HasSwitch(switches::kEnableSeccompSandbox)) { | 100 if (browser_command_line.HasSwitch(switches::kEnableSeccompSandbox)) { |
| 100 cmd_line.AppendSwitch(switches::kEnableSeccompSandbox); | 101 cmd_line.AppendSwitch(switches::kEnableSeccompSandbox); |
| 101 } | 102 } |
| 102 | 103 |
| 103 const char* sandbox_binary = sandbox_cmd.c_str(); | 104 sandbox_binary_ = sandbox_cmd.c_str(); |
| 104 struct stat st; | 105 struct stat st; |
| 105 | 106 |
| 106 bool using_suid_sandbox = false; | 107 if (!sandbox_cmd.empty() && stat(sandbox_binary_.c_str(), &st) == 0) { |
| 107 if (!sandbox_cmd.empty() && stat(sandbox_binary, &st) == 0) { | 108 if (access(sandbox_binary_.c_str(), X_OK) == 0 && |
| 108 if (access(sandbox_binary, X_OK) == 0 && | |
| 109 (st.st_uid == 0) && | 109 (st.st_uid == 0) && |
| 110 (st.st_mode & S_ISUID) && | 110 (st.st_mode & S_ISUID) && |
| 111 (st.st_mode & S_IXOTH)) { | 111 (st.st_mode & S_IXOTH)) { |
| 112 using_suid_sandbox = true; | 112 using_suid_sandbox_ = true; |
| 113 cmd_line.PrependWrapper(ASCIIToWide(sandbox_binary)); | 113 cmd_line.PrependWrapper(ASCIIToWide(sandbox_binary_.c_str())); |
| 114 | 114 |
| 115 SaveSUIDUnsafeEnvironmentVariables(); | 115 SaveSUIDUnsafeEnvironmentVariables(); |
| 116 } else { | 116 } else { |
| 117 LOG(FATAL) << "The SUID sandbox helper binary was found, but is not " | 117 LOG(FATAL) << "The SUID sandbox helper binary was found, but is not " |
| 118 "configured correctly. Rather than run without sandboxing " | 118 "configured correctly. Rather than run without sandboxing " |
| 119 "I'm aborting now. You need to make sure that " | 119 "I'm aborting now. You need to make sure that " |
| 120 << sandbox_binary << " is mode 4755 and owned by root."; | 120 << sandbox_binary_ << " is mode 4755 and owned by root."; |
| 121 } | 121 } |
| 122 } | 122 } |
| 123 | 123 |
| 124 // Start up the sandbox host process and get the file descriptor for the | 124 // Start up the sandbox host process and get the file descriptor for the |
| 125 // renderers to talk to it. | 125 // renderers to talk to it. |
| 126 const int sfd = Singleton<RenderSandboxHostLinux>()->GetRendererSocket(); | 126 const int sfd = Singleton<RenderSandboxHostLinux>()->GetRendererSocket(); |
| 127 fds_to_map.push_back(std::make_pair(sfd, 5)); | 127 fds_to_map.push_back(std::make_pair(sfd, 5)); |
| 128 | 128 |
| 129 int dummy_fd = -1; | 129 int dummy_fd = -1; |
| 130 if (using_suid_sandbox) { | 130 if (using_suid_sandbox_) { |
| 131 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); | 131 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
| 132 CHECK(dummy_fd >= 0); | 132 CHECK(dummy_fd >= 0); |
| 133 fds_to_map.push_back(std::make_pair(dummy_fd, 7)); | 133 fds_to_map.push_back(std::make_pair(dummy_fd, 7)); |
| 134 } | 134 } |
| 135 | 135 |
| 136 base::ProcessHandle process; | 136 base::ProcessHandle process; |
| 137 base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process); | 137 base::LaunchApp(cmd_line.argv(), fds_to_map, false, &process); |
| 138 CHECK(process != -1) << "Failed to launch zygote process"; | 138 CHECK(process != -1) << "Failed to launch zygote process"; |
| 139 | 139 |
| 140 if (using_suid_sandbox) { | 140 if (using_suid_sandbox_) { |
| 141 // In the SUID sandbox, the real zygote is forked from the sandbox. | 141 // In the SUID sandbox, the real zygote is forked from the sandbox. |
| 142 // We need to look for it. | 142 // We need to look for it. |
| 143 // But first, wait for the zygote to tell us it's running. | 143 // But first, wait for the zygote to tell us it's running. |
| 144 // The sending code is in chrome/browser/zygote_main_linux.cc. | 144 // The sending code is in chrome/browser/zygote_main_linux.cc. |
| 145 std::vector<int> fds_vec; | 145 std::vector<int> fds_vec; |
| 146 const int kExpectedLength = sizeof(kZygoteMagic); | 146 const int kExpectedLength = sizeof(kZygoteMagic); |
| 147 char buf[kExpectedLength]; | 147 char buf[kExpectedLength]; |
| 148 const ssize_t len = base::RecvMsg(fds[0], buf, sizeof(buf), &fds_vec); | 148 const ssize_t len = base::RecvMsg(fds[0], buf, sizeof(buf), &fds_vec); |
| 149 CHECK(len == kExpectedLength) << "Incorrect zygote magic length"; | 149 CHECK(len == kExpectedLength) << "Incorrect zygote magic length"; |
| 150 CHECK(0 == strcmp(buf, kZygoteMagic)) << "Incorrect zygote magic"; | 150 CHECK(0 == strcmp(buf, kZygoteMagic)) << "Incorrect zygote magic"; |
| 151 | 151 |
| 152 std::string inode_output; | 152 std::string inode_output; |
| 153 ino_t inode = 0; | 153 ino_t inode = 0; |
| 154 // Figure out the inode for |dummy_fd|, close |dummy_fd| on our end, | 154 // Figure out the inode for |dummy_fd|, close |dummy_fd| on our end, |
| 155 // and find the zygote process holding |dummy_fd|. | 155 // and find the zygote process holding |dummy_fd|. |
| 156 if (base::FileDescriptorGetInode(&inode, dummy_fd)) { | 156 if (base::FileDescriptorGetInode(&inode, dummy_fd)) { |
| 157 close(dummy_fd); | 157 close(dummy_fd); |
| 158 std::vector<std::string> get_inode_cmdline; | 158 std::vector<std::string> get_inode_cmdline; |
| 159 get_inode_cmdline.push_back(sandbox_binary); | 159 get_inode_cmdline.push_back(sandbox_binary_); |
| 160 get_inode_cmdline.push_back(base::kFindInodeSwitch); | 160 get_inode_cmdline.push_back(base::kFindInodeSwitch); |
| 161 get_inode_cmdline.push_back(Int64ToString(inode)); | 161 get_inode_cmdline.push_back(Int64ToString(inode)); |
| 162 CommandLine get_inode_cmd(get_inode_cmdline); | 162 CommandLine get_inode_cmd(get_inode_cmdline); |
| 163 if (base::GetAppOutput(get_inode_cmd, &inode_output)) { | 163 if (base::GetAppOutput(get_inode_cmd, &inode_output)) { |
| 164 StringToInt(inode_output, &pid_); | 164 StringToInt(inode_output, &pid_); |
| 165 } | 165 } |
| 166 } | 166 } |
| 167 CHECK(pid_ > 0) << "Did not find zygote process"; | 167 CHECK(pid_ > 0) << "Did not find zygote process"; |
| 168 | 168 |
| 169 if (process != pid_) { | 169 if (process != pid_) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 200 fds.push_back(i->second); | 200 fds.push_back(i->second); |
| 201 } | 201 } |
| 202 | 202 |
| 203 if (!base::SendMsg(control_fd_, pickle.data(), pickle.size(), fds)) | 203 if (!base::SendMsg(control_fd_, pickle.data(), pickle.size(), fds)) |
| 204 return base::kNullProcessHandle; | 204 return base::kNullProcessHandle; |
| 205 | 205 |
| 206 pid_t pid; | 206 pid_t pid; |
| 207 if (HANDLE_EINTR(read(control_fd_, &pid, sizeof(pid))) != sizeof(pid)) | 207 if (HANDLE_EINTR(read(control_fd_, &pid, sizeof(pid))) != sizeof(pid)) |
| 208 return base::kNullProcessHandle; | 208 return base::kNullProcessHandle; |
| 209 | 209 |
| 210 const int kRendererScore = 5; |
| 211 if (using_suid_sandbox_) { |
| 212 base::ProcessHandle sandbox_helper_process; |
| 213 base::file_handle_mapping_vector dummy_map; |
| 214 std::vector<std::string> adj_oom_score_cmdline; |
| 215 |
| 216 adj_oom_score_cmdline.push_back(sandbox_binary_); |
| 217 adj_oom_score_cmdline.push_back(base::kAdjustOOMScoreSwitch); |
| 218 adj_oom_score_cmdline.push_back(Int64ToString(pid)); |
| 219 adj_oom_score_cmdline.push_back(IntToString(kRendererScore)); |
| 220 CommandLine adj_oom_score_cmd(adj_oom_score_cmdline); |
| 221 if (base::LaunchApp(adj_oom_score_cmdline, dummy_map, false, |
| 222 &sandbox_helper_process)) { |
| 223 ProcessWatcher::EnsureProcessGetsReaped(sandbox_helper_process); |
| 224 } |
| 225 } else { |
| 226 base::AdjustOOMScore(pid, kRendererScore); |
| 227 } |
| 228 |
| 210 return pid; | 229 return pid; |
| 211 } | 230 } |
| 212 | 231 |
| 213 void ZygoteHost::EnsureProcessTerminated(pid_t process) { | 232 void ZygoteHost::EnsureProcessTerminated(pid_t process) { |
| 214 DCHECK(init_); | 233 DCHECK(init_); |
| 215 Pickle pickle; | 234 Pickle pickle; |
| 216 | 235 |
| 217 pickle.WriteInt(kCmdReap); | 236 pickle.WriteInt(kCmdReap); |
| 218 pickle.WriteInt(process); | 237 pickle.WriteInt(process); |
| 219 | 238 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 248 !read_pickle.ReadBool(&iter, &tmp_child_exited)) { | 267 !read_pickle.ReadBool(&iter, &tmp_child_exited)) { |
| 249 LOG(WARNING) << "Error parsing DidProcessCrash response from zygote."; | 268 LOG(WARNING) << "Error parsing DidProcessCrash response from zygote."; |
| 250 return false; | 269 return false; |
| 251 } | 270 } |
| 252 | 271 |
| 253 if (child_exited) | 272 if (child_exited) |
| 254 *child_exited = tmp_child_exited; | 273 *child_exited = tmp_child_exited; |
| 255 | 274 |
| 256 return did_crash; | 275 return did_crash; |
| 257 } | 276 } |
| OLD | NEW |