summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-10-15 12:29:03 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-10-17 10:03:20 +0000
commitb5d06a4582837e4fa6e021688fccdefa7417af16 (patch)
tree894150454afb0008551108b10334f421789ae572
parent18d4c6e8250324d084d89b17ad80721bb46ddbd9 (diff)
downloadqtwebengine-chromium-b5d06a4582837e4fa6e021688fccdefa7417af16.tar.gz
[Backport] Security issue 946978 [1/2]
Fail decoder / SharedContextState creation if context is lost When the context is lost during creation, on some drivers we may have had bogus values during initialization for the static queries, which means we might have constructed a ContextState that's inconsistent with other ContextStates for the same real context, which causes problems when doing virtualized context switches. So check reset state after initialization and fail if the context is lost. Bug: 946978 Change-Id: I38fb73d819dfcedf0565e6b4345c3700c49fbb07 Commit-Queue: Antoine Labour <piman@chromium.org> Reviewed-by: Zhenyao Mo <zmo@chromium.org> Auto-Submit: Antoine Labour <piman@chromium.org> Cr-Commit-Position: refs/heads/master@{#670301} Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--chromium/gpu/BUILD.gn1
-rw-r--r--chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc12
-rw-r--r--chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc8
-rw-r--r--chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc42
-rw-r--r--chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h31
-rw-r--r--chromium/gpu/command_buffer/service/raster_decoder_unittest_base.cc5
-rw-r--r--chromium/gpu/command_buffer/service/shared_context_state.cc18
7 files changed, 87 insertions, 30 deletions
diff --git a/chromium/gpu/BUILD.gn b/chromium/gpu/BUILD.gn
index 9974be5f0cc..308f0e4106e 100644
--- a/chromium/gpu/BUILD.gn
+++ b/chromium/gpu/BUILD.gn
@@ -407,6 +407,7 @@ test("gpu_unittests") {
"command_buffer/service/shader_manager_unittest.cc",
"command_buffer/service/shader_translator_cache_unittest.cc",
"command_buffer/service/shader_translator_unittest.cc",
+ "command_buffer/service/shared_context_state_unittest.cc",
"command_buffer/service/sync_point_manager_unittest.cc",
"command_buffer/service/test_helper.cc",
"command_buffer/service/test_helper.h",
diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 44c494c67a7..51d566483ac 100644
--- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -4047,6 +4047,18 @@ gpu::ContextResult GLES2DecoderImpl::Initialize(
api()->glHintFn(GL_TEXTURE_FILTERING_HINT_CHROMIUM, GL_NICEST);
}
+ if (CheckResetStatus()) {
+ // If the context was lost at any point before or during initialization, the
+ // values queried from the driver could be bogus, and potentially
+ // inconsistent between various ContextStates on the same underlying real GL
+ // context. Make sure to report the failure early, to not allow virtualized
+ // context switches in that case.
+ LOG(ERROR)
+ << " GLES2DecoderImpl: Context reset detected after initialization.";
+ group_->LoseContexts(error::kUnknown);
+ return gpu::ContextResult::kTransientFailure;
+ }
+
return gpu::ContextResult::kSuccess;
}
diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index a982b5ceb93..bfee5911b04 100644
--- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -582,6 +582,14 @@ TEST_P(GLES3DecoderTest, WaitSyncValidArgs) {
EXPECT_EQ(GL_NO_ERROR, GetGLError());
}
+TEST_P(GLES2DecoderManualInitTest, InitFailsIfLostContext) {
+ InitState init;
+ init.extensions = "GL_KHR_robustness";
+ init.lose_context_on_init = true;
+ EXPECT_EQ(ContextResult::kTransientFailure,
+ MaybeInitDecoderWithWorkarounds(init, GpuDriverBugWorkarounds()));
+}
+
TEST_P(GLES2DecoderManualInitTest, BindGeneratesResourceFalse) {
InitState init;
InitDecoder(init);
diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 856224e909e..314fa42670d 100644
--- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -168,21 +168,10 @@ void GLES2DecoderTestBase::AddExpectationsForVertexAttribManager() {
}
}
-GLES2DecoderTestBase::InitState::InitState()
- : extensions("GL_EXT_framebuffer_object"),
- gl_version("2.1"),
- has_alpha(false),
- has_depth(false),
- has_stencil(false),
- request_alpha(false),
- request_depth(false),
- request_stencil(false),
- bind_generates_resource(false),
- lose_context_when_out_of_memory(false),
- use_native_vao(true),
- context_type(CONTEXT_TYPE_OPENGLES2) {}
-
+GLES2DecoderTestBase::InitState::InitState() = default;
GLES2DecoderTestBase::InitState::InitState(const InitState& other) = default;
+GLES2DecoderTestBase::InitState& GLES2DecoderTestBase::InitState::operator=(
+ const InitState& other) = default;
void GLES2DecoderTestBase::InitDecoder(const InitState& init) {
gpu::GpuDriverBugWorkarounds workarounds;
@@ -192,6 +181,13 @@ void GLES2DecoderTestBase::InitDecoder(const InitState& init) {
void GLES2DecoderTestBase::InitDecoderWithWorkarounds(
const InitState& init,
const gpu::GpuDriverBugWorkarounds& workarounds) {
+ ContextResult result = MaybeInitDecoderWithWorkarounds(init, workarounds);
+ ASSERT_EQ(result, gpu::ContextResult::kSuccess);
+}
+
+ContextResult GLES2DecoderTestBase::MaybeInitDecoderWithWorkarounds(
+ const InitState& init,
+ const gpu::GpuDriverBugWorkarounds& workarounds) {
InitState normalized_init = init;
NormalizeInitState(&normalized_init);
// For easier substring/extension matching
@@ -480,6 +476,12 @@ void GLES2DecoderTestBase::InitDecoderWithWorkarounds(
}
#endif
+ if (context_->WasAllocatedUsingRobustnessExtension()) {
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB())
+ .WillOnce(Return(init.lose_context_on_init ? GL_GUILTY_CONTEXT_RESET_ARB
+ : GL_NO_ERROR));
+ }
+
scoped_refptr<gpu::Buffer> buffer =
command_buffer_service_->CreateTransferBufferHelper(kSharedBufferSize,
&shared_memory_id_);
@@ -510,9 +512,14 @@ void GLES2DecoderTestBase::InitDecoderWithWorkarounds(
decoder_->SetCopyTexImageBlitterForTest(copy_tex_image_blitter_);
}
- ASSERT_EQ(decoder_->Initialize(surface_, context_, false,
- DisallowedFeatures(), attribs),
- gpu::ContextResult::kSuccess);
+ gpu::ContextResult result = decoder_->Initialize(
+ surface_, context_, false, DisallowedFeatures(), attribs);
+ if (result != gpu::ContextResult::kSuccess) {
+ decoder_->Destroy(false /* have_context */);
+ decoder_.reset();
+ group_->Destroy(mock_decoder_.get(), false);
+ return result;
+ }
EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(true));
if (context_->WasAllocatedUsingRobustnessExtension()) {
@@ -564,6 +571,7 @@ void GLES2DecoderTestBase::InitDecoderWithWorkarounds(
}
EXPECT_EQ(GL_NO_ERROR, GetGLError());
+ return result;
}
void GLES2DecoderTestBase::ResetDecoder() {
diff --git a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 0ba7ee75291..5bf869b095f 100644
--- a/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/chromium/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -215,24 +215,29 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool>,
struct InitState {
InitState();
InitState(const InitState& other);
-
- std::string extensions;
- std::string gl_version;
- bool has_alpha;
- bool has_depth;
- bool has_stencil;
- bool request_alpha;
- bool request_depth;
- bool request_stencil;
- bool bind_generates_resource;
- bool lose_context_when_out_of_memory;
- bool use_native_vao; // default is true.
- ContextType context_type;
+ InitState& operator=(const InitState& other);
+
+ std::string extensions = "GL_EXT_framebuffer_object";
+ std::string gl_version = "2.1";
+ bool has_alpha = false;
+ bool has_depth = false;
+ bool has_stencil = false;
+ bool request_alpha = false;
+ bool request_depth = false;
+ bool request_stencil = false;
+ bool bind_generates_resource = false;
+ bool lose_context_when_out_of_memory = false;
+ bool lose_context_on_init = false;
+ bool use_native_vao = true;
+ ContextType context_type = CONTEXT_TYPE_OPENGLES2;
};
void InitDecoder(const InitState& init);
void InitDecoderWithWorkarounds(const InitState& init,
const GpuDriverBugWorkarounds& workarounds);
+ ContextResult MaybeInitDecoderWithWorkarounds(
+ const InitState& init,
+ const GpuDriverBugWorkarounds& workarounds);
void ResetDecoder();
diff --git a/chromium/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/chromium/gpu/command_buffer/service/raster_decoder_unittest_base.cc
index 7c953e1c84c..983f8dca4d1 100644
--- a/chromium/gpu/command_buffer/service/raster_decoder_unittest_base.cc
+++ b/chromium/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -240,6 +240,11 @@ void RasterDecoderTestBase::InitDecoder(const InitState& init) {
SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable());
SetupInitStateExpectations(group_->feature_info()->IsES3Capable());
+ if (context_->WasAllocatedUsingRobustnessExtension()) {
+ EXPECT_CALL(*gl_, GetGraphicsResetStatusARB())
+ .WillOnce(Return(GL_NO_ERROR));
+ }
+
shared_context_state_ = base::MakeRefCounted<SharedContextState>(
new gl::GLShareGroup(), surface_, context_,
feature_info->workarounds().use_virtualized_gl_contexts,
diff --git a/chromium/gpu/command_buffer/service/shared_context_state.cc b/chromium/gpu/command_buffer/service/shared_context_state.cc
index 02acb107330..ffb188ceb82 100644
--- a/chromium/gpu/command_buffer/service/shared_context_state.cc
+++ b/chromium/gpu/command_buffer/service/shared_context_state.cc
@@ -169,6 +169,24 @@ bool SharedContextState::InitializeGL(
context_state_->InitCapabilities(nullptr);
context_state_->InitState(nullptr);
+ bool has_robustness = (feature_info_->feature_flags().arb_robustness ||
+ feature_info_->feature_flags().khr_robustness ||
+ feature_info_->feature_flags().ext_robustness) &&
+ real_context_->WasAllocatedUsingRobustnessExtension();
+ if (has_robustness) {
+ GLenum driver_status = api->glGetGraphicsResetStatusARBFn();
+ if (driver_status != GL_NO_ERROR) {
+ // If the context was lost at any point before or during initialization,
+ // the values queried from the driver could be bogus, and potentially
+ // inconsistent between various ContextStates on the same underlying real
+ // GL context. Make sure to report the failure early, to not allow
+ // virtualized context switches in that case.
+ feature_info_ = nullptr;
+ context_state_ = nullptr;
+ return false;
+ }
+ }
+
if (use_virtualized_gl_contexts_) {
auto virtual_context = base::MakeRefCounted<GLContextVirtual>(
share_group_.get(), real_context_.get(),