← All issues

[16] ANGLE Metal: initialize missing fragment shader output components

Severity: Medium | Component: ANGLE MSL translator (ModifyStruct) | 3043c63

좁은 fragment output에서 초기화되지 않은 G/B/A 바이트가 readPixels까지 전달되어, 픽셀당 1~4바이트의 잔류 데이터가 임의의 웹 origin에서 수동으로 읽힐 수 있기 때문에 Medium으로 평가됩니다. 공격자의 제어 가능성은 낮으며, Metal register allocator의 상태에 의존합니다.

Source/ThirdParty/ANGLE/src/compiler/translator/msl/ModifyStruct.cpp

+ for (uint8_t d = dim; d < saturation; ++d)
+ {
+ state.addConversion([=](Access::Env &, OriginalAccess &, ModifiedAccess &m) {
+ auto &m_ = AccessIndex(m, d);
+ return Access{*CreateZeroNode(m_.getType()), m_};
+ });
+ }

SaturateScalarOrVectorCommon에 두 번째 루프가 추가되었습니다. 이 루프는 [dim, saturation) 범위의 component index에 대해 zero-initialization conversion lambda를 생성합니다. 이 범위는 Metal 친화적으로 확장된 struct에는 존재하지만, 원래의 GLSL fragment shader output에는 없는 component들에 해당합니다. 누락된 각 component d에 대해, 해당 타입에 맞는 CreateZeroNodeAccessIndex(m, d)를 감싸는 conversion이 등록됩니다. regression test는 layout(location=0) out float outColor;를 선언하고 RGBA target에 렌더링한 뒤, readPixels(255, 0, 0, 0)을 반환하는지 검증합니다.

Shader translation widening pass에서 확장된 output component가 초기화되지 않은 채 공격자가 읽을 수 있는 framebuffer pixel로 누출됩니다.

WebGL2에서 fragment shader는 바인딩된 color attachment보다 component 수가 적은 output을 선언할 수 있습니다. 이때 spec은 누락된 component를 zero로 읽도록 요구합니다. Metal의 엄격한 struct layout 규칙을 충족하기 위해, ANGLE의 ModifyStruct pass는 사용자의 output struct를 확장합니다. ConvertStructStatestate.addConversion(...)을 통해 ConversionFunc lambda를 누적하며, 이후 pass가 이를 original에서 modified struct 필드로의 MSL assignment로 생성합니다. SaturateScalarOrVectorCommon은 scalar/vector 필드를 dim에서 saturation으로 확장하는 역할을 담당합니다.

패치 이전에는 해당 helper가 [0, dim) 범위에 대해서만 conversion lambda를 생성했습니다. 즉, outColor를 modified[0]에 복사하는 처리만 이루어졌습니다. [dim, saturation) 범위의 component에는 conversion이 등록되지 않아, 생성된 MSL이 shader의 local/register 상태에 남아 있던 값을 그대로 framebuffer에 기록하는 상황이었습니다.

🔒

Detailed look at how a shader-translation widening pass turns into a cross-process information-disclosure primitive readable from JavaScript, and the bounds of what an attacker can actually scrape.

더 확인하려면 구독해 주세요

🔒

Multiple reusable audit patterns identified — translation-layer widening, readback-surface guarantees, and cross-backend parity — each with concrete starting points in ANGLE's translator tree.

더 확인하려면 구독해 주세요