From 9c60af3743c81e827976b1a31255d12549a6f05a Mon Sep 17 00:00:00 2001 From: Paul Hu Date: Thu, 20 Aug 2020 03:13:04 +0000 Subject: [PATCH] Revert "[RFPM03] Check permission by uid." This reverts commit 8adb39a68880c3f63d277d02f67412a4870555ca. Reason for revert: Regression in SW. Bug:162499840 Change-Id: Ic93e762e41a728f66e200e5bc8e40ebe4c7b44f7 --- .../connectivity/PermissionMonitor.java | 162 +++++++------- .../connectivity/PermissionMonitorTest.java | 204 ++++++++++-------- 2 files changed, 209 insertions(+), 157 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index f8774b1b00..a75a80a606 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -21,23 +21,14 @@ 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; @@ -60,6 +51,7 @@ 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; @@ -73,6 +65,7 @@ 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. @@ -121,13 +114,6 @@ 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) { @@ -170,9 +156,8 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } mAllApps.add(UserHandle.getAppId(uid)); - final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); - final boolean hasRestrictedPermission = - hasRestrictedNetworkPermission(app.applicationInfo); + boolean isNetwork = hasNetworkPermission(app); + boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); if (isNetwork || hasRestrictedPermission) { Boolean permission = mApps.get(uid); @@ -184,7 +169,8 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } //TODO: unify the management of the permissions into one codepath. - final int otherNetdPerms = getNetdPermissionMask(uid); + int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions, + app.requestedPermissionsFlags); netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } @@ -204,8 +190,9 @@ 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) - ? PERMISSION_UPDATE_DEVICE_STATS : 0; - netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0; + ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0; + netdPermission |= perms.contains(INTERNET) + ? INetd.PERMISSION_INTERNET : 0; } netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); } @@ -220,33 +207,48 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } @VisibleForTesting - boolean hasPermission(@NonNull final String permission, final int uid) { - return mDeps.uidPermission(permission, uid) == PackageManager.PERMISSION_GRANTED; + 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; } @VisibleForTesting - boolean hasRestrictedNetworkPermission(@Nullable final ApplicationInfo appInfo) { - if (appInfo == null) return false; - // TODO : remove this check in the future(b/162295056). All apps should just + 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 // request the appropriate permission for their use case since android Q. - 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; + 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; + } } - return hasPermission(PERMISSION_MAINLINE_NETWORK_STACK, appInfo.uid) - || hasPermission(NETWORK_STACK, appInfo.uid) - || hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, appInfo.uid); + return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) + || hasPermission(app, NETWORK_STACK) + || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); } /** 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 CHANGE_NETWORK_STATE permission - // and hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of + // 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 // permissions at least. return mApps.containsKey(uid); } @@ -271,11 +273,11 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } try { if (add) { - mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, convertToIntArray(network)); - mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, convertToIntArray(system)); + mNetd.networkSetPermissionForUser(INetd.PERMISSION_NETWORK, toIntArray(network)); + mNetd.networkSetPermissionForUser(INetd.PERMISSION_SYSTEM, toIntArray(system)); } else { - mNetd.networkClearPermissionForUser(convertToIntArray(network)); - mNetd.networkClearPermissionForUser(convertToIntArray(system)); + mNetd.networkClearPermissionForUser(toIntArray(network)); + mNetd.networkClearPermissionForUser(toIntArray(system)); } } catch (RemoteException e) { loge("Exception when updating permissions: " + e); @@ -321,15 +323,14 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } @VisibleForTesting - protected Boolean highestPermissionForUid(Boolean currentPermission, String name, int uid) { + protected Boolean highestPermissionForUid(Boolean currentPermission, String name) { if (currentPermission == SYSTEM) { return currentPermission; } try { final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS); - final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); - final boolean hasRestrictedPermission = - hasRestrictedNetworkPermission(app.applicationInfo); + final boolean isNetwork = hasNetworkPermission(app); + final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app); if (isNetwork || hasRestrictedPermission) { currentPermission = hasRestrictedPermission; } @@ -341,14 +342,23 @@ 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) { + 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 { // The last package of this uid is removed from device. Clean the package up. - return PERMISSION_UNINSTALLED; + permission = INetd.PERMISSION_UNINSTALLED; } - return getNetdPermissionMask(uid); + return permission; } /** @@ -365,7 +375,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, uid); + final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName); if (permission != mApps.get(uid)) { mApps.put(uid, permission); @@ -421,7 +431,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, uid); + permission = highestPermissionForUid(permission, name); if (permission == SYSTEM) { // An app with this UID still has the SYSTEM permission. // Therefore, this UID must already have the SYSTEM permission. @@ -457,13 +467,19 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); } - 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; + 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; + } } return permissions; } @@ -632,19 +648,19 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse for (int i = 0; i < netdPermissionsAppIds.size(); i++) { int permissions = netdPermissionsAppIds.valueAt(i); switch(permissions) { - case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS): + case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS): allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case PERMISSION_INTERNET: + case INetd.PERMISSION_INTERNET: internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case PERMISSION_UPDATE_DEVICE_STATS: + case INetd.PERMISSION_UPDATE_DEVICE_STATS: updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case PERMISSION_NONE: + case INetd.PERMISSION_NONE: noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; - case PERMISSION_UNINSTALLED: + case INetd.PERMISSION_UNINSTALLED: uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); default: Log.e(TAG, "unknown permission type: " + permissions + "for uid: " @@ -655,24 +671,24 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids() if (allPermissionAppIds.size() != 0) { mNetd.trafficSetNetPermForUids( - PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, - convertToIntArray(allPermissionAppIds)); + INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, + ArrayUtils.convertToIntArray(allPermissionAppIds)); } if (internetPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET, - convertToIntArray(internetPermissionAppIds)); + mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET, + ArrayUtils.convertToIntArray(internetPermissionAppIds)); } if (updateStatsPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, - convertToIntArray(updateStatsPermissionAppIds)); + mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS, + ArrayUtils.convertToIntArray(updateStatsPermissionAppIds)); } if (noPermissionAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(PERMISSION_NONE, - convertToIntArray(noPermissionAppIds)); + mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE, + ArrayUtils.convertToIntArray(noPermissionAppIds)); } if (uninstalledAppIds.size() != 0) { - mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED, - convertToIntArray(uninstalledAppIds)); + mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED, + ArrayUtils.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 6633c9d69c..fdc6084884 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -26,6 +26,8 @@ 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; @@ -95,6 +97,7 @@ 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"; @@ -125,7 +128,6 @@ 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)); @@ -138,22 +140,35 @@ 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 = buildPackageInfo(partition, uid, MOCK_USER1); + final PackageInfo packageInfo = + packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition); packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion; - removeAllPermissions(uid); - addPermissions(uid, permissions); - return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo.applicationInfo); + packageInfo.applicationInfo.uid = uid; + return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo); } - private static PackageInfo packageInfoWithPartition(String partition) { + 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; + } final PackageInfo packageInfo = new PackageInfo(); + packageInfo.requestedPermissions = permissions; packageInfo.applicationInfo = new ApplicationInfo(); + packageInfo.requestedPermissionsFlags = requestedPermissionsFlags; int privateFlags = 0; switch (partition) { case PARTITION_OEM: @@ -170,64 +185,84 @@ public class PermissionMonitorTest { return packageInfo; } - private static PackageInfo buildPackageInfo(String partition, int uid, int userId) { - final PackageInfo pkgInfo = packageInfoWithPartition(partition); + 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[] {}, ""); + } 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() { - 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)); + 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)); - 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)); + 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)); - 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)); + 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)); } @Test public void testIsVendorApp() { - PackageInfo app = packageInfoWithPartition(PARTITION_SYSTEM); + PackageInfo app = systemPackageInfoWithPermissions(); assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPartition(PARTITION_OEM); + app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, + new String[] {}, PARTITION_OEM); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPartition(PARTITION_PRODUCT); + app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, + new String[] {}, PARTITION_PRODUCT); assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo)); - app = packageInfoWithPartition(PARTITION_VENDOR); + app = vendorPackageInfoWithPermissions(); 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)); @@ -288,27 +323,30 @@ public class PermissionMonitorTest { private void assertBackgroundPermission(boolean hasPermission, String name, int uid, String... permissions) throws Exception { when(mPackageManager.getPackageInfo(eq(name), anyInt())) - .thenReturn(buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1)); - addPermissions(uid, permissions); + .thenReturn(packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM)); 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, "system1", SYSTEM_UID); - assertBackgroundPermission(false, "system2", SYSTEM_UID, CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, "system3", SYSTEM_UID, CHANGE_NETWORK_STATE); + 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); assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID1)); - assertBackgroundPermission(false, "mock1", MOCK_UID1); - assertBackgroundPermission(true, "mock2", MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS); + assertBackgroundPermission(false, MOCK_PACKAGE1, MOCK_UID1); + assertBackgroundPermission(true, MOCK_PACKAGE1, MOCK_UID1, + CONNECTIVITY_USE_RESTRICTED_NETWORKS); assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2)); - assertBackgroundPermission(false, "mock3", MOCK_UID2, CONNECTIVITY_INTERNAL); - assertBackgroundPermission(true, "mock4", MOCK_UID2, NETWORK_STACK); + assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2); + assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2, + CONNECTIVITY_INTERNAL); + assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, NETWORK_STACK); } private class NetdMonitor { @@ -378,14 +416,13 @@ 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(), anyInt()); + doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString()); doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE1), anyInt()); + eq(SYSTEM_PACKAGE1)); doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(SYSTEM_PACKAGE2), anyInt()); + eq(SYSTEM_PACKAGE2)); doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(), - eq(MOCK_PACKAGE1), anyInt()); + eq(MOCK_PACKAGE1)); // Add SYSTEM_PACKAGE2, expect only have network permission. mPermissionMonitor.onUserAdded(MOCK_USER1); @@ -436,15 +473,13 @@ public class PermissionMonitorTest { public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception { when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { - 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) + 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) })); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn( - buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1)); - addPermissions(SYSTEM_UID, - CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS); + buildPackageInfo(false, MOCK_UID1, MOCK_USER1)); mPermissionMonitor.startMonitoring(); // Every app on user 0 except MOCK_UID2 are under VPN. final Set vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] { @@ -489,11 +524,11 @@ public class PermissionMonitorTest { public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception { when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn( Arrays.asList(new PackageInfo[] { - buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1), - buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1) + buildPackageInfo(true, SYSTEM_UID1, MOCK_USER1), + buildPackageInfo(false, VPN_UID, MOCK_USER1) })); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn( - buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1)); + buildPackageInfo(false, MOCK_UID1, MOCK_USER1)); mPermissionMonitor.startMonitoring(); final Set vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1)); @@ -598,10 +633,10 @@ public class PermissionMonitorTest { private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) throws Exception { - final PackageInfo packageInfo = buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1); + PackageInfo packageInfo = packageInfoWithPermissions( + REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM); when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo); when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName}); - addPermissions(uid, permissions); return packageInfo; } @@ -628,13 +663,14 @@ public class PermissionMonitorTest { public void testPackageInstallSharedUid() throws Exception { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); - addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); + PackageInfo packageInfo1 = 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. - final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1); + PackageInfo packageInfo2 = systemPackageInfoWithPermissions(); when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2); when(mPackageManager.getPackagesForUid(MOCK_UID1)) .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); @@ -665,7 +701,6 @@ 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}); @@ -693,12 +728,10 @@ public class PermissionMonitorTest { | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Mock another package with the same uid but different permissions. - final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1); + PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET); 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}); @@ -710,6 +743,9 @@ public class PermissionMonitorTest { // necessary permission. final Context realContext = InstrumentationRegistry.getContext(); final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService); - assertTrue(monitor.hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, SYSTEM_UID)); + 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)); } }