Loading services/core/java/com/android/server/connectivity/Vpn.java +0 −28 Original line number Diff line number Diff line Loading @@ -1850,34 +1850,6 @@ public class Vpn { } } /** * @param uid The target uid. * * @return {@code true} if {@code uid} is included in one of the mBlockedUidsAsToldToNetd * ranges and the VPN is not connected, or if the VPN is connected but does not apply to * the {@code uid}. * * @apiNote This method don't check VPN lockdown status. * @see #mBlockedUidsAsToldToConnectivity */ public synchronized boolean isBlockingUid(int uid) { if (mNetworkInfo.isConnected()) { return !appliesToUid(uid); } else { return containsUid(mBlockedUidsAsToldToConnectivity, uid); } } private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) { if (ranges == null) return false; for (UidRangeParcel range : ranges) { if (range.start <= uid && uid <= range.stop) { return true; } } return false; } private void updateAlwaysOnNotification(DetailedState networkState) { final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); Loading tests/net/java/com/android/server/ConnectivityServiceTest.java +54 −0 Original line number Diff line number Diff line Loading @@ -1199,6 +1199,8 @@ public class ConnectivityServiceTest { updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect"); } mAgentRegistered = false; setUids(null); mInterface = null; } @Override Loading Loading @@ -6180,11 +6182,15 @@ public class ConnectivityServiceTest { // Create a fake restricted profile whose parent is our user ID. final int userId = UserHandle.getUserId(uid); when(mUserManager.canHaveRestrictedProfile(userId)).thenReturn(true); final int restrictedUserId = userId + 1; final UserInfo info = new UserInfo(restrictedUserId, "user", UserInfo.FLAG_RESTRICTED); info.restrictedProfileParentId = userId; assertTrue(info.isRestricted()); when(mUserManager.getUserInfo(restrictedUserId)).thenReturn(info); when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, restrictedUserId)) .thenReturn(UserHandle.getUid(restrictedUserId, VPN_UID)); final Intent addedIntent = new Intent(ACTION_USER_ADDED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId); Loading Loading @@ -6224,6 +6230,54 @@ public class ConnectivityServiceTest { && caps.getUids().contains(new UidRange(uid, uid)) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); // Test lockdown with restricted profiles. mServiceContext.setPermission( Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED); mServiceContext.setPermission( Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); mServiceContext.setPermission( Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); // Connect wifi and check that UIDs in the main and restricted profiles have network access. mMockVpn.disconnect(); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true /* validated */); final int restrictedUid = UserHandle.getUid(restrictedUserId, 42 /* appId */); assertNotNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); // Enable always-on VPN lockdown. The main user loses network access because no VPN is up. final ArrayList<String> allowList = new ArrayList<>(); mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); // Start the restricted profile, and check that the UID within it loses network access. when(mUserManager.getAliveUsers()).thenReturn( Arrays.asList(new UserInfo[] { new UserInfo(userId, "", 0), info })); // TODO: check that VPN app within restricted profile still has access, etc. handler.post(() -> mServiceContext.sendBroadcast(addedIntent)); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); assertNull(mCm.getActiveNetworkForUid(restrictedUid)); // Stop the restricted profile, and check that the UID within it has network access again. when(mUserManager.getAliveUsers()).thenReturn( Arrays.asList(new UserInfo[] { new UserInfo(userId, "", 0), })); handler.post(() -> mServiceContext.sendBroadcast(removedIntent)); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); waitForIdle(); } @Test Loading tests/net/java/com/android/server/connectivity/VpnTest.java +0 −77 Original line number Diff line number Diff line Loading @@ -339,14 +339,8 @@ public class VpnTest { final Vpn vpn = createVpn(primaryUser.id); final UidRange user = PRI_USER_RANGE; // Default state. assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore)); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore)); Loading @@ -355,10 +349,6 @@ public class VpnTest { new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { Loading @@ -369,9 +359,6 @@ public class VpnTest { new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[3]); } @Test Loading @@ -386,8 +373,6 @@ public class VpnTest { new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); Loading @@ -398,8 +383,6 @@ public class VpnTest { new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]); // Change the VPN app. assertTrue(vpn.setAlwaysOnPackage( Loading @@ -412,8 +395,6 @@ public class VpnTest { new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) })); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); Loading @@ -424,9 +405,6 @@ public class VpnTest { verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop), })); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0]); // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( Loading @@ -438,8 +416,6 @@ public class VpnTest { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); // Try allowing a package with a comma, should be rejected. assertFalse(vpn.setAlwaysOnPackage( Loading @@ -459,45 +435,6 @@ public class VpnTest { })); } @Test public void testLockdownAddingAProfile() throws Exception { final Vpn vpn = createVpn(primaryUser.id); setMockedUsers(primaryUser); // Make a copy of the restricted profile, as we're going to mark it deleted halfway through. final UserInfo tempProfile = new UserInfo(restrictedProfileA.id, restrictedProfileA.name, restrictedProfileA.flags); tempProfile.restrictedProfileParentId = primaryUser.id; final UidRange user = PRI_USER_RANGE; final UidRange profile = UidRange.createForUser(tempProfile.id); // Set lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); // Verify restricted user isn't affected at first. assertUnblocked(vpn, profile.start + PKG_UIDS[0]); // Add the restricted user. setMockedUsers(primaryUser, tempProfile); vpn.onUserAdded(tempProfile.id); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1), new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop) })); // Remove the restricted user. tempProfile.partial = true; vpn.onUserRemoved(tempProfile.id); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1), new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop) })); } @Test public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); Loading Loading @@ -1207,20 +1144,6 @@ public class VpnTest { return vpn; } private static void assertBlocked(Vpn vpn, int... uids) { for (int uid : uids) { final boolean blocked = vpn.getLockdown() && vpn.isBlockingUid(uid); assertTrue("Uid " + uid + " should be blocked", blocked); } } private static void assertUnblocked(Vpn vpn, int... uids) { for (int uid : uids) { final boolean blocked = vpn.getLockdown() && vpn.isBlockingUid(uid); assertFalse("Uid " + uid + " should not be blocked", blocked); } } /** * Populate {@link #mUserManager} with a list of fake users. */ Loading Loading
services/core/java/com/android/server/connectivity/Vpn.java +0 −28 Original line number Diff line number Diff line Loading @@ -1850,34 +1850,6 @@ public class Vpn { } } /** * @param uid The target uid. * * @return {@code true} if {@code uid} is included in one of the mBlockedUidsAsToldToNetd * ranges and the VPN is not connected, or if the VPN is connected but does not apply to * the {@code uid}. * * @apiNote This method don't check VPN lockdown status. * @see #mBlockedUidsAsToldToConnectivity */ public synchronized boolean isBlockingUid(int uid) { if (mNetworkInfo.isConnected()) { return !appliesToUid(uid); } else { return containsUid(mBlockedUidsAsToldToConnectivity, uid); } } private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) { if (ranges == null) return false; for (UidRangeParcel range : ranges) { if (range.start <= uid && uid <= range.stop) { return true; } } return false; } private void updateAlwaysOnNotification(DetailedState networkState) { final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); Loading
tests/net/java/com/android/server/ConnectivityServiceTest.java +54 −0 Original line number Diff line number Diff line Loading @@ -1199,6 +1199,8 @@ public class ConnectivityServiceTest { updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect"); } mAgentRegistered = false; setUids(null); mInterface = null; } @Override Loading Loading @@ -6180,11 +6182,15 @@ public class ConnectivityServiceTest { // Create a fake restricted profile whose parent is our user ID. final int userId = UserHandle.getUserId(uid); when(mUserManager.canHaveRestrictedProfile(userId)).thenReturn(true); final int restrictedUserId = userId + 1; final UserInfo info = new UserInfo(restrictedUserId, "user", UserInfo.FLAG_RESTRICTED); info.restrictedProfileParentId = userId; assertTrue(info.isRestricted()); when(mUserManager.getUserInfo(restrictedUserId)).thenReturn(info); when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, restrictedUserId)) .thenReturn(UserHandle.getUid(restrictedUserId, VPN_UID)); final Intent addedIntent = new Intent(ACTION_USER_ADDED); addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId); Loading Loading @@ -6224,6 +6230,54 @@ public class ConnectivityServiceTest { && caps.getUids().contains(new UidRange(uid, uid)) && caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_WIFI)); // Test lockdown with restricted profiles. mServiceContext.setPermission( Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED); mServiceContext.setPermission( Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED); mServiceContext.setPermission( Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED); // Connect wifi and check that UIDs in the main and restricted profiles have network access. mMockVpn.disconnect(); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true /* validated */); final int restrictedUid = UserHandle.getUid(restrictedUserId, 42 /* appId */); assertNotNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); // Enable always-on VPN lockdown. The main user loses network access because no VPN is up. final ArrayList<String> allowList = new ArrayList<>(); mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); // Start the restricted profile, and check that the UID within it loses network access. when(mUserManager.getAliveUsers()).thenReturn( Arrays.asList(new UserInfo[] { new UserInfo(userId, "", 0), info })); // TODO: check that VPN app within restricted profile still has access, etc. handler.post(() -> mServiceContext.sendBroadcast(addedIntent)); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); assertNull(mCm.getActiveNetworkForUid(restrictedUid)); // Stop the restricted profile, and check that the UID within it has network access again. when(mUserManager.getAliveUsers()).thenReturn( Arrays.asList(new UserInfo[] { new UserInfo(userId, "", 0), })); handler.post(() -> mServiceContext.sendBroadcast(removedIntent)); waitForIdle(); assertNull(mCm.getActiveNetworkForUid(uid)); assertNotNull(mCm.getActiveNetworkForUid(restrictedUid)); mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); waitForIdle(); } @Test Loading
tests/net/java/com/android/server/connectivity/VpnTest.java +0 −77 Original line number Diff line number Diff line Loading @@ -339,14 +339,8 @@ public class VpnTest { final Vpn vpn = createVpn(primaryUser.id); final UidRange user = PRI_USER_RANGE; // Default state. assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore)); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore)); Loading @@ -355,10 +349,6 @@ public class VpnTest { new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { Loading @@ -369,9 +359,6 @@ public class VpnTest { new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[3]); } @Test Loading @@ -386,8 +373,6 @@ public class VpnTest { new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); Loading @@ -398,8 +383,6 @@ public class VpnTest { new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]); // Change the VPN app. assertTrue(vpn.setAlwaysOnPackage( Loading @@ -412,8 +395,6 @@ public class VpnTest { new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) })); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); Loading @@ -424,9 +405,6 @@ public class VpnTest { verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop), })); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0]); // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( Loading @@ -438,8 +416,6 @@ public class VpnTest { new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); // Try allowing a package with a comma, should be rejected. assertFalse(vpn.setAlwaysOnPackage( Loading @@ -459,45 +435,6 @@ public class VpnTest { })); } @Test public void testLockdownAddingAProfile() throws Exception { final Vpn vpn = createVpn(primaryUser.id); setMockedUsers(primaryUser); // Make a copy of the restricted profile, as we're going to mark it deleted halfway through. final UserInfo tempProfile = new UserInfo(restrictedProfileA.id, restrictedProfileA.name, restrictedProfileA.flags); tempProfile.restrictedProfileParentId = primaryUser.id; final UidRange user = PRI_USER_RANGE; final UidRange profile = UidRange.createForUser(tempProfile.id); // Set lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); // Verify restricted user isn't affected at first. assertUnblocked(vpn, profile.start + PKG_UIDS[0]); // Add the restricted user. setMockedUsers(primaryUser, tempProfile); vpn.onUserAdded(tempProfile.id); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1), new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop) })); // Remove the restricted user. tempProfile.partial = true; vpn.onUserRemoved(tempProfile.id); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1), new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop) })); } @Test public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); Loading Loading @@ -1207,20 +1144,6 @@ public class VpnTest { return vpn; } private static void assertBlocked(Vpn vpn, int... uids) { for (int uid : uids) { final boolean blocked = vpn.getLockdown() && vpn.isBlockingUid(uid); assertTrue("Uid " + uid + " should be blocked", blocked); } } private static void assertUnblocked(Vpn vpn, int... uids) { for (int uid : uids) { final boolean blocked = vpn.getLockdown() && vpn.isBlockingUid(uid); assertFalse("Uid " + uid + " should not be blocked", blocked); } } /** * Populate {@link #mUserManager} with a list of fake users. */ Loading