CVE-2025-48649 AI-generated analysis
platform/frameworks/base, ActivityManagerService / PackageManagerService / permission (resetRuntimePermissions)
Threads a restorePregrantedPermissions flag from ActivityManager through ActivityManagerService, PackageManagerService and PermissionManagerServiceImpl so that an app clearing its own data (public ActivityManager.clearApplicationUserData()) no longer gets default- or role-granted runtime permissions re-granted by the system, while callers holding CLEAR_APP_USER_DATA keep the old restoring behaviour.
Root cause
ActivityManagerService.clearApplicationUserData permits a caller without CLEAR_APP_USER_DATA when the target package has the caller's own uid (applicationInfo.uid == uid). That path calls IPackageManager.clearApplicationUserData after Binder.clearCallingIdentity, which in PackageManagerService.clearApplicationUserDataLIF calls mPermissionManager.resetRuntimePermissions(pkg, userId). In PermissionManagerServiceImpl.resetRuntimePermissionsInternal, every permission carrying FLAG_PERMISSION_GRANTED_BY_DEFAULT or FLAG_PERMISSION_GRANTED_BY_ROLE was unconditionally re-granted via grantRuntimePermissionInternal(..., Process.SYSTEM_UID, ...). As a result the public, unprivileged ActivityManager.clearApplicationUserData() let an app have previously pregranted runtime permissions restored for itself, which the bulletin rates as a High EoP.
How the fix works
- core/java/android/app/ActivityManager.java: clearApplicationUserData() (self, public API) now calls a new private overload with restorePregrantedPermissions=false, which invokes the new binder method IActivityManager.clearApplicationUserDataWithoutPermissionReset; the hidden two-arg clearApplicationUserData(packageName, observer) keeps restoring (true) and uses the original binder method.
- core/java/android/app/IActivityManager.aidl: adds clearApplicationUserDataWithoutPermissionReset(packageName, keepState, observer, userId).
- services/core/java/com/android/server/am/ActivityManagerService.java: clearApplicationUserData (binder) delegates with true, clearApplicationUserDataWithoutPermissionReset delegates with false, to a new private clearApplicationUserData(..., restorePregrantedPermissions). The own-uid exemption is tightened to (applicationInfo.uid == uid && !restorePregrantedPermissions); otherwise CLEAR_APP_USER_DATA is required. The flag is forwarded to pm.clearApplicationUserData(packageName, localObserver, resolvedUserId, restorePregrantedPermissions).
- core/java/android/content/pm/IPackageManager.aidl and services/core/java/com/android/server/pm/PackageManagerService.java: the binder clearApplicationUserData in PackageManagerService gains the boolean (still enforces CLEAR_APP_USER_DATA) and passes it to clearApplicationUserDataLIF, which passes it to mPermissionManager.resetRuntimePermissions(pkg, userId, restorePregrantedPermissions). core/java/android/app/ApplicationPackageManager.java passes true; core/java/android/content/pm/PackageManager.java adds @RequiresPermission(CLEAR_APP_USER_DATA) on the abstract method.
- services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java: resetRuntimePermissions and both resetRuntimePermissionsInternal overloads take restorePregrantedPermissions; the grantRuntimePermissionInternal call for FLAG_PERMISSION_GRANTED_BY_DEFAULT / FLAG_PERMISSION_GRANTED_BY_ROLE permissions is now executed only when the flag is true, otherwise the grant state is left unchanged. resetRuntimePermissionsForUser and the uninstall-with-keep-data path pass true.
- Interface plumbing: PermissionManagerServiceInterface, PermissionManagerServiceInternal, PermissionManagerService (Internal), PermissionManagerServiceLoggingDecorator, LegacyPermissionManagerService (passes true) and PermissionService.kt (signature only; body is a TODO stub on 14) updated to the new 3-arg signature; CrossUserPackageVisibilityTests updated to pass true.
Completeness
- Covers the unprivileged self-clear path: the public ActivityManager.clearApplicationUserData() and the new clearApplicationUserDataWithoutPermissionReset binder are the only paths where the own-uid exemption still applies, and they never re-grant pregranted permissions.
- Calling the original IActivityManager.clearApplicationUserData binder (restore=true) for one's own package now requires CLEAR_APP_USER_DATA, since the own-uid exemption is conditioned on !restorePregrantedPermissions.
- IPackageManager.clearApplicationUserData and ApplicationPackageManager.clearApplicationUserData keep restoring (true) but are gated by CLEAR_APP_USER_DATA in PackageManagerService, so they are not reachable by unprivileged apps.
- Privileged callers (Settings AppStorageSettings.initiateClearUserData and Car Settings via the hidden two-arg ActivityManager method, per index search; LegacyPermissionManagerService.resetRuntimePermissions, resetRuntimePermissionsForUser, uninstall-keep-data path) keep the previous restore behaviour by passing true.
- On Android 14 only the legacy PermissionManagerServiceImpl implementation is changed behaviourally; PermissionService.kt.resetRuntimePermissions is a TODO stub in this branch, so no Kotlin policy change was needed (15/16 additionally change AppIdPermissionPolicy.kt).
- The code block after pm.clearApplicationUserData in ActivityManagerService that the diff context describes as 'Restore already established notification state and permission grants' is not modified by this fix; the material does not show its contents.
Behavior changes
- An app clearing its own data via ActivityManager.clearApplicationUserData() no longer has permissions flagged GRANTED_BY_DEFAULT or GRANTED_BY_ROLE re-granted; their grant state is left as it was before the clear.
- A caller without CLEAR_APP_USER_DATA invoking the hidden IActivityManager.clearApplicationUserData for its own package is no longer permitted (permitted evaluates to false), where previously it was permitted; the resulting failure reporting is not shown in the diff.
- New hidden binder method IActivityManager.clearApplicationUserDataWithoutPermissionReset; IPackageManager.clearApplicationUserData, PermissionManagerServiceInternal.resetRuntimePermissions and PermissionManagerServiceInterface.resetRuntimePermissions change signature (extra boolean).
- PermissionManagerServiceLoggingDecorator log line now includes shouldRestorePregrants.
Per major
- Android 14: Fixed by c1f49d2c2cac (RESTRICT AUTOMERGE) in android-security-14.0.0_r25; 15 files; AMS in this branch has no isRestore overload or LocalService.clearApplicationUserData hunk; PermissionService.kt only gets a signature change (body is a TODO). 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: Adapted fix 452f0beb15a9 in android-security-15.0.0_r13: same core change plus threading through the isRestore overload and LocalService.clearApplicationUserData (passes true), updates to PermissionManagerServiceTestingShim and PermissionManagerServiceTracingDecorator, AppIdPermissionPolicy.kt.resetRuntimePermissions honours restorePregrants (RUNTIME_GRANTED only or'ed in when true), PermissionService.kt forwards the flag, tests updated. 8/8 present at android-security-15.0.0_r17.
- Android 16: Adapted fix 7b9a906980a3 in android-security-16.0.0_r4, same shape as 15 (AppIdPermissionPolicy.kt condition also includes isSystemOrInstalled). 8/8 present at android-security-16.0.0_r8.
- Android 17: Resolved in base android-17.0.0_r1 (23da448adbb0, RESTRICT AUTOMERGE title); the diff provided for it has the same content as the Android 14 diff, though some pre-image blob hashes differ (PackageManager.java, ActivityManagerService.java, PermissionManagerService.java). 8/8 present at android-security-17.0.0_r1.
Unknowns
- Whether the Android 17 fix differs materially from the 14 commit (the provided 17 diff has the same content but different blob hashes for some files, suggesting a slightly different base).
- Contents of the AMS block that restores 'notification state and permission grants' after pm.clearApplicationUserData, and whether it interacts with pregranted permissions.
- The exact gating of the isPackageDataProtected branch around the permitted computation (context truncated).
- How a denied (permitted == false) call is reported to the caller.
- Whether the Android 14 security branch contains PermissionManagerServiceTracingDecorator/TestingShim (not touched by the 14 diff).