Loading services/core/java/com/android/server/connectivity/PermissionMonitor.java +38 −73 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.system.OsConstants; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -129,42 +130,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } } /** * A data class to store each uid Netd permission information. Netd permissions includes * PERMISSION_NETWORK, PERMISSION_SYSTEM, PERMISSION_INTERNET, PERMISSION_UPDATE_DEVICE_STATS * and OR'd with the others. Default permission is PERMISSION_NONE and PERMISSION_UNINSTALLED * will be set if all packages are removed from the uid. */ public static class UidNetdPermissionInfo { private final int mNetdPermissions; UidNetdPermissionInfo() { this(PERMISSION_NONE); } UidNetdPermissionInfo(int permissions) { mNetdPermissions = permissions; } /** Plus given permissions and return new UidNetdPermissionInfo instance. */ public UidNetdPermissionInfo plusNetdPermissions(int permissions) { return new UidNetdPermissionInfo(mNetdPermissions | permissions); } /** Return whether package is uninstalled. */ public boolean isPackageUninstalled() { return mNetdPermissions == PERMISSION_UNINSTALLED; } /** Check that uid has given permissions */ public boolean hasNetdPermissions(final int permissions) { if (isPackageUninstalled()) return false; if (permissions == PERMISSION_NONE) return true; return (mNetdPermissions & permissions) == permissions; } } public PermissionMonitor(Context context, INetd netd) { public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { this(context, netd, new Dependencies()); } Loading Loading @@ -195,7 +161,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return; } final SparseArray<UidNetdPermissionInfo> netdPermsUids = new SparseArray<>(); SparseIntArray netdPermsUids = new SparseIntArray(); for (PackageInfo app : apps) { int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID; Loading @@ -217,13 +183,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } } // Skip already checked uid. if (netdPermsUids.get(uid) != null) continue; //TODO: unify the management of the permissions into one codepath. final UidNetdPermissionInfo permInfo = new UidNetdPermissionInfo(getNetdPermissionMask(uid)); netdPermsUids.put(uid, permInfo); final int otherNetdPerms = getNetdPermissionMask(uid); netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users Loading @@ -245,10 +207,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse ? PERMISSION_UPDATE_DEVICE_STATS : 0; netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0; } final UidNetdPermissionInfo permInfo = netdPermsUids.get(uid); netdPermsUids.put(uid, permInfo != null ? permInfo.plusNetdPermissions(netdPermission) : new UidNetdPermissionInfo(netdPermission)); netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); } log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); update(mUsers, mApps, true); Loading Loading @@ -382,15 +341,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return currentPermission; } private UidNetdPermissionInfo getPermissionForUid(final int uid) { private int getPermissionForUid(final int uid) { // 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) { // The last package of this uid is removed from device. Clean the package up. return new UidNetdPermissionInfo(PERMISSION_UNINSTALLED); return PERMISSION_UNINSTALLED; } return new UidNetdPermissionInfo(getNetdPermissionMask(uid)); return getNetdPermissionMask(uid); } /** Loading Loading @@ -640,28 +599,28 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * permission information to netd. * * @param uid the app uid of the package installed * @param permissionInfo the permission info of given uid. * @param permissions the permissions the app requested and netd cares about. * * @hide */ @VisibleForTesting void sendPackagePermissionsForUid(int uid, UidNetdPermissionInfo permissionInfo) { final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>(); uidsPermInfo.put(uid, permissionInfo); sendPackagePermissionsToNetd(uidsPermInfo); void sendPackagePermissionsForUid(int uid, int permissions) { SparseIntArray netdPermissionsAppIds = new SparseIntArray(); netdPermissionsAppIds.put(uid, permissions); sendPackagePermissionsToNetd(netdPermissionsAppIds); } /** * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET * and/or UPDATE_DEVICE_STATS permission of the uids in array. * * @param uidsPermInfo permission info array generated from each uid. If the uid permission is * PERMISSION_NONE or PERMISSION_UNINSTALLED, revoke all permissions of that * uid. * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the * permission is 0, revoke all permissions of that uid. * * @hide */ @VisibleForTesting void sendPackagePermissionsToNetd(final SparseArray<UidNetdPermissionInfo> uidsPermInfo) { void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) { if (mNetd == null) { Log.e(TAG, "Failed to get the netd service"); return; Loading @@ -671,20 +630,26 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>(); ArrayList<Integer> noPermissionAppIds = new ArrayList<>(); ArrayList<Integer> uninstalledAppIds = new ArrayList<>(); for (int i = 0; i < uidsPermInfo.size(); i++) { final int uid = uidsPermInfo.keyAt(i); final UidNetdPermissionInfo permInfo = uidsPermInfo.valueAt(i); if (permInfo.hasNetdPermissions( PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)) { allPermissionAppIds.add(uid); } else if (permInfo.hasNetdPermissions(PERMISSION_INTERNET)) { internetPermissionAppIds.add(uid); } else if (permInfo.hasNetdPermissions(PERMISSION_UPDATE_DEVICE_STATS)) { updateStatsPermissionAppIds.add(uid); } else if (permInfo.isPackageUninstalled()) { uninstalledAppIds.add(uid); } else { noPermissionAppIds.add(uid); for (int i = 0; i < netdPermissionsAppIds.size(); i++) { int permissions = netdPermissionsAppIds.valueAt(i); switch(permissions) { case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS): allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_INTERNET: internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_UPDATE_DEVICE_STATS: updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_NONE: noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_UNINSTALLED: uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); default: Log.e(TAG, "unknown permission type: " + permissions + "for uid: " + netdPermissionsAppIds.keyAt(i)); } } try { Loading tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +42 −49 Original line number Diff line number Diff line Loading @@ -28,17 +28,11 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR; 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_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.SYSTEM_UID; import static com.android.server.connectivity.PermissionMonitor.NETWORK; import static com.android.server.connectivity.PermissionMonitor.SYSTEM; import static com.android.server.connectivity.PermissionMonitor.UidNetdPermissionInfo; import static junit.framework.Assert.fail; Loading Loading @@ -70,7 +64,7 @@ import android.net.UidRange; import android.os.Build; import android.os.UserHandle; import android.os.UserManager; import android.util.SparseArray; import android.util.SparseIntArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; Loading Loading @@ -318,7 +312,7 @@ public class PermissionMonitorTest { // Add hook to verify and track result of setPermission. doAnswer((InvocationOnMock invocation) -> { final Object[] args = invocation.getArguments(); final Boolean isSystem = args[0].equals(PERMISSION_SYSTEM); final Boolean isSystem = args[0].equals(INetd.PERMISSION_SYSTEM); for (final int uid : (int[]) args[1]) { // TODO: Currently, permission monitor will send duplicate commands for each uid // corresponding to each user. Need to fix that and uncomment below test. Loading Loading @@ -561,40 +555,39 @@ public class PermissionMonitorTest { // SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission. // SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission. final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>(); uidsPermInfo.put(MOCK_UID1, new UidNetdPermissionInfo(PERMISSION_INTERNET)); uidsPermInfo.put(MOCK_UID2, new UidNetdPermissionInfo(PERMISSION_NONE)); uidsPermInfo.put(SYSTEM_UID1, new UidNetdPermissionInfo( PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)); uidsPermInfo.put(SYSTEM_UID2, new UidNetdPermissionInfo(PERMISSION_UPDATE_DEVICE_STATS)); SparseIntArray netdPermissionsAppIds = new SparseIntArray(); netdPermissionsAppIds.put(MOCK_UID1, INetd.PERMISSION_INTERNET); netdPermissionsAppIds.put(MOCK_UID2, INetd.PERMISSION_NONE); netdPermissionsAppIds.put(SYSTEM_UID1, INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS); netdPermissionsAppIds.put(SYSTEM_UID2, INetd.PERMISSION_UPDATE_DEVICE_STATS); // Send the permission information to netd, expect permission updated. mPermissionMonitor.sendPackagePermissionsToNetd(uidsPermInfo); mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID2}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); mNetdServiceMonitor.expectPermission(PERMISSION_UPDATE_DEVICE_STATS, mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID2}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID2}); // Update permission of MOCK_UID1, expect new permission show up. mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, new UidNetdPermissionInfo( PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Change permissions of SYSTEM_UID2, expect new permission show up and old permission // revoked. mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, new UidNetdPermissionInfo( PERMISSION_INTERNET)); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, INetd.PERMISSION_INTERNET); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); // Revoke permission from SYSTEM_UID1, expect no permission stored. mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, new UidNetdPermissionInfo( PERMISSION_NONE)); mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{SYSTEM_UID1}); mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, INetd.PERMISSION_NONE); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{SYSTEM_UID1}); } private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) Loading @@ -618,11 +611,11 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID2}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID2}); } @Test Loading @@ -630,8 +623,8 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); 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. Loading @@ -640,8 +633,8 @@ public class PermissionMonitorTest { when(mPackageManager.getPackagesForUid(MOCK_UID1)) .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); } @Test Loading @@ -649,12 +642,12 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); mNetdServiceMonitor.expectPermission(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); } @Test Loading @@ -662,16 +655,16 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | 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(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test Loading @@ -679,10 +672,10 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {}); mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test Loading @@ -690,8 +683,8 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | 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); Loading @@ -702,7 +695,7 @@ public class PermissionMonitorTest { addPermissions(MOCK_UID1, INTERNET); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test Loading Loading
services/core/java/com/android/server/connectivity/PermissionMonitor.java +38 −73 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.system.OsConstants; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -129,42 +130,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } } /** * A data class to store each uid Netd permission information. Netd permissions includes * PERMISSION_NETWORK, PERMISSION_SYSTEM, PERMISSION_INTERNET, PERMISSION_UPDATE_DEVICE_STATS * and OR'd with the others. Default permission is PERMISSION_NONE and PERMISSION_UNINSTALLED * will be set if all packages are removed from the uid. */ public static class UidNetdPermissionInfo { private final int mNetdPermissions; UidNetdPermissionInfo() { this(PERMISSION_NONE); } UidNetdPermissionInfo(int permissions) { mNetdPermissions = permissions; } /** Plus given permissions and return new UidNetdPermissionInfo instance. */ public UidNetdPermissionInfo plusNetdPermissions(int permissions) { return new UidNetdPermissionInfo(mNetdPermissions | permissions); } /** Return whether package is uninstalled. */ public boolean isPackageUninstalled() { return mNetdPermissions == PERMISSION_UNINSTALLED; } /** Check that uid has given permissions */ public boolean hasNetdPermissions(final int permissions) { if (isPackageUninstalled()) return false; if (permissions == PERMISSION_NONE) return true; return (mNetdPermissions & permissions) == permissions; } } public PermissionMonitor(Context context, INetd netd) { public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { this(context, netd, new Dependencies()); } Loading Loading @@ -195,7 +161,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return; } final SparseArray<UidNetdPermissionInfo> netdPermsUids = new SparseArray<>(); SparseIntArray netdPermsUids = new SparseIntArray(); for (PackageInfo app : apps) { int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID; Loading @@ -217,13 +183,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse } } // Skip already checked uid. if (netdPermsUids.get(uid) != null) continue; //TODO: unify the management of the permissions into one codepath. final UidNetdPermissionInfo permInfo = new UidNetdPermissionInfo(getNetdPermissionMask(uid)); netdPermsUids.put(uid, permInfo); final int otherNetdPerms = getNetdPermissionMask(uid); netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users Loading @@ -245,10 +207,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse ? PERMISSION_UPDATE_DEVICE_STATS : 0; netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0; } final UidNetdPermissionInfo permInfo = netdPermsUids.get(uid); netdPermsUids.put(uid, permInfo != null ? permInfo.plusNetdPermissions(netdPermission) : new UidNetdPermissionInfo(netdPermission)); netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); } log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); update(mUsers, mApps, true); Loading Loading @@ -382,15 +341,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse return currentPermission; } private UidNetdPermissionInfo getPermissionForUid(final int uid) { private int getPermissionForUid(final int uid) { // 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) { // The last package of this uid is removed from device. Clean the package up. return new UidNetdPermissionInfo(PERMISSION_UNINSTALLED); return PERMISSION_UNINSTALLED; } return new UidNetdPermissionInfo(getNetdPermissionMask(uid)); return getNetdPermissionMask(uid); } /** Loading Loading @@ -640,28 +599,28 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse * permission information to netd. * * @param uid the app uid of the package installed * @param permissionInfo the permission info of given uid. * @param permissions the permissions the app requested and netd cares about. * * @hide */ @VisibleForTesting void sendPackagePermissionsForUid(int uid, UidNetdPermissionInfo permissionInfo) { final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>(); uidsPermInfo.put(uid, permissionInfo); sendPackagePermissionsToNetd(uidsPermInfo); void sendPackagePermissionsForUid(int uid, int permissions) { SparseIntArray netdPermissionsAppIds = new SparseIntArray(); netdPermissionsAppIds.put(uid, permissions); sendPackagePermissionsToNetd(netdPermissionsAppIds); } /** * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET * and/or UPDATE_DEVICE_STATS permission of the uids in array. * * @param uidsPermInfo permission info array generated from each uid. If the uid permission is * PERMISSION_NONE or PERMISSION_UNINSTALLED, revoke all permissions of that * uid. * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the * permission is 0, revoke all permissions of that uid. * * @hide */ @VisibleForTesting void sendPackagePermissionsToNetd(final SparseArray<UidNetdPermissionInfo> uidsPermInfo) { void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) { if (mNetd == null) { Log.e(TAG, "Failed to get the netd service"); return; Loading @@ -671,20 +630,26 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>(); ArrayList<Integer> noPermissionAppIds = new ArrayList<>(); ArrayList<Integer> uninstalledAppIds = new ArrayList<>(); for (int i = 0; i < uidsPermInfo.size(); i++) { final int uid = uidsPermInfo.keyAt(i); final UidNetdPermissionInfo permInfo = uidsPermInfo.valueAt(i); if (permInfo.hasNetdPermissions( PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)) { allPermissionAppIds.add(uid); } else if (permInfo.hasNetdPermissions(PERMISSION_INTERNET)) { internetPermissionAppIds.add(uid); } else if (permInfo.hasNetdPermissions(PERMISSION_UPDATE_DEVICE_STATS)) { updateStatsPermissionAppIds.add(uid); } else if (permInfo.isPackageUninstalled()) { uninstalledAppIds.add(uid); } else { noPermissionAppIds.add(uid); for (int i = 0; i < netdPermissionsAppIds.size(); i++) { int permissions = netdPermissionsAppIds.valueAt(i); switch(permissions) { case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS): allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_INTERNET: internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_UPDATE_DEVICE_STATS: updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_NONE: noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); break; case PERMISSION_UNINSTALLED: uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); default: Log.e(TAG, "unknown permission type: " + permissions + "for uid: " + netdPermissionsAppIds.keyAt(i)); } } try { Loading
tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +42 −49 Original line number Diff line number Diff line Loading @@ -28,17 +28,11 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR; 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_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.SYSTEM_UID; import static com.android.server.connectivity.PermissionMonitor.NETWORK; import static com.android.server.connectivity.PermissionMonitor.SYSTEM; import static com.android.server.connectivity.PermissionMonitor.UidNetdPermissionInfo; import static junit.framework.Assert.fail; Loading Loading @@ -70,7 +64,7 @@ import android.net.UidRange; import android.os.Build; import android.os.UserHandle; import android.os.UserManager; import android.util.SparseArray; import android.util.SparseIntArray; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; Loading Loading @@ -318,7 +312,7 @@ public class PermissionMonitorTest { // Add hook to verify and track result of setPermission. doAnswer((InvocationOnMock invocation) -> { final Object[] args = invocation.getArguments(); final Boolean isSystem = args[0].equals(PERMISSION_SYSTEM); final Boolean isSystem = args[0].equals(INetd.PERMISSION_SYSTEM); for (final int uid : (int[]) args[1]) { // TODO: Currently, permission monitor will send duplicate commands for each uid // corresponding to each user. Need to fix that and uncomment below test. Loading Loading @@ -561,40 +555,39 @@ public class PermissionMonitorTest { // SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission. // SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission. final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>(); uidsPermInfo.put(MOCK_UID1, new UidNetdPermissionInfo(PERMISSION_INTERNET)); uidsPermInfo.put(MOCK_UID2, new UidNetdPermissionInfo(PERMISSION_NONE)); uidsPermInfo.put(SYSTEM_UID1, new UidNetdPermissionInfo( PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)); uidsPermInfo.put(SYSTEM_UID2, new UidNetdPermissionInfo(PERMISSION_UPDATE_DEVICE_STATS)); SparseIntArray netdPermissionsAppIds = new SparseIntArray(); netdPermissionsAppIds.put(MOCK_UID1, INetd.PERMISSION_INTERNET); netdPermissionsAppIds.put(MOCK_UID2, INetd.PERMISSION_NONE); netdPermissionsAppIds.put(SYSTEM_UID1, INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS); netdPermissionsAppIds.put(SYSTEM_UID2, INetd.PERMISSION_UPDATE_DEVICE_STATS); // Send the permission information to netd, expect permission updated. mPermissionMonitor.sendPackagePermissionsToNetd(uidsPermInfo); mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID2}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); mNetdServiceMonitor.expectPermission(PERMISSION_UPDATE_DEVICE_STATS, mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID2}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID2}); // Update permission of MOCK_UID1, expect new permission show up. mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, new UidNetdPermissionInfo( PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); // Change permissions of SYSTEM_UID2, expect new permission show up and old permission // revoked. mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, new UidNetdPermissionInfo( PERMISSION_INTERNET)); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, INetd.PERMISSION_INTERNET); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{SYSTEM_UID2}); // Revoke permission from SYSTEM_UID1, expect no permission stored. mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, new UidNetdPermissionInfo( PERMISSION_NONE)); mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{SYSTEM_UID1}); mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, INetd.PERMISSION_NONE); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{SYSTEM_UID1}); } private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions) Loading @@ -618,11 +611,11 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID2}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID2}); } @Test Loading @@ -630,8 +623,8 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); 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. Loading @@ -640,8 +633,8 @@ public class PermissionMonitorTest { when(mPackageManager.getPackagesForUid(MOCK_UID1)) .thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2}); mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); } @Test Loading @@ -649,12 +642,12 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{}); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); mNetdServiceMonitor.expectPermission(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); } @Test Loading @@ -662,16 +655,16 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | 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(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test Loading @@ -679,10 +672,10 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {}); mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID1}); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test Loading @@ -690,8 +683,8 @@ public class PermissionMonitorTest { final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService); addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS}); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET | 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); Loading @@ -702,7 +695,7 @@ public class PermissionMonitorTest { addPermissions(MOCK_UID1, INTERNET); mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1); mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1}); mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1}); } @Test Loading