diff options
| author | 2022-01-17 16:47:16 +0800 | |
|---|---|---|
| committer | 2022-01-18 16:45:33 +0800 | |
| commit | 8423dd15ff7b12687d6726ce555f7a0717ae7f14 (patch) | |
| tree | 18f40d5ffec7ad409d7f13ce6150b3aa6ea45f91 | |
| parent | 35eef324464aee9d46301815ddad3d65578bf1a8 (diff) | |
Verify the incoming package first.
The callingPackage is a parameter from the Binder, and the caller
could forge any name they want. We should verify if it's trusted.
Bug: 194105935
Bug: 194106074
Bug: 214894893
Test: atest -p core/java/android/app/
Test: atest -p services/tests/servicestests/src/com/android/server/am
Test: manually using the PoC in the buganizer to ensure the symptom
no longer exists.
Change-Id: Ib7b4676d5c54df304d896b9f8260fe08c79dd3ce
3 files changed, 58 insertions, 27 deletions
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 70bd734a9ccd..96594d5ea4e1 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2870,13 +2870,51 @@ public class ActivityManagerService extends IActivityManager.Stub return mode == AppOpsManager.MODE_ALLOWED; } - @Override - public int getPackageProcessState(String packageName, String callingPackage) { + /** + * Checks whether the calling package is trusted. + * + * The calling package is trusted if it's from system or the supposed package name matches the + * UID making the call. + * + * @throws SecurityException if the package name and UID don't match. + */ + private void verifyCallingPackage(String callingPackage) { + final int callingUid = Binder.getCallingUid(); + // The caller is System or Shell. + if (callingUid == SYSTEM_UID || isCallerShell()) { + return; + } + + // Handle the special UIDs that don't have real package (audioserver, cameraserver, etc). + final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, + null /* packageName */); + if (resolvedPackage != null && resolvedPackage.equals(callingPackage)) { + return; + } + + final int claimedUid = getPackageManagerInternal().getPackageUid(callingPackage, + 0 /* flags */, UserHandle.getUserId(callingUid)); + if (callingUid == claimedUid) { + return; + } + + throw new SecurityException( + "Claimed calling package " + callingPackage + " does not match the calling UID " + + Binder.getCallingUid()); + } + + private void enforceUsageStatsPermission(String callingPackage, String func) { + verifyCallingPackage(callingPackage); + // Since the protection level of PACKAGE_USAGE_STATS has 'appop', apps may grant this + // permission via that way. We need to check both app-ops and permission. if (!hasUsageStatsPermission(callingPackage)) { - enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, - "getPackageProcessState"); + enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, func); } + } + @Override + public int getPackageProcessState(String packageName, String callingPackage) { + enforceUsageStatsPermission(callingPackage, "getPackageProcessState"); final int[] procState = {PROCESS_STATE_NONEXISTENT}; synchronized (mProcLock) { mProcessList.forEachLruProcessesLOSP(false, proc -> { @@ -6937,11 +6975,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public int getUidProcessState(int uid, String callingPackage) { - if (!hasUsageStatsPermission(callingPackage)) { - enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, - "getUidProcessState"); - } - + enforceUsageStatsPermission(callingPackage, "getUidProcessState"); synchronized (mProcLock) { return mProcessList.getUidProcStateLOSP(uid); } @@ -6949,11 +6983,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public @ProcessCapability int getUidProcessCapabilities(int uid, String callingPackage) { - if (!hasUsageStatsPermission(callingPackage)) { - enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, - "getUidProcessState"); - } - + enforceUsageStatsPermission(callingPackage, "getUidProcessCapabilities"); synchronized (mProcLock) { return mProcessList.getUidProcessCapabilityLOSP(uid); } @@ -6962,10 +6992,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void registerUidObserver(IUidObserver observer, int which, int cutpoint, String callingPackage) { - if (!hasUsageStatsPermission(callingPackage)) { - enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, - "registerUidObserver"); - } + enforceUsageStatsPermission(callingPackage, "registerUidObserver"); mUidObserverController.register(observer, which, cutpoint, callingPackage, Binder.getCallingUid()); } @@ -6977,10 +7004,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public boolean isUidActive(int uid, String callingPackage) { - if (!hasUsageStatsPermission(callingPackage)) { - enforceCallingPermission(android.Manifest.permission.PACKAGE_USAGE_STATS, - "isUidActive"); - } + enforceUsageStatsPermission(callingPackage, "isUidActive"); synchronized (mProcLock) { if (isUidActiveLOSP(uid)) { return true; diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index df6ffa2bd009..0cc625d203ad 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -168,7 +168,7 @@ final class VibrationSettings { try { ActivityManager.getService().registerUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, - ActivityManager.PROCESS_STATE_UNKNOWN, null); + ActivityManager.PROCESS_STATE_UNKNOWN, mContext.getOpPackageName()); } catch (RemoteException e) { // ignored; both services live in system_server } diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java index 36c37c4dbf2a..677f0f642e6e 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -541,11 +541,14 @@ public class ActivityManagerServiceTest { | ActivityManager.UID_OBSERVER_CAPABILITY }; final IUidObserver[] observers = new IUidObserver.Stub[changesToObserve.length]; + doReturn(Process.myUid()).when(sPackageManagerInternal) + .getPackageUid(mContext.getOpPackageName(), 0 /* flags */, mContext.getUserId()); for (int i = 0; i < observers.length; ++i) { observers[i] = mock(IUidObserver.Stub.class); when(observers[i].asBinder()).thenReturn((IBinder) observers[i]); mAms.registerUidObserver(observers[i], changesToObserve[i] /* which */, - ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, null /* caller */); + ActivityManager.PROCESS_STATE_UNKNOWN /* cutpoint */, + mContext.getOpPackageName()); // When we invoke AMS.registerUidObserver, there are some interactions with observers[i] // mock in RemoteCallbackList class. We don't want to test those interactions and @@ -674,10 +677,12 @@ public class ActivityManagerServiceTest { mockNoteOperation(); final IUidObserver observer = mock(IUidObserver.Stub.class); - when(observer.asBinder()).thenReturn((IBinder) observer); + doReturn(Process.myUid()).when(sPackageManagerInternal) + .getPackageUid(mContext.getOpPackageName(), 0 /* flags */, mContext.getUserId()); mAms.registerUidObserver(observer, ActivityManager.UID_OBSERVER_PROCSTATE /* which */, - ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, null /* callingPackage */); + ActivityManager.PROCESS_STATE_SERVICE /* cutpoint */, + mContext.getOpPackageName()); // When we invoke AMS.registerUidObserver, there are some interactions with observer // mock in RemoteCallbackList class. We don't want to test those interactions and // at the same time, we don't want those to interfere with verifyNoMoreInteractions. @@ -771,7 +776,9 @@ public class ActivityManagerServiceTest { final IUidObserver observer = mock(IUidObserver.Stub.class); when(observer.asBinder()).thenReturn((IBinder) observer); - mAms.registerUidObserver(observer, 0, 0, null); + doReturn(Process.myUid()).when(sPackageManagerInternal) + .getPackageUid(mContext.getOpPackageName(), 0 /* flags */, mContext.getUserId()); + mAms.registerUidObserver(observer, 0, 0, mContext.getOpPackageName()); // Verify that when observers are registered, then validateUids is correctly updated. addPendingUidChanges(pendingItemsForUids); mAms.mUidObserverController.dispatchUidsChanged(); |