summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jackal Guo <jackalguo@google.com> 2022-01-17 16:47:16 +0800
committer Jackal Guo <jackalguo@google.com> 2022-01-18 16:45:33 +0800
commit8423dd15ff7b12687d6726ce555f7a0717ae7f14 (patch)
tree18f40d5ffec7ad409d7f13ce6150b3aa6ea45f91
parent35eef324464aee9d46301815ddad3d65578bf1a8 (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
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java68
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSettings.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java15
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();