CVE-2025-48630 AI-generated analysis
platform/frameworks/native, libs/renderengine (SkiaRenderEngine blur rendering)
SkiaRenderEngine::drawLayersInternal now clips the canvas to the layer bounds before drawing blur regions when no rounded-corner clip is present, so a client-supplied blur region larger than the layer can no longer draw blurred content outside the layer's bounds.
Root cause
In libs/renderengine/skia/SkiaRenderEngine.cpp, drawLayersInternal() set a canvas clip for blur drawing only when roundRectClip was non-empty (canvas->clipRRect(roundRectClip, true)). When the layer had no rounded corners, no layer-bounds clip was applied. Only the existing device clip limited drawing. As a result, the later blur draws for layer.blurRegions, whose geometry comes from the client per the code comment, were not limited to the layer's bounds. Per the commit message, a crafted blur region on a 1-2 pixel layer could make the blur "escape" the layer bounds and fill the entire screen. The blurred image is generated from blurInput, a snapshot of the content drawn so far.
How the fix works
- libs/renderengine/skia/SkiaRenderEngine.cpp : SkiaRenderEngine::drawLayersInternal(): adds an else branch to the existing `if (!roundRectClip.isEmpty())` block. When there is no rounded-corner clip, the new branch calls `canvas->clipRRect(bounds, true)`, clipping to the layer bounds returned by getBoundsAndClip(). The clip sits inside the existing SkAutoCanvasRestore acr(canvas, true) scope, so it applies to the background blur draw and to the loop over layer.blurRegions. It is restored before any shadow drawing.
- Single commit with 4 added lines. The hunk content is identical on 14, 15 and 16. The commit message lists two internal Cherrypick-From commits.
Completeness
- Covers both the background blur (drawBlurRegion with bounds) and the per-region blur loop over layer.blurRegions, because the clip is set once in the enclosing SkAutoCanvasRestore scope before both.
- Layers with rounded corners are still constrained by the pre-existing roundRectClip branch. The fix only changes the no-rounded-corner path, which is now clipped to `bounds`.
- The fix does not validate or reject oversized blur regions where the client input arrives. It only constrains the rendering output. The diff modifies no other rendering paths.
Behavior changes
- Blur region drawing is now always clipped to the layer's bounds or to its rounded-corner clip. Blur regions that extend beyond the layer no longer render outside it.
- The diff adds no new error codes or logging. The change is purely a rendering restriction.
Per major
- Android 14: same fix: platform/frameworks/native 6906658b06e3 in android-security-14.0.0_r25; 4/4 patched lines present at android-security-14.0.0_r29.
- Android 15: same fix: platform/frameworks/native 4deb93b73906 in android-security-15.0.0_r13 (identical hunk, different line offset); 4/4 lines present at android-security-15.0.0_r17.
- Android 16: same fix: platform/frameworks/native c81cf361489e in android-security-16.0.0_r4 (identical hunk, different line offset); 4/4 lines present at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin); the patched region (4/4 lines) is present at android-security-17.0.0_r1.
Unknowns
- The material does not show how blur region geometry reaches the layer (the SurfaceFlinger/SurfaceControl input path) or whether any validation exists on that input side.
- The two internal Cherrypick-From commits are not shown individually; only the resulting 4-line change is visible.