CVE-2024-0022 AI-generated analysis
platform/frameworks/base, CompanionDeviceManagerService (system_server companion service)
CompanionDeviceManagerService.requestNotificationAccess now passes the caller-supplied userId into checkCanCallNotificationApi/enforceCallerIsSystemOr instead of ignoring it. Per the commit message, this makes sure the calling user id matches the passed user id, so notification access can no longer be requested across users.
Root cause
The binder method requestNotificationAccess(ComponentName component, int userId) took a userId from the caller. However, its permission check checkCanCallNotificationApi(callingPackage) worked out its own userId from getCallingUserId() and never compared it with the passed one (the code carried a "TODO: check userId" comment). The passed userId was still used to build the NotificationAccessConfirmationActivityContract launcher intent and the PendingIntent via getActivityAsUser(..., new UserHandle(userId)), with the calling identity cleared. So the caller checks ran against the calling user while the resulting action targeted the user id the caller supplied.
How the fix works
- services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java:checkCanCallNotificationApi: the signature changes from (String callingPackage) to (String callingPackage, int userId), and the local `final int userId = getCallingUserId()` is removed. enforceCallerIsSystemOr(userId, callingPackage) now runs on the userId passed in by the API's caller; per the commit message, this enforces that the calling user matches it. The remaining checks (the SYSTEM_UID early return and what follows) are unchanged.
- CompanionDeviceManagerService.java:requestNotificationAccess: now calls checkCanCallNotificationApi(callingPackage, userId) with the userId received over binder, and the TODO comment is removed. The PendingIntent construction that follows still uses that userId but is only reached after the check passes.
- CompanionDeviceManagerService.java:hasNotificationAccess (deprecated, takes no userId): now calls checkCanCallNotificationApi(component.getPackageName(), getCallingUserId()), which keeps the previous behavior for this path.
Completeness
- The fix covers requestNotificationAccess, the only method in the diff that takes a caller-supplied userId for notification access. The userId used for the launcher intent and the PendingIntent is now the one that was checked.
- hasNotificationAccess has no userId parameter, so its effect is unchanged (it is still checked against the calling user).
- How strong the check is depends on enforceCallerIsSystemOr(userId, callingPackage), whose body is not in the material.
- The length check on component.flattenToString() and the rest of the method are untouched. No other userId-taking methods of the service are shown, so the material does not show whether sibling paths are covered.
Behavior changes
- Non-system callers of ICompanionDeviceManager.requestNotificationAccess that pass a userId other than their own calling user should now be rejected by the userId-based check. The exact exception type is not shown in the material.
- Callers that pass their own userId should see no change. The public CompanionDeviceManager.requestNotificationAccess wrapper passes mContext.getUserId() (per index search).
- hasNotificationAccess behavior is unchanged.
Per major
- Android 14: same fix: commit bdf1cce569c9 in android-security-14.0.0_r4 (cherry-pick of internal 12bb4ed9ab46). At android-security-14.0.0_r29, 6/8 lines of the patched region are present, and the code context shows checkCanCallNotificationApi(callingPackage, userId).
- Android 15: not affected per the bulletin; 6/8 lines of the patched region are present at android-security-15.0.0_r17.
- Android 16: not affected per the bulletin; 6/8 lines of the patched region are present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin; 6/8 lines of the patched region are present at android-security-17.0.0_r1.
Unknowns
- The body of enforceCallerIsSystemOr and the remaining checks in checkCanCallNotificationApi (which exception is thrown, and whether an association is required).
- Which Android 13 commit carries the fix (the bulletin lists 13 as affected, but the material only shows the 14 commit).
- Why the resolver reports 6/8 rather than 8/8 lines of the patched region in the security tags.