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/gpu/gpu_process_host.h" | 5 #include "content/browser/gpu/gpu_process_host.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <list> | 10 #include <list> |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 } else { | 199 } else { |
200 delete message; | 200 delete message; |
201 } | 201 } |
202 } | 202 } |
203 #endif | 203 #endif |
204 | 204 |
205 // NOTE: changes to this class need to be reviewed by the security team. | 205 // NOTE: changes to this class need to be reviewed by the security team. |
206 class GpuSandboxedProcessLauncherDelegate | 206 class GpuSandboxedProcessLauncherDelegate |
207 : public SandboxedProcessLauncherDelegate { | 207 : public SandboxedProcessLauncherDelegate { |
208 public: | 208 public: |
209 explicit GpuSandboxedProcessLauncherDelegate(base::CommandLine* cmd_line) | 209 explicit GpuSandboxedProcessLauncherDelegate( |
| 210 const base::CommandLine& cmd_line) |
210 #if defined(OS_WIN) | 211 #if defined(OS_WIN) |
211 : cmd_line_(cmd_line) | 212 : cmd_line_(cmd_line) |
212 #endif | 213 #endif |
213 { | 214 { |
214 } | 215 } |
215 | 216 |
216 ~GpuSandboxedProcessLauncherDelegate() override {} | 217 ~GpuSandboxedProcessLauncherDelegate() override {} |
217 | 218 |
218 #if defined(OS_WIN) | 219 #if defined(OS_WIN) |
219 bool ShouldSandbox() override { | 220 bool ShouldSandbox() override { |
220 bool sandbox = !cmd_line_->HasSwitch(switches::kDisableGpuSandbox); | 221 bool sandbox = !cmd_line_.HasSwitch(switches::kDisableGpuSandbox); |
221 if (!sandbox) { | 222 if (!sandbox) { |
222 DVLOG(1) << "GPU sandbox is disabled"; | 223 DVLOG(1) << "GPU sandbox is disabled"; |
223 } | 224 } |
224 return sandbox; | 225 return sandbox; |
225 } | 226 } |
226 | 227 |
227 bool DisableDefaultPolicy() override { | 228 bool DisableDefaultPolicy() override { |
228 return true; | 229 return true; |
229 } | 230 } |
230 | 231 |
231 // For the GPU process we gotten as far as USER_LIMITED. The next level | 232 // For the GPU process we gotten as far as USER_LIMITED. The next level |
232 // which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL | 233 // which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL |
233 // backend. Note that the GPU process is connected to the interactive | 234 // backend. Note that the GPU process is connected to the interactive |
234 // desktop. | 235 // desktop. |
235 bool PreSpawnTarget(sandbox::TargetPolicy* policy) override { | 236 bool PreSpawnTarget(sandbox::TargetPolicy* policy) override { |
236 if (base::win::GetVersion() > base::win::VERSION_XP) { | 237 if (base::win::GetVersion() > base::win::VERSION_XP) { |
237 if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) == | 238 if (cmd_line_.GetSwitchValueASCII(switches::kUseGL) == |
238 gl::kGLImplementationDesktopName) { | 239 gl::kGLImplementationDesktopName) { |
239 // Open GL path. | 240 // Open GL path. |
240 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, | 241 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, |
241 sandbox::USER_LIMITED); | 242 sandbox::USER_LIMITED); |
242 SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); | 243 SetJobLevel(cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); |
243 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); | 244 policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); |
244 } else { | 245 } else { |
245 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, | 246 policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, |
246 sandbox::USER_LIMITED); | 247 sandbox::USER_LIMITED); |
247 | 248 |
248 // UI restrictions break when we access Windows from outside our job. | 249 // UI restrictions break when we access Windows from outside our job. |
249 // However, we don't want a proxy window in this process because it can | 250 // However, we don't want a proxy window in this process because it can |
250 // introduce deadlocks where the renderer blocks on the gpu, which in | 251 // introduce deadlocks where the renderer blocks on the gpu, which in |
251 // turn blocks on the browser UI thread. So, instead we forgo a window | 252 // turn blocks on the browser UI thread. So, instead we forgo a window |
252 // message pump entirely and just add job restrictions to prevent child | 253 // message pump entirely and just add job restrictions to prevent child |
253 // processes. | 254 // processes. |
254 SetJobLevel(*cmd_line_, | 255 SetJobLevel(cmd_line_, |
255 sandbox::JOB_LIMITED_USER, | 256 sandbox::JOB_LIMITED_USER, |
256 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | | 257 JOB_OBJECT_UILIMIT_SYSTEMPARAMETERS | |
257 JOB_OBJECT_UILIMIT_DESKTOP | | 258 JOB_OBJECT_UILIMIT_DESKTOP | |
258 JOB_OBJECT_UILIMIT_EXITWINDOWS | | 259 JOB_OBJECT_UILIMIT_EXITWINDOWS | |
259 JOB_OBJECT_UILIMIT_DISPLAYSETTINGS, | 260 JOB_OBJECT_UILIMIT_DISPLAYSETTINGS, |
260 policy); | 261 policy); |
261 | 262 |
262 policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); | 263 policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW); |
263 } | 264 } |
264 } else { | 265 } else { |
265 SetJobLevel(*cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); | 266 SetJobLevel(cmd_line_, sandbox::JOB_UNPROTECTED, 0, policy); |
266 policy->SetTokenLevel(sandbox::USER_UNPROTECTED, | 267 policy->SetTokenLevel(sandbox::USER_UNPROTECTED, |
267 sandbox::USER_LIMITED); | 268 sandbox::USER_LIMITED); |
268 } | 269 } |
269 | 270 |
270 // Allow the server side of GPU sockets, which are pipes that have | 271 // Allow the server side of GPU sockets, which are pipes that have |
271 // the "chrome.gpu" namespace and an arbitrary suffix. | 272 // the "chrome.gpu" namespace and an arbitrary suffix. |
272 sandbox::ResultCode result = policy->AddRule( | 273 sandbox::ResultCode result = policy->AddRule( |
273 sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, | 274 sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, |
274 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, | 275 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, |
275 L"\\\\.\\pipe\\chrome.gpu.*"); | 276 L"\\\\.\\pipe\\chrome.gpu.*"); |
276 if (result != sandbox::SBOX_ALL_OK) | 277 if (result != sandbox::SBOX_ALL_OK) |
277 return false; | 278 return false; |
278 | 279 |
279 // Block this DLL even if it is not loaded by the browser process. | 280 // Block this DLL even if it is not loaded by the browser process. |
280 policy->AddDllToUnload(L"cmsetac.dll"); | 281 policy->AddDllToUnload(L"cmsetac.dll"); |
281 | 282 |
282 if (cmd_line_->HasSwitch(switches::kEnableLogging)) { | 283 if (cmd_line_.HasSwitch(switches::kEnableLogging)) { |
283 base::string16 log_file_path = logging::GetLogFileFullPath(); | 284 base::string16 log_file_path = logging::GetLogFileFullPath(); |
284 if (!log_file_path.empty()) { | 285 if (!log_file_path.empty()) { |
285 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, | 286 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, |
286 sandbox::TargetPolicy::FILES_ALLOW_ANY, | 287 sandbox::TargetPolicy::FILES_ALLOW_ANY, |
287 log_file_path.c_str()); | 288 log_file_path.c_str()); |
288 if (result != sandbox::SBOX_ALL_OK) | 289 if (result != sandbox::SBOX_ALL_OK) |
289 return false; | 290 return false; |
290 } | 291 } |
291 } | 292 } |
292 | 293 |
293 return true; | 294 return true; |
294 } | 295 } |
295 #endif // OS_WIN | 296 #endif // OS_WIN |
296 | 297 |
297 SandboxType GetSandboxType() override { | 298 SandboxType GetSandboxType() override { |
298 return SANDBOX_TYPE_GPU; | 299 return SANDBOX_TYPE_GPU; |
299 } | 300 } |
300 | 301 |
301 private: | 302 private: |
302 #if defined(OS_WIN) | 303 #if defined(OS_WIN) |
303 base::CommandLine* cmd_line_; | 304 base::CommandLine cmd_line_; |
304 #endif // OS_WIN | 305 #endif // OS_WIN |
305 }; | 306 }; |
306 | 307 |
307 void HostLoadedShader(int host_id, | 308 void HostLoadedShader(int host_id, |
308 const std::string& key, | 309 const std::string& key, |
309 const std::string& data) { | 310 const std::string& data) { |
310 GpuProcessHost* host = GpuProcessHost::FromID(host_id); | 311 GpuProcessHost* host = GpuProcessHost::FromID(host_id); |
311 if (host) | 312 if (host) |
312 host->LoadedShader(key, data); | 313 host->LoadedShader(key, data); |
313 } | 314 } |
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 const base::CommandLine& browser_command_line = | 979 const base::CommandLine& browser_command_line = |
979 *base::CommandLine::ForCurrentProcess(); | 980 *base::CommandLine::ForCurrentProcess(); |
980 | 981 |
981 base::CommandLine::StringType gpu_launcher = | 982 base::CommandLine::StringType gpu_launcher = |
982 browser_command_line.GetSwitchValueNative(switches::kGpuLauncher); | 983 browser_command_line.GetSwitchValueNative(switches::kGpuLauncher); |
983 | 984 |
984 #if defined(OS_ANDROID) | 985 #if defined(OS_ANDROID) |
985 // crbug.com/447735. readlink("self/proc/exe") sometimes fails on Android | 986 // crbug.com/447735. readlink("self/proc/exe") sometimes fails on Android |
986 // at startup with EACCES. As a workaround ignore this here, since the | 987 // at startup with EACCES. As a workaround ignore this here, since the |
987 // executable name is actually not used or useful anyways. | 988 // executable name is actually not used or useful anyways. |
988 base::CommandLine* cmd_line = | 989 std::unique_ptr<base::CommandLine> cmd_line = |
989 new base::CommandLine(base::CommandLine::NO_PROGRAM); | 990 base::MakeUnique<base::CommandLine>(base::CommandLine::NO_PROGRAM); |
990 #else | 991 #else |
991 #if defined(OS_LINUX) | 992 #if defined(OS_LINUX) |
992 int child_flags = gpu_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : | 993 int child_flags = gpu_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : |
993 ChildProcessHost::CHILD_NORMAL; | 994 ChildProcessHost::CHILD_NORMAL; |
994 #else | 995 #else |
995 int child_flags = ChildProcessHost::CHILD_NORMAL; | 996 int child_flags = ChildProcessHost::CHILD_NORMAL; |
996 #endif | 997 #endif |
997 | 998 |
998 base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); | 999 base::FilePath exe_path = ChildProcessHost::GetChildPath(child_flags); |
999 if (exe_path.empty()) | 1000 if (exe_path.empty()) |
1000 return false; | 1001 return false; |
1001 | 1002 |
1002 base::CommandLine* cmd_line = new base::CommandLine(exe_path); | 1003 std::unique_ptr<base::CommandLine> cmd_line = |
| 1004 base::MakeUnique<base::CommandLine>(exe_path); |
1003 #endif | 1005 #endif |
1004 | 1006 |
1005 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); | 1007 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess); |
1006 | 1008 |
1007 BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line); | 1009 BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line.get()); |
1008 | 1010 |
1009 #if defined(OS_WIN) | 1011 #if defined(OS_WIN) |
1010 cmd_line->AppendArg(switches::kPrefetchArgumentGpu); | 1012 cmd_line->AppendArg(switches::kPrefetchArgumentGpu); |
1011 #endif // defined(OS_WIN) | 1013 #endif // defined(OS_WIN) |
1012 | 1014 |
1013 if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED) | 1015 if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED) |
1014 cmd_line->AppendSwitch(switches::kDisableGpuSandbox); | 1016 cmd_line->AppendSwitch(switches::kDisableGpuSandbox); |
1015 | 1017 |
1016 // TODO(penghuang): Replace all GPU related switches with GpuPreferences. | 1018 // TODO(penghuang): Replace all GPU related switches with GpuPreferences. |
1017 // https://crbug.com/590825 | 1019 // https://crbug.com/590825 |
1018 // If you want a browser command-line switch passed to the GPU process | 1020 // If you want a browser command-line switch passed to the GPU process |
1019 // you need to add it to |kSwitchNames| at the beginning of this file. | 1021 // you need to add it to |kSwitchNames| at the beginning of this file. |
1020 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, | 1022 cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames, |
1021 arraysize(kSwitchNames)); | 1023 arraysize(kSwitchNames)); |
1022 cmd_line->CopySwitchesFrom( | 1024 cmd_line->CopySwitchesFrom( |
1023 browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost, | 1025 browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost, |
1024 switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches); | 1026 switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches); |
1025 | 1027 |
1026 GetContentClient()->browser()->AppendExtraCommandLineSwitches( | 1028 GetContentClient()->browser()->AppendExtraCommandLineSwitches( |
1027 cmd_line, process_->GetData().id); | 1029 cmd_line.get(), process_->GetData().id); |
1028 | 1030 |
1029 GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line, | 1031 GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line.get(), |
1030 gpu_preferences); | 1032 gpu_preferences); |
1031 if (cmd_line->HasSwitch(switches::kUseGL)) { | 1033 if (cmd_line->HasSwitch(switches::kUseGL)) { |
1032 swiftshader_rendering_ = | 1034 swiftshader_rendering_ = |
1033 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); | 1035 (cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader"); |
1034 } | 1036 } |
1035 | 1037 |
1036 bool current_gpu_type_enabled = | 1038 bool current_gpu_type_enabled = |
1037 swiftshader_rendering_ ? gpu_enabled_ : hardware_gpu_enabled_; | 1039 swiftshader_rendering_ ? gpu_enabled_ : hardware_gpu_enabled_; |
1038 if (!current_gpu_type_enabled) { | 1040 if (!current_gpu_type_enabled) { |
1039 SendOutstandingReplies(); | 1041 SendOutstandingReplies(); |
1040 return false; | 1042 return false; |
1041 } | 1043 } |
1042 | 1044 |
1043 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", | 1045 UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessSoftwareRendering", |
1044 swiftshader_rendering_); | 1046 swiftshader_rendering_); |
1045 | 1047 |
1046 // If specified, prepend a launcher program to the command line. | 1048 // If specified, prepend a launcher program to the command line. |
1047 if (!gpu_launcher.empty()) | 1049 if (!gpu_launcher.empty()) |
1048 cmd_line->PrependWrapper(gpu_launcher); | 1050 cmd_line->PrependWrapper(gpu_launcher); |
1049 | 1051 |
1050 process_->Launch(new GpuSandboxedProcessLauncherDelegate(cmd_line), cmd_line, | 1052 std::unique_ptr<GpuSandboxedProcessLauncherDelegate> delegate = |
1051 true); | 1053 base::MakeUnique<GpuSandboxedProcessLauncherDelegate>(*cmd_line); |
| 1054 process_->Launch(std::move(delegate), std::move(cmd_line), true); |
1052 process_launched_ = true; | 1055 process_launched_ = true; |
1053 | 1056 |
1054 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", | 1057 UMA_HISTOGRAM_ENUMERATION("GPU.GPUProcessLifetimeEvents", |
1055 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); | 1058 LAUNCHED, GPU_PROCESS_LIFETIME_EVENT_MAX); |
1056 return true; | 1059 return true; |
1057 } | 1060 } |
1058 | 1061 |
1059 void GpuProcessHost::SendOutstandingReplies() { | 1062 void GpuProcessHost::SendOutstandingReplies() { |
1060 valid_ = false; | 1063 valid_ = false; |
1061 // First send empty channel handles for all EstablishChannel requests. | 1064 // First send empty channel handles for all EstablishChannel requests. |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader"); | 1197 TRACE_EVENT0("gpu", "GpuProcessHost::OnCacheShader"); |
1195 ClientIdToShaderCacheMap::iterator iter = | 1198 ClientIdToShaderCacheMap::iterator iter = |
1196 client_id_to_shader_cache_.find(client_id); | 1199 client_id_to_shader_cache_.find(client_id); |
1197 // If the cache doesn't exist then this is an off the record profile. | 1200 // If the cache doesn't exist then this is an off the record profile. |
1198 if (iter == client_id_to_shader_cache_.end()) | 1201 if (iter == client_id_to_shader_cache_.end()) |
1199 return; | 1202 return; |
1200 iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader); | 1203 iter->second->Cache(GetShaderPrefixKey() + ":" + key, shader); |
1201 } | 1204 } |
1202 | 1205 |
1203 } // namespace content | 1206 } // namespace content |
OLD | NEW |