diff options
| -rw-r--r-- | services/core/java/com/android/server/connectivity/PermissionMonitor.java | 162 | ||||
| -rw-r--r-- | tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java | 208 |
2 files changed, 159 insertions, 211 deletions
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index a75a80a606eb..f8774b1b0054 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -21,14 +21,23 @@ import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; import static android.Manifest.permission.INTERNET; import static android.Manifest.permission.NETWORK_STACK; import static android.Manifest.permission.UPDATE_DEVICE_STATS; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.INetd.PERMISSION_INTERNET; +import static android.net.INetd.PERMISSION_NETWORK; +import static android.net.INetd.PERMISSION_NONE; +import static android.net.INetd.PERMISSION_SYSTEM; +import static android.net.INetd.PERMISSION_UNINSTALLED; +import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS; import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.INVALID_UID; import static android.os.Process.SYSTEM_UID; +import static com.android.internal.util.ArrayUtils.convertToIntArray; + import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityManager; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; @@ -51,7 +60,6 @@ import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemConfig; @@ -65,7 +73,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; - /** * A utility class to inform Netd of UID permisisons. * Does a mass update at boot and then monitors for app install/remove. @@ -114,6 +121,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse public int getDeviceFirstSdkInt() { return Build.VERSION.FIRST_SDK_INT; } + + /** + * Check whether given uid has specific permission. + */ + public int uidPermission(@NonNull final String permission, final int uid) { + return ActivityManager.checkUidPermission(permission, uid); + } } public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { @@ -156,8 +170,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } mAllApps.add(UserHandle.getAppId(uid)); - boolean isNetwork = hasNetworkPermission(app); - boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); + final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); + final boolean hasRestrictedPermission = + hasRestrictedNetworkPermission(app.applicationInfo); if (isNetwork || hasRestrictedPermission) { Boolean permission = mApps.get(uid); @@ -169,8 +184,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } //TODO: unify the management of the permissions into one codepath. - int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions, - app.requestedPermissionsFlags); + final int otherNetdPerms = getNetdPermissionMask(uid); netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } @@ -190,9 +204,8 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse // Get the uids of native services that have UPDATE_DEVICE_STATS or INTERNET permission. if (perms != null) { netdPermission |= perms.contains(UPDATE_DEVICE_STATS) - ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0; - netdPermission |= perms.contains(INTERNET) - ? INetd.PERMISSION_INTERNET : 0; + ? PERMISSION_UPDATE_DEVICE_STATS : 0; + netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0; } netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); } @@ -207,48 +220,33 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } @VisibleForTesting - boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) { - if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) { - return false; - } - final int index = ArrayUtils.indexOf(app.requestedPermissions, permission); - if (index < 0 || index >= app.requestedPermissionsFlags.length) return false; - return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0; + boolean hasPermission(@NonNull final String permission, final int uid) { + return mDeps.uidPermission(permission, uid) == PackageManager.PERMISSION_GRANTED; } @VisibleForTesting - boolean hasNetworkPermission(@NonNull final PackageInfo app) { - return hasPermission(app, CHANGE_NETWORK_STATE); - } - - @VisibleForTesting - boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) { - // TODO : remove this check in the future(b/31479477). All apps should just + boolean hasRestrictedNetworkPermission(@Nullable final ApplicationInfo appInfo) { + if (appInfo == null) return false; + // TODO : remove this check in the future(b/162295056). All apps should just // request the appropriate permission for their use case since android Q. - if (app.applicationInfo != null) { - // Backward compatibility for b/114245686, on devices that launched before Q daemons - // and apps running as the system UID are exempted from this check. - if (app.applicationInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q) { - return true; - } - - if (app.applicationInfo.targetSdkVersion < VERSION_Q - && isVendorApp(app.applicationInfo)) { - return true; - } + if ((appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo)) + // Backward compatibility for b/114245686, on devices that launched before Q daemons + // and apps running as the system UID are exempted from this check. + || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q)) { + return true; } - return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) - || hasPermission(app, NETWORK_STACK) - || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); + return hasPermission(PERMISSION_MAINLINE_NETWORK_STACK, appInfo.uid) + || hasPermission(NETWORK_STACK, appInfo.uid) + || hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, appInfo.uid); } /** Returns whether the given uid has using background network permission. */ public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) { // Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background - // networks. mApps contains the result of checks for both hasNetworkPermission and - // hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of + // networks. mApps contains the result of checks for both CHANGE_NETWORK_STATE permission + // and hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of // permissions at least. return mApps.containsKey(uid); } @@ -273,11 +271,11 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } try { if (add) { - mNetd.networkSetPermissionForUser(INetd.PERMISSION_NETWORK, toIntArray(network)); - mNetd.networkSetPermissionForUser(INetd.PERMISSION_SYSTEM, toIntArray(system)); + mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, convertToIntArray(network)); + mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, convertToIntArray(system)); } else { - mNetd.networkClearPermissionForUser(toIntArray(network)); - mNetd.networkClearPermissionForUser(toIntArray(system)); + mNetd.networkClearPermissionForUser(convertToIntArray(network)); + mNetd.networkClearPermissionForUser(convertToIntArray(system)); } } catch (RemoteException e) { loge("Exception when updating permissions: " + e); @@ -323,14 +321,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } @VisibleForTesting - protected Boolean highestPermissionForUid(Boolean currentPermission, String name) { + protected Boolean highestPermissionForUid(Boolean currentPermission, String name, int uid) { if (currentPermission == SYSTEM) { return currentPermission; } try { final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS); - final boolean isNetwork = hasNetworkPermission(app); - final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); + final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); + final boolean hasRestrictedPermission = + hasRestrictedNetworkPermission(app.applicationInfo); if (isNetwork || hasRestrictedPermission) { currentPermission = hasRestrictedPermission; } @@ -342,23 +341,14 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } private int getPermissionForUid(final int uid) { - int permission = INetd.PERMISSION_NONE; // Check all the packages for this UID. The UID has the permission if any of the // packages in it has the permission. final String[] packages = mPackageManager.getPackagesForUid(uid); - if (packages != null && packages.length > 0) { - for (String name : packages) { - final PackageInfo app = getPackageInfo(name); - if (app != null && app.requestedPermissions != null) { - permission |= getNetdPermissionMask(app.requestedPermissions, - app.requestedPermissionsFlags); - } - } - } else { + if (packages == null || packages.length <= 0) { // The last package of this uid is removed from device. Clean the package up. - permission = INetd.PERMISSION_UNINSTALLED; + return PERMISSION_UNINSTALLED; } - return permission; + return getNetdPermissionMask(uid); } /** @@ -375,7 +365,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse // If multiple packages share a UID (cf: android:sharedUserId) and ask for different // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). - final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName); + final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName, uid); if (permission != mApps.get(uid)) { mApps.put(uid, permission); @@ -431,7 +421,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse String[] packages = mPackageManager.getPackagesForUid(uid); if (packages != null && packages.length > 0) { for (String name : packages) { - permission = highestPermissionForUid(permission, name); + permission = highestPermissionForUid(permission, name, uid); if (permission == SYSTEM) { // An app with this UID still has the SYSTEM permission. // Therefore, this UID must already have the SYSTEM permission. @@ -467,19 +457,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); } - private static int getNetdPermissionMask(String[] requestedPermissions, - int[] requestedPermissionsFlags) { - int permissions = 0; - if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions; - for (int i = 0; i < requestedPermissions.length; i++) { - if (requestedPermissions[i].equals(INTERNET) - && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { - permissions |= INetd.PERMISSION_INTERNET; - } - if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS) - && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) { - permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS; - } + private int getNetdPermissionMask(final int uid) { + int permissions = PERMISSION_NONE; + if (hasPermission(INTERNET, uid)) { + permissions |= PERMISSION_INTERNET; + } + if (hasPermission(UPDATE_DEVICE_STATS, uid)) { + permissions |= PERMISSION_UPDATE_DEVICE_STATS; } return permissions; } @@ -648,19 +632,19 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse for (int i = 0; i < netdPermissionsAppIds.size(); i++) { int permissions = netdPermissionsAppIds.valueAt(i); switch(permissions) { - case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS): + case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS): allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case INetd.PERMISSION_INTERNET: + case PERMISSION_INTERNET: internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case INetd.PERMISSION_UPDATE_DEVICE_STATS: + case PERMISSION_UPDATE_DEVICE_STATS: updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case INetd.PERMISSION_NONE: + case PERMISSION_NONE: noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case INetd.PERMISSION_UNINSTALLED: + case PERMISSION_UNINSTALLED: uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); default: Log.e(TAG, "unknown permission type: " + permissions + "for uid: " @@ -671,24 +655,24 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids() if (allPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids( - INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, - ArrayUtils.convertToIntArray(allPermissionAppIds)); + PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, + convertToIntArray(allPermissionAppIds)); } if (internetPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET, - ArrayUtils.convertToIntArray(internetPermissionAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET, + convertToIntArray(internetPermissionAppIds)); } if (updateStatsPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS, - ArrayUtils.convertToIntArray(updateStatsPermissionAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, + convertToIntArray(updateStatsPermissionAppIds)); } if (noPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE, - ArrayUtils.convertToIntArray(noPermissionAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_NONE, + convertToIntArray(noPermissionAppIds)); } if (uninstalledAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED, - ArrayUtils.convertToIntArray(uninstalledAppIds)); + mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED, + convertToIntArray(uninstalledAppIds)); } } catch (RemoteException e) { Log.e(TAG, "Pass appId list of special permission failed." + e); diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index 5a29c2c96ba7..eb0a867d8ec1 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -26,8 +26,6 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; -import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.os.Process.SYSTEM_UID; @@ -97,7 +95,6 @@ public class PermissionMonitorTest { private static final int SYSTEM_UID1 = 1000; private static final int SYSTEM_UID2 = 1008; private static final int VPN_UID = 10002; - private static final String REAL_SYSTEM_PACKAGE_NAME = "android"; private static final String MOCK_PACKAGE1 = "appName1"; private static final String MOCK_PACKAGE2 = "appName2"; private static final String SYSTEM_PACKAGE1 = "sysName1"; @@ -128,6 +125,7 @@ public class PermissionMonitorTest { new UserInfo(MOCK_USER1, "", 0), new UserInfo(MOCK_USER2, "", 0), })); + doReturn(PackageManager.PERMISSION_DENIED).when(mDeps).uidPermission(anyString(), anyInt()); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); @@ -140,35 +138,22 @@ public class PermissionMonitorTest { verify(mMockPmi).getPackageList(mPermissionMonitor); } + /** + * Remove all permissions from the uid then build new package info and setup permissions to uid + * for checking restricted network permission. + */ private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid, String... permissions) { - final PackageInfo packageInfo = - packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition); + final PackageInfo packageInfo = buildPackageInfo(partition, uid, MOCK_USER1); packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; - packageInfo.applicationInfo.uid = uid; - return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo); + removeAllPermissions(uid); + addPermissions(uid, permissions); + return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo.applicationInfo); } - private static PackageInfo systemPackageInfoWithPermissions(String... permissions) { - return packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); - } - - private static PackageInfo vendorPackageInfoWithPermissions(String... permissions) { - return packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_VENDOR); - } - - private static PackageInfo packageInfoWithPermissions(int permissionsFlags, - String[] permissions, String partition) { - int[] requestedPermissionsFlags = new int[permissions.length]; - for (int i = 0; i < permissions.length; i++) { - requestedPermissionsFlags[i] = permissionsFlags; - } + private static PackageInfo packageInfoWithPartition(String partition) { final PackageInfo packageInfo = new PackageInfo(); - packageInfo.requestedPermissions = permissions; packageInfo.applicationInfo = new ApplicationInfo(); - packageInfo.requestedPermissionsFlags = requestedPermissionsFlags; int privateFlags = 0; switch (partition) { case PARTITION_OEM: @@ -185,85 +170,65 @@ public class PermissionMonitorTest { return packageInfo; } - private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, int userId) { - final PackageInfo pkgInfo; - if (hasSystemPermission) { - pkgInfo = systemPackageInfoWithPermissions( - CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); - } else { - pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, ""); - } + private static PackageInfo buildPackageInfo(String partition, int uid, int userId) { + final PackageInfo pkgInfo = packageInfoWithPartition(partition); pkgInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(uid)); return pkgInfo; } + /** This will REMOVE all previously set permissions from given uid. */ + private void removeAllPermissions(int uid) { + doReturn(PackageManager.PERMISSION_DENIED).when(mDeps).uidPermission(anyString(), eq(uid)); + } + + /** Set up mocks so that given UID has the requested permissions. */ + private void addPermissions(int uid, String... permissions) { + for (String permission : permissions) { + doReturn(PackageManager.PERMISSION_GRANTED) + .when(mDeps).uidPermission(eq(permission), eq(uid)); + } + } + @Test public void testHasPermission() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE, NETWORK_STACK); - assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions( - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = packageInfoWithPermissions(REQUESTED_PERMISSION_REQUIRED, new String[] { - CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL, NETWORK_STACK }, - PARTITION_SYSTEM); - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); - assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - app.requestedPermissions = null; - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); - - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - app.requestedPermissionsFlags = null; - assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE)); + addPermissions(MOCK_UID1); + assertFalse(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1)); + + addPermissions(MOCK_UID1, CHANGE_NETWORK_STATE, NETWORK_STACK); + assertTrue(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID1)); + assertTrue(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID2)); + assertFalse(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID2)); + + addPermissions(MOCK_UID2, CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL); + assertFalse(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1)); + assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1)); + assertTrue(mPermissionMonitor.hasPermission( + CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID2)); + assertTrue(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID2)); } @Test public void testIsVendorApp() { - PackageInfo app = systemPackageInfoWithPermissions(); + PackageInfo app = packageInfoWithPartition(PARTITION_SYSTEM); assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, - new String[] {}, PARTITION_OEM); + app = packageInfoWithPartition(PARTITION_OEM); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, - new String[] {}, PARTITION_PRODUCT); + app = packageInfoWithPartition(PARTITION_PRODUCT); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = vendorPackageInfoWithPermissions(); + app = packageInfoWithPartition(PARTITION_VENDOR); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); } @Test - public void testHasNetworkPermission() { - PackageInfo app = systemPackageInfoWithPermissions(); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE); - assertTrue(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(NETWORK_STACK); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CONNECTIVITY_USE_RESTRICTED_NETWORKS); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - app = systemPackageInfoWithPermissions(CONNECTIVITY_INTERNAL); - assertFalse(mPermissionMonitor.hasNetworkPermission(app)); - } - - @Test public void testHasRestrictedNetworkPermission() { assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1)); assertFalse(hasRestrictedNetworkPermission( @@ -323,30 +288,27 @@ public class PermissionMonitorTest { private void assertBackgroundPermission(boolean hasPermission, String name, int uid, String... permissions) throws Exception { when(mPackageManager.getPackageInfo(eq(name), anyInt())) - .thenReturn(packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM)); + .thenReturn(buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1)); + addPermissions(uid, permissions); mPermissionMonitor.onPackageAdded(name, uid); assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid)); } @Test public void testHasUseBackgroundNetworksPermission() throws Exception { + doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt(); assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID)); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_NETWORK_STATE); - assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, NETWORK_STACK); + assertBackgroundPermission(false, "system1", SYSTEM_UID); + assertBackgroundPermission(false, "system2", SYSTEM_UID, CONNECTIVITY_INTERNAL); + assertBackgroundPermission(true, "system3", SYSTEM_UID, CHANGE_NETWORK_STATE); assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID1)); - assertBackgroundPermission(false, MOCK_PACKAGE1, MOCK_UID1); - assertBackgroundPermission(true, MOCK_PACKAGE1, MOCK_UID1, - CONNECTIVITY_USE_RESTRICTED_NETWORKS); + assertBackgroundPermission(false, "mock1", MOCK_UID1); + assertBackgroundPermission(true, "mock2", MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS); assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2)); - assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2); - assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2, - CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, NETWORK_STACK); + assertBackgroundPermission(false, "mock3", MOCK_UID2, CONNECTIVITY_INTERNAL); + assertBackgroundPermission(true, "mock4", MOCK_UID2, NETWORK_STACK); } private class NetdMonitor { @@ -416,13 +378,14 @@ public class PermissionMonitorTest { // MOCK_UID1: MOCK_PACKAGE1 only has network permission. // SYSTEM_UID: SYSTEM_PACKAGE1 has system permission. // SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission. - doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString()); + doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), + anyString(), anyInt()); doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE1)); + eq(SYSTEM_PACKAGE1), anyInt()); doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE2)); + eq(SYSTEM_PACKAGE2), anyInt()); doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(MOCK_PACKAGE1)); + eq(MOCK_PACKAGE1), anyInt()); // Add SYSTEM_PACKAGE2, expect only have network permission. mPermissionMonitor.onUserAdded(MOCK_USER1); @@ -473,13 +436,15 @@ public class PermissionMonitorTest { public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception { when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { - buildPackageInfo(/* SYSTEM */ true, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(/* SYSTEM */ false, MOCK_UID1, MOCK_USER1), - buildPackageInfo(/* SYSTEM */ false, MOCK_UID2, MOCK_USER1), - buildPackageInfo(/* SYSTEM */ false, VPN_UID, MOCK_USER1) + buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID2, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1) })); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn( - buildPackageInfo(false, MOCK_UID1, MOCK_USER1)); + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1)); + addPermissions(SYSTEM_UID, + CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); mPermissionMonitor.startMonitoring(); // Every app on user 0 except MOCK_UID2 are under VPN. final Set<UidRange> vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] { @@ -524,11 +489,11 @@ public class PermissionMonitorTest { public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception { when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { - buildPackageInfo(true, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(false, VPN_UID, MOCK_USER1) + buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1), + buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1) })); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn( - buildPackageInfo(false, MOCK_UID1, MOCK_USER1)); + buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1)); mPermissionMonitor.startMonitoring(); final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1)); @@ -633,10 +598,10 @@ public class PermissionMonitorTest { private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) throws Exception { - PackageInfo packageInfo = packageInfoWithPermissions( - REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); + final PackageInfo packageInfo = buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1); when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo); when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName}); + addPermissions(uid, permissions); return packageInfo; } @@ -663,14 +628,13 @@ public class PermissionMonitorTest { public void testPackageInstallSharedUid() throws Exception { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - PackageInfo packageInfo1 = addPackage(MOCK_PACKAGE1, MOCK_UID1, - new String[] {INTERNET, UPDATE_DEVICE_STATS}); + addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Install another package with the same uid and no permissions should not cause the UID to // lose permissions. - PackageInfo packageInfo2 = systemPackageInfoWithPermissions(); + final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)) .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); @@ -701,6 +665,7 @@ public class PermissionMonitorTest { | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); + removeAllPermissions(MOCK_UID1); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); @@ -728,10 +693,12 @@ public class PermissionMonitorTest { | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Mock another package with the same uid but different permissions. - PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET); + final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{ MOCK_PACKAGE2}); + removeAllPermissions(MOCK_UID1); + addPermissions(MOCK_UID1, INTERNET); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); @@ -743,9 +710,6 @@ public class PermissionMonitorTest { // necessary permission. final Context realContext = InstrumentationRegistry.getContext(); final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService); - final PackageManager manager = realContext.getPackageManager(); - final PackageInfo systemInfo = manager.getPackageInfo(REAL_SYSTEM_PACKAGE_NAME, - GET_PERMISSIONS | MATCH_ANY_USER); - assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); + assertTrue(monitor.hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, SYSTEM_UID)); } } |