CVE-2023-40140 AI-generated analysis
platform/frameworks/base, core JNI for android.view.InputDevice / KeyCharacterMap (input)
android_view_InputDevice_create now gives the Java KeyCharacterMap a copy of the native KeyCharacterMap (std::make_shared<KeyCharacterMap>(*map)) instead of the shared_ptr it shares with the native InputDeviceInfo, so Java-side reads no longer hit the same instance that native code can modify.
Root cause
In core/jni/android_view_InputDevice.cpp, android_view_InputDevice_create passed deviceInfo.getKeyCharacterMap() (a std::shared_ptr<KeyCharacterMap>) directly to android_view_KeyCharacterMap_create. As a result, the Java KeyCharacterMap object and the native key mappings shared one instance. The commit message says a read could be attempted while the mappings were being modified.
How the fix works
- core/jni/android_view_InputDevice.cpp:android_view_InputDevice_create: obtain std::shared_ptr<KeyCharacterMap> map = deviceInfo.getKeyCharacterMap(); if it is non-null, replace it with std::make_shared<KeyCharacterMap>(*map), a separate copy made with the KeyCharacterMap copy constructor.
- The call android_view_KeyCharacterMap_create(env, deviceInfo.getId(), ...) now receives map (the copy) instead of deviceInfo.getKeyCharacterMap(), so the Java-visible KeyCharacterMap no longer points to the native instance. A null map is still passed through as nullptr.
- Both commits (3839e41580d0 in android-security-14.0.0_r1 and 5ae8ed07ace7 in android-security-14.0.0_r2) have the same Change-Id I745008a0a8ea30830660c45dcebee917b3913d13 and an identical diff. This is one change appearing in two release tags, not a two-step fix.
Completeness
- Covers the single sharing point in android_view_InputDevice_create: every Java InputDevice created through this JNI path gets its own KeyCharacterMap copy.
- Adds no locking or synchronization on the native KeyCharacterMap itself; it only separates the Java object from the native one. Other native consumers that may read the shared map while it is being modified are not addressed (none are shown in the material).
- Relies on the KeyCharacterMap copy constructor producing an independent copy of all mapping state. The copy constructor is not in the material.
- Any other call sites of android_view_KeyCharacterMap_create that pass a shared native map are not touched by this diff. The material does not show whether such call sites exist.
Behavior changes
- One extra KeyCharacterMap allocation and copy each time a Java InputDevice object is created.
- The Java KeyCharacterMap is now a copy taken at creation time, so later changes to the native instance are not reflected in an InputDevice object that already exists.
- No new error paths; null maps are still passed through as before.
Per major
- Android 14: same fix: commit 3839e41580d0 in android-security-14.0.0_r1 and the identical commit 5ae8ed07ace7 in android-security-14.0.0_r2 (same Change-Id). At android-security-14.0.0_r29 the resolver matches 6/7 lines of the patched region, and the code context shows the full copy logic in place.
- Android 15: not affected (not listed by the bulletin); 6/7 lines of the patched region are present at android-security-15.0.0_r17.
- Android 16: not affected (not listed by the bulletin); 6/7 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: not affected (not listed by the bulletin); 6/7 lines of the patched region are present at android-security-17.0.0_r1.
Unknowns
- Which native code path modifies the KeyCharacterMap concurrently, and what triggers it.
- The concrete callers of android_view_InputDevice_create, and whether android_view_KeyCharacterMap_create is called elsewhere with a shared native map.
- Whether the KeyCharacterMap copy constructor fully copies all internal state.
- How the fix was applied on Android 11, 12, 12L and 13, which the bulletin lists as affected. No commits for those branches are in the material, and neither is the type returned by getKeyCharacterMap() there.
- Why the resolver reports 6/7 lines on all branches when the code shown contains the full patched region.