From 917c63fca668939db6c25fd4c950bcd3c1579822 Mon Sep 17 00:00:00 2001 From: Patrick Baumann Date: Thu, 4 Feb 2021 09:57:41 -0800 Subject: [PATCH] Visibility checks for checkPackage and watchingMode This change adds a check for app visibility to calls to checkPackage and startWatchingMode to ensure that the subject package name should be visible to the caller before taking action. Test: atest AppOpTests CtsAppOpsTestCases Bug: 179047153 Change-Id: I8a5b2e355656a5409f6712d8d131adc7873f2f14 --- .../android/server/appop/AppOpsService.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index f07da8f0236b9..10fe1e1d06848 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2796,6 +2796,8 @@ public class AppOpsService extends IAppOpsService.Stub { if (callback == null) { return; } + final boolean mayWatchPackageName = + packageName != null && !filterAppAccessUnlocked(packageName); synchronized (this) { int switchOp = (op != AppOpsManager.OP_NONE) ? AppOpsManager.opToSwitch(op) : op; @@ -2824,7 +2826,7 @@ public class AppOpsService extends IAppOpsService.Stub { } cbs.add(cb); } - if (packageName != null) { + if (mayWatchPackageName) { ArraySet cbs = mPackageModeWatchers.get(packageName); if (cbs == null) { cbs = new ArraySet<>(); @@ -3008,13 +3010,27 @@ public class AppOpsService extends IAppOpsService.Stub { Objects.requireNonNull(packageName); try { verifyAndGetBypass(uid, packageName, null); - + if (filterAppAccessUnlocked(packageName)) { + return AppOpsManager.MODE_ERRORED; + } return AppOpsManager.MODE_ALLOWED; } catch (SecurityException ignored) { return AppOpsManager.MODE_ERRORED; } } + /** + * This method will check with PackageManager to determine if the package provided should + * be visible to the {@link Binder#getCallingUid()}. + * + * NOTE: This must not be called while synchronized on {@code this} to avoid dead locks + */ + private boolean filterAppAccessUnlocked(String packageName) { + final int callingUid = Binder.getCallingUid(); + return LocalServices.getService(PackageManagerInternal.class) + .filterAppAccess(packageName, callingUid, UserHandle.getUserId(callingUid)); + } + @Override public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName, String proxiedAttributionTag, int proxyUid, String proxyPackageName,