diff options
author | Zhenyao Mo <zmo@chromium.org> | 2023-03-06 22:54:01 +0000 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2023-05-02 08:58:59 +0000 |
commit | d82c07428deb6d22b3cfbd41e891b094145efe7e (patch) | |
tree | 8f6e607403819cac92c34ec5ef2c203a8ea11921 | |
parent | fc2d84dc7a8642f3ce5d0fda565ee3b6f7debbcb (diff) | |
download | qtwebengine-chromium-d82c07428deb6d22b3cfbd41e891b094145efe7e.tar.gz |
[Backport] CVE-2023-1818: Use after free in Vulkan. (2/2)
Manual backport of patch originally reviewed on
https://chromium-review.googlesource.com/c/chromium/src/+/4242104:
Enable GPU watchdog for SwiftShader.
At a longer timeout.
R=magchen@chromium.org,geofflang@chromium.org
TEST=bots
Bug: 1223346
Change-Id: Ic8b7f5e77eae5257711d9c210c4ede1816b834be
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4242104
Commit-Queue: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: Maggie Chen <magchen@chromium.org>
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1113632}
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/474369
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
6 files changed, 93 insertions, 47 deletions
diff --git a/chromium/components/viz/service/display_embedder/compositor_gpu_thread.cc b/chromium/components/viz/service/display_embedder/compositor_gpu_thread.cc index e5cb55b8511..d4509649b1b 100644 --- a/chromium/components/viz/service/display_embedder/compositor_gpu_thread.cc +++ b/chromium/components/viz/service/display_embedder/compositor_gpu_thread.cc @@ -221,9 +221,9 @@ bool CompositorGpuThread::Initialize() { StartWithOptions(std::move(thread_options)); // Wait until thread is started and Init() is executed in order to return - // updated |init_succeded_|. + // updated |init_succeeded_|. WaitUntilThreadStarted(); - return init_succeded_; + return init_succeeded_; } void CompositorGpuThread::HandleMemoryPressure( @@ -239,12 +239,11 @@ void CompositorGpuThread::HandleMemoryPressure( void CompositorGpuThread::Init() { const auto& gpu_preferences = gpu_channel_manager_->gpu_preferences(); - if (enable_watchdog_) { + if (enable_watchdog_ && gpu_channel_manager_->watchdog()) { watchdog_thread_ = gpu::GpuWatchdogThread::Create( - gpu_preferences.watchdog_starts_backgrounded, "GpuWatchdog_Compositor"); + gpu_preferences.watchdog_starts_backgrounded, + gpu_channel_manager_->watchdog(), "GpuWatchdog_Compositor"); - if (!watchdog_thread_) - return; watchdog_thread_->OnInitComplete(); } @@ -254,7 +253,7 @@ void CompositorGpuThread::Init() { memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( FROM_HERE, base::BindRepeating(&CompositorGpuThread::HandleMemoryPressure, base::Unretained(this))), - init_succeded_ = true; + init_succeeded_ = true; } void CompositorGpuThread::CleanUp() { diff --git a/chromium/components/viz/service/display_embedder/compositor_gpu_thread.h b/chromium/components/viz/service/display_embedder/compositor_gpu_thread.h index 86b2a0e5c03..6c9f60427e4 100644 --- a/chromium/components/viz/service/display_embedder/compositor_gpu_thread.h +++ b/chromium/components/viz/service/display_embedder/compositor_gpu_thread.h @@ -87,7 +87,7 @@ class VIZ_SERVICE_EXPORT CompositorGpuThread raw_ptr<gpu::GpuChannelManager> gpu_channel_manager_; const bool enable_watchdog_; - bool init_succeded_ = false; + bool init_succeeded_ = false; scoped_refptr<VulkanContextProvider> vulkan_context_provider_; diff --git a/chromium/gpu/ipc/common/gpu_watchdog_timeout.h b/chromium/gpu/ipc/common/gpu_watchdog_timeout.h index f673ec47381..35d7572275d 100644 --- a/chromium/gpu/ipc/common/gpu_watchdog_timeout.h +++ b/chromium/gpu/ipc/common/gpu_watchdog_timeout.h @@ -43,6 +43,9 @@ constexpr int kInitFactor = 2; constexpr int kInitFactor = 1; #endif +// Software rasterizer runs slower than hardware accelerated. +constexpr int kSoftwareRenderingFactor = 2; + } // namespace gpu #endif // GPU_IPC_COMMON_GPU_WATCHDOG_TIMEOUT_H_ diff --git a/chromium/gpu/ipc/service/gpu_init.cc b/chromium/gpu/ipc/service/gpu_init.cc index e0e03b53ba9..579ed26b93b 100644 --- a/chromium/gpu/ipc/service/gpu_init.cc +++ b/chromium/gpu/ipc/service/gpu_init.cc @@ -345,9 +345,27 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, } } + if (!gl_use_swiftshader_) { + gl_use_swiftshader_ = EnableSwiftShaderIfNeeded( + command_line, gpu_feature_info_, + gpu_preferences_.disable_software_rasterizer, needs_more_info); + } + + if (gl_initialized && gl_use_swiftshader_ && + !gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) { +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly " + << "on Linux"; + return false; +#else // !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) + SaveHardwareGpuInfoAndGpuFeatureInfo(); + gl::init::ShutdownGL(nullptr, true); + gl_initialized = false; +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + } + bool enable_watchdog = !gpu_preferences_.disable_gpu_watchdog && - !command_line->HasSwitch(switches::kHeadless) && - !gl_use_swiftshader_; + !command_line->HasSwitch(switches::kHeadless); // Disable the watchdog in debug builds because they tend to only be run by // developers who will not appreciate the watchdog killing the GPU process. @@ -386,7 +404,10 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, // consuming has completed, otherwise the process is liable to be aborted. if (enable_watchdog && !delayed_watchdog_enable) { watchdog_thread_ = GpuWatchdogThread::Create( - gpu_preferences_.watchdog_starts_backgrounded, "GpuWatchdog"); + gpu_preferences_.watchdog_starts_backgrounded, + gl_use_swiftshader_ || + gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts()), + "GpuWatchdog"); watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get()); } @@ -432,25 +453,6 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, ->GetSupportedFormatsForTexturing(); #endif // defined(USE_OZONE) - if (!gl_use_swiftshader_) { - gl_use_swiftshader_ = EnableSwiftShaderIfNeeded( - command_line, gpu_feature_info_, - gpu_preferences_.disable_software_rasterizer, needs_more_info); - } - - if (gl_initialized && gl_use_swiftshader_ && - !gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) - VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly " - << "on Linux"; - return false; -#else // !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) - SaveHardwareGpuInfoAndGpuFeatureInfo(); - gl::init::ShutdownGL(nullptr, true); - gl_initialized = false; -#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) - } - gl::GLDisplay* gl_display = nullptr; if (!gl_initialized) { @@ -558,8 +560,14 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, #else SaveHardwareGpuInfoAndGpuFeatureInfo(); gl::init::ShutdownGL(gl_display, true); - watchdog_thread_ = nullptr; - watchdog_init.SetGpuWatchdogPtr(nullptr); + if (watchdog_thread_.get()) { + watchdog_thread_ = nullptr; + watchdog_init.SetGpuWatchdogPtr(nullptr); + watchdog_thread_ = GpuWatchdogThread::Create( + gpu_preferences_.watchdog_starts_backgrounded, + /*software_rendering=*/true, "GpuWatchdog"); + watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get()); + } gl_display = gl::init::InitializeGLNoExtensionsOneOff( /*init_bindings=*/true, system_device_id); if (!gl_display) { @@ -719,8 +727,8 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, UMA_HISTOGRAM_MEDIUM_TIMES("GPU.InitializeOneOffMediumTime", elapsed_timer.Elapsed()); - // SwANGLE is expected to run slowly, so disable the watchdog - // in that case. + bool recreate_watchdog = false; + if (!gl_use_swiftshader_ && command_line->HasSwitch(switches::kUseGL)) { std::string use_gl = command_line->GetSwitchValueASCII(switches::kUseGL); std::string use_angle = @@ -729,6 +737,9 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, (use_angle == gl::kANGLEImplementationSwiftShaderName || use_angle == gl::kANGLEImplementationSwiftShaderForWebGLName)) { gl_use_swiftshader_ = true; + if (watchdog_thread_) { + recreate_watchdog = true; + } } } #if BUILDFLAG(IS_LINUX) || \ @@ -739,19 +750,27 @@ bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line, // process's address space. Using swiftshader helps ensure that doesn't // happen and keeps Chrome and linux-chromeos usable with rr. gl_use_swiftshader_ = true; + if (watchdog_thread_) { + recreate_watchdog = true; + } } #endif if (gl_use_swiftshader_ || gl::IsSoftwareGLImplementation(gl::GetGLImplementationParts())) { gpu_info_.software_rendering = true; - watchdog_thread_ = nullptr; - watchdog_init.SetGpuWatchdogPtr(nullptr); } else if (gl_disabled) { + DCHECK(!recreate_watchdog); watchdog_thread_ = nullptr; watchdog_init.SetGpuWatchdogPtr(nullptr); } else if (enable_watchdog && delayed_watchdog_enable) { - watchdog_thread_ = GpuWatchdogThread::Create( - gpu_preferences_.watchdog_starts_backgrounded, "GpuWatchdog"); + recreate_watchdog = true; + } + if (recreate_watchdog) { + watchdog_thread_ = nullptr; + watchdog_init.SetGpuWatchdogPtr(nullptr); + watchdog_thread_ = + GpuWatchdogThread::Create(gpu_preferences_.watchdog_starts_backgrounded, + gpu_info_.software_rendering, "GpuWatchdog"); watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get()); } diff --git a/chromium/gpu/ipc/service/gpu_watchdog_thread.cc b/chromium/gpu/ipc/service/gpu_watchdog_thread.cc index 6371fca14d3..5fe6a7ac35b 100644 --- a/chromium/gpu/ipc/service/gpu_watchdog_thread.cc +++ b/chromium/gpu/ipc/service/gpu_watchdog_thread.cc @@ -37,7 +37,7 @@ namespace gpu { -base::TimeDelta GetGpuWatchdogTimeout() { +base::TimeDelta GetGpuWatchdogTimeout(bool software_rendering) { std::string timeout_str = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kGpuWatchdogTimeoutSeconds); @@ -50,17 +50,21 @@ base::TimeDelta GetGpuWatchdogTimeout() { << timeout_str; } + base::TimeDelta timeout = kGpuWatchdogTimeout; #if BUILDFLAG(IS_WIN) if (base::win::GetVersion() >= base::win::Version::WIN10) { int num_of_processors = base::SysInfo::NumberOfProcessors(); - if (num_of_processors > 8) - return (kGpuWatchdogTimeout - base::Seconds(10)); - else if (num_of_processors <= 4) - return kGpuWatchdogTimeout + base::Seconds(5); - } + if (num_of_processors > 8) { + timeout -= base::Seconds(10); + } else if (num_of_processors <= 4) { + timeout += base::Seconds(5); + } #endif - return kGpuWatchdogTimeout; + if (software_rendering) { + timeout *= kSoftwareRenderingFactor; + } + return timeout; } GpuWatchdogThread::GpuWatchdogThread(base::TimeDelta timeout, @@ -156,9 +160,22 @@ std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create( // static std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create( bool start_backgrounded, + bool software_rendering, + const std::string& thread_name) { + return Create(start_backgrounded, GetGpuWatchdogTimeout(software_rendering), + kInitFactor, kRestartFactor, /*test_mode=*/false, thread_name); +} + +// static +std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create( + bool start_backgrounded, + const GpuWatchdogThread* existing_watchdog, const std::string& thread_name) { - return Create(start_backgrounded, GetGpuWatchdogTimeout(), kInitFactor, - kRestartFactor, /*test_mode=*/false, thread_name); + DCHECK(existing_watchdog); + return Create(start_backgrounded, existing_watchdog->watchdog_timeout_, + existing_watchdog->watchdog_init_factor_, + existing_watchdog->watchdog_restart_factor_, + /*test_mode=*/false, thread_name); } // Android Chrome goes to the background. Called from the gpu io thread. diff --git a/chromium/gpu/ipc/service/gpu_watchdog_thread.h b/chromium/gpu/ipc/service/gpu_watchdog_thread.h index 0ae2182eab8..f0c412903dd 100644 --- a/chromium/gpu/ipc/service/gpu_watchdog_thread.h +++ b/chromium/gpu/ipc/service/gpu_watchdog_thread.h @@ -93,6 +93,14 @@ class GPU_IPC_SERVICE_EXPORT GpuWatchdogThread public: static std::unique_ptr<GpuWatchdogThread> Create( bool start_backgrounded, + bool software_rendering, + const std::string& thread_name); + + // Use the existing GpuWatchdogThread to create a second one. This is used + // for DrDC thread only. + static std::unique_ptr<GpuWatchdogThread> Create( + bool start_backgrounded, + const GpuWatchdogThread* existing_watchdog, const std::string& thread_name); static std::unique_ptr<GpuWatchdogThread> Create( |