CVE-2025-22428 AI-generated analysis
platform/packages/apps/Settings, applications/AppInfoBase (cross-user permission gate)
Settings' AppInfoBase now checks INTERACT_ACROSS_USERS_FULL against the UID that launched the hosting activity (from ActivityManager getLaunchedFromUid) instead of against the package name from SettingsActivity.getInitialCallingPackage().
Root cause
The cross-user gate in src/com/android/settings/applications/AppInfoBase.java got the caller via ((SettingsActivity) activity).getInitialCallingPackage() and ran mPm.checkPermission(INTERACT_ACROSS_USERS_FULL, callingPackageName). The fix title says the permission should be checked for the calling UID, not the calling package. The material does not show exactly how the package-name-based check could fail. The bulletin classifies the issue as EoP, severity High.
How the fix works
- src/com/android/settings/applications/AppInfoBase.java, the INTERACT_ACROSS_USERS_FULL check helper (the method name is outside the hunk; the method begins with 'if (!(activity instanceof SettingsActivity)) return false;'): removes the getInitialCallingPackage()/TextUtils.isEmpty path and the mPm.checkPermission(permission, packageName) call.
- Replaces it with callerUid = ActivityManager.getService().getLaunchedFromUid(activity.getActivityToken()).
- Checks ActivityManager.checkUidPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callerUid). If the result is not PERMISSION_GRANTED, it logs 'Uid <uid> does not have required permission ...' and returns false; otherwise it returns true.
- Wraps the calls in try/catch RemoteException and returns false on failure. Adds imports for android.app.ActivityManager and android.os.RemoteException.
Completeness
- Covers one gate: the cross-user permission helper in AppInfoBase.
- The 'activity instanceof SettingsActivity' check is unchanged; a host that is not a SettingsActivity still gets false.
- On RemoteException the method returns false, so it fails closed.
- The material does not show whether other Settings code uses getInitialCallingPackage() for permission decisions.
Behavior changes
- Permission is now checked for the UID that launched the hosting SettingsActivity instead of for a package name. Callers whose launching UID lacks INTERACT_ACROSS_USERS_FULL are refused.
- The early return for an empty calling package is gone; a RemoteException now returns false.
- The log message changes from 'Package <name> does not have required permission' to 'Uid <uid> does not have required permission'.
Per major
- Android 14: same fix: commit 4a9cb946e978 in android-security-14.0.0_r19 (Change-Id Ib36c0a3b); 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: same fix: commit 9dba6f50302b in android-security-15.0.0_r7, identical diff apart from a hunk offset (line 176 vs 172); 8/8 lines present at android-security-15.0.0_r17.
- Android 16: not affected per the bulletin (not listed); the patched region is present at android-security-16.0.0_r8.
- Android 17: not affected per the bulletin (not listed); the patched region is present at android-security-17.0.0_r1.
Unknowns
- The name of the patched helper method and its callers in AppInfoBase and its subclasses.
- Why the package-name-based check was insufficient (for example, where the initial calling package value comes from).
- The concrete exported entry point and extras used to reach the cross-user path.
- Whether the Android 13 branch received the same commit.
- Whether other Settings components use getInitialCallingPackage() for authorization decisions.