CVE-2024-34743 AI-generated analysis
platform/frameworks/native, SurfaceFlinger (services/surfaceflinger)
Changes the sanitization loop in SurfaceFlinger::setTransactionState to iterate ComposerState entries by reference (auto&) instead of by value, so layer_state_t::sanitize(permissions) actually strips privileged fields from the states that are later applied.
Root cause
In services/surfaceflinger/SurfaceFlinger.cpp, SurfaceFlinger::setTransactionState computes the caller's permissions via LayerStatePermissions::getTransactionPermissions(originPid, originUid) and then loops `for (auto composerState : states) { composerState.state.sanitize(permissions); }`. Because the loop variable is declared `auto` (by value), each iteration operates on a copy of the ComposerState. sanitize() cleared privileged fields on the copy, which was then discarded. The original entries in `states` stayed unsanitized, so permission-gated layer state from an unprivileged caller was not removed. The trusted-overlay flag is the example exercised in the test.
How the fix works
- services/surfaceflinger/SurfaceFlinger.cpp:SurfaceFlinger::setTransactionState: the loop is changed to `for (auto& composerState : states)`, so composerState.state.sanitize(permissions) mutates the actual elements of the `states` Vector. This one-line change is the only production code change.
- services/surfaceflinger/tests/Credentials_test.cpp:TEST_F(CredentialsTest, TransactionPermissionTest): the test is fixed so it actually exercises the path. Previously `Transaction().setTrustedOverlay(surfaceControl, true)` was built but never applied, and the waitForWindowInfosPredicate results were not asserted. Now the unprivileged attempt runs under `UIDFaker f{AID_BIN}` and calls `.apply(/*synchronous=*/true)`. The privileged attempt under AID_SYSTEM also applies synchronously. Both predicate waits are wrapped in ASSERT_TRUE, which verifies that the layer is not trusted after the unprivileged attempt and is trusted after the privileged one.
Completeness
- Covers the single ComposerState sanitization loop in setTransactionState. After the change, all entries in `states` are sanitized according to the caller's permissions, for every field that layer_state_t::sanitize handles (not only trusted overlay).
- The DisplayState loop and the inputWindowCommands / eEarlyWakeup permission checks in the same function are not touched by the diff. At android-security-14.0.0_r29 the display loop iterates by reference (`DisplayState& display`).
- The fix does not alter what layer_state_t::sanitize removes. If sanitize itself omits a privileged field, this change does not address that (not shown in the material).
- At android-security-14.0.0_r29 the code context shows the `auto&` form in place, confirming the fix persisted in the Android 14 security branch.
Behavior changes
- Permission-gated layer state fields set by callers that lack the matching permission are now actually stripped before the transaction is applied. Such requests fail silently, with no new error code, consistent with the test comment 'This should fail silently'.
- Privileged callers (e.g. AID_SYSTEM in the test) are unaffected.
- CredentialsTest.TransactionPermissionTest now applies transactions synchronously and asserts the results, so it can fail where previously it was effectively a no-op.
Per major
- Android 14: same fix: commit 3f85323b27d9 in android-security-14.0.0_r11 (cherry-pick of 04e41761914c3c3aaca965103be3679b7a7af76f), a one-line `auto` -> `auto&` change plus a test fix. The code at android-security-14.0.0_r29 shows the `auto&` loop present.
- Android 15: not affected per the bulletin. 5/8 lines of the patched region present at android-security-15.0.0_r17. The loop form in this branch is not shown.
- Android 16: not affected per the bulletin. 5/8 lines of the patched region present at android-security-16.0.0_r8. The loop form in this branch is not shown.
- Android 17: not affected per the bulletin. 5/8 lines of the patched region present at android-security-17.0.0_r1. The loop form in this branch is not shown.
Unknowns
- The exact set of fields cleared by layer_state_t::sanitize(permissions) and the LayerStatePermissions::getTransactionPermissions logic are not included in the material.
- Whether the Android 15/16/17 branches contain the `auto&` form is not shown textually. Android 14 r29, which has the fix, also shows only 5/8 lines.
- The production callers that reach setTransactionState are not shown in the material.
- Which specific privileged field(s) motivated bugs 336648041 and 336648613, beyond the trusted-overlay case exercised by the test.