CVE-2023-40105 AI-generated analysis
platform/frameworks/base, ActivityManagerService (backup agent callback, services/core/java/com/android/server/am)
Adds a check to ActivityManagerService.backupAgentCreated() that compares the caller's uid with the package's uid, so a caller can only report a backup agent for a package that belongs to its own uid.
Root cause
backupAgentCreated(String agentPackageName, IBinder agent, int userId) is a Binder entry point (@Override) in ActivityManagerService. Before the fix it called only mUserController.handleIncomingUser(...) to resolve and check the target user. It never checked that the calling uid owned agentPackageName, so a caller could report a backup agent for a package it does not own. The bulletin classifies this as information disclosure (ID). Per index search, the only uid check on this path is in the app process, in ActivityThread.handleCreateBackupAgent (it compares the requested package's uid to Process.myUid()). That check does not protect the server side.
How the fix works
- services/core/java/com/android/server/am/ActivityManagerService.java: adds a private helper, enforceCallingPackage(String packageName, int callingUid). It sets userId = UserHandle.getUserId(callingUid) and looks up getPackageManagerInternal().getPackageUid(packageName, /*flags=*/0, userId). If the result differs from callingUid, it throws SecurityException(packageName + " does not belong to uid " + callingUid).
- services/core/java/com/android/server/am/ActivityManagerService.java:backupAgentCreated(): reads callingUid = Binder.getCallingUid() once at entry and calls enforceCallingPackage(agentPackageName, callingUid) before handleIncomingUser(). The cached callingUid replaces the later Binder.getCallingUid() calls in the handleIncomingUser argument and the DEBUG_BACKUP log line. The synchronized block is unchanged.
Completeness
- Covers the backupAgentCreated Binder entry point. The new check runs before user resolution and before the synchronized block.
- The lookup uses the caller's own user, not the userId parameter. The call is accepted only if the package resolves to exactly callingUid in that user.
- If the package does not resolve to callingUid in the caller's user (for example, it is not installed there), the call is rejected with SecurityException.
- The client-side check in ActivityThread.handleCreateBackupAgent (per index search) is unchanged. The fix adds server-side enforcement.
- The synchronized block is not shown, and neither are other ActivityManagerService backup APIs. Whether related APIs have comparable checks cannot be judged from this material.
Behavior changes
- backupAgentCreated now throws SecurityException to any caller whose uid does not equal the uid of agentPackageName in the caller's user. Before the fix, such calls went on to handleIncomingUser and the synchronized block.
- The SecurityException is thrown before handleIncomingUser, so a uid mismatch is reported even for callers that would also have failed the cross-user check.
- Normal calls from the agent's own app process (ActivityThread.handleCreateBackupAgent, per index search) are expected to pass, because that path already checks that the package's uid equals the process uid.
- DEBUG_BACKUP log output now uses the cached callingUid value (no functional difference).
Per major
- Android 14: Same fix: [DO NOT MERGE] cherry-pick 06830ff04faa in android-security-14.0.0_r2 (linked by bug 289549315). At android-security-14.0.0_r29 the patched region is fully present (8/8 lines).
- Android 15: Not affected (not listed by the bulletin). The patched region is present at android-security-15.0.0_r17 (8/8 lines).
- Android 16: Not affected (not listed by the bulletin). The patched region is present at android-security-16.0.0_r8 (8/8 lines).
- Android 17: Not affected (not listed by the bulletin). 7/8 lines of the patched region are present at android-security-17.0.0_r1. The differing line is not shown.
Unknowns
- What the synchronized block in backupAgentCreated does with the supplied agent binder (not shown), and therefore the exact nature of the information disclosed.
- Whether the CTS test named in the commit (ActivityManagerTest#testActivityManager_backupAgentCreated_rejectIfCallerUidNotEqualsPackageUid) landed with the fix on each branch.
- Which line of the patched region differs at android-security-17.0.0_r1.
- Which permission checks, if any, exist inside the synchronized block.