Merge "Resolve UidRange dependency between NMS and CS module"

This commit is contained in:
Chiachang Wang
2020-12-14 02:55:41 +00:00
committed by Gerrit Code Review
3 changed files with 117 additions and 98 deletions

View File

@@ -129,6 +129,7 @@ import android.net.RouteInfoParcel;
import android.net.SocketKeepalive; import android.net.SocketKeepalive;
import android.net.TetheringManager; import android.net.TetheringManager;
import android.net.UidRange; import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.Uri; import android.net.Uri;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.VpnService; import android.net.VpnService;
@@ -5152,7 +5153,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
loge("Starting user already has a VPN"); loge("Starting user already has a VPN");
return; return;
} }
userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore); userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore);
mVpns.put(userId, userVpn); mVpns.put(userId, userVpn);
if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
updateLockdownVpn(); updateLockdownVpn();
@@ -6622,6 +6623,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
&& (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute()); && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute());
} }
private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()];
int index = 0;
for (UidRange range : ranges) {
stableRanges[index] = new UidRangeParcel(range.start, range.stop);
index++;
}
return stableRanges;
}
private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
NetworkCapabilities newNc) { NetworkCapabilities newNc) {
Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids(); Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
@@ -6641,14 +6652,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
// removing old range works because, unlike the filtering rules below, it's possible to // removing old range works because, unlike the filtering rules below, it's possible to
// add duplicate UID routing rules. // add duplicate UID routing rules.
if (!newRanges.isEmpty()) { if (!newRanges.isEmpty()) {
final UidRange[] addedRangesArray = new UidRange[newRanges.size()]; mNetd.networkAddUidRanges(nai.network.netId, toUidRangeStableParcels(newRanges));
newRanges.toArray(addedRangesArray);
mNMS.addVpnUidRanges(nai.network.getNetId(), addedRangesArray);
} }
if (!prevRanges.isEmpty()) { if (!prevRanges.isEmpty()) {
final UidRange[] removedRangesArray = new UidRange[prevRanges.size()]; mNetd.networkRemoveUidRanges(
prevRanges.toArray(removedRangesArray); nai.network.netId, toUidRangeStableParcels(prevRanges));
mNMS.removeVpnUidRanges(nai.network.getNetId(), removedRangesArray);
} }
final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties); final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties);
final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties); final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties);

View File

@@ -188,6 +188,7 @@ import android.net.RouteInfo;
import android.net.RouteInfoParcel; import android.net.RouteInfoParcel;
import android.net.SocketKeepalive; import android.net.SocketKeepalive;
import android.net.UidRange; import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.Uri; import android.net.Uri;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.metrics.IpConnectivityLog; import android.net.metrics.IpConnectivityLog;
@@ -1055,7 +1056,7 @@ public class ConnectivityServiceTest {
public MockVpn(int userId) { public MockVpn(int userId) {
super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
userId, mock(KeyStore.class)); mMockNetd, userId, mock(KeyStore.class));
mConfig = new VpnConfig(); mConfig = new VpnConfig();
} }
@@ -1094,10 +1095,11 @@ public class ConnectivityServiceTest {
mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp, mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp,
mNetworkCapabilities); mNetworkCapabilities);
mMockNetworkAgent.waitForIdle(TIMEOUT_MS); mMockNetworkAgent.waitForIdle(TIMEOUT_MS);
verify(mNetworkManagementService, times(1))
.addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0]))); verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetId()),
verify(mNetworkManagementService, never()) eq(toUidRangeStableParcels(uids)));
.removeVpnUidRanges(eq(mMockVpn.getNetId()), any()); verify(mMockNetd, never())
.networkRemoveUidRanges(eq(mMockVpn.getNetId()), any());
mAgentRegistered = true; mAgentRegistered = true;
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mNetworkAgent = mMockNetworkAgent.getNetworkAgent(); mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
@@ -1169,6 +1171,11 @@ public class ConnectivityServiceTest {
} }
} }
private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) {
return ranges.stream().map(
r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new);
}
private void mockVpn(int uid) { private void mockVpn(int uid) {
synchronized (mService.mVpns) { synchronized (mService.mVpns) {
int userId = UserHandle.getUserId(uid); int userId = UserHandle.getUserId(uid);

View File

@@ -58,6 +58,7 @@ import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.Ikev2VpnProfile; import android.net.Ikev2VpnProfile;
import android.net.InetAddresses; import android.net.InetAddresses;
import android.net.IpPrefix; import android.net.IpPrefix;
@@ -70,6 +71,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo; import android.net.RouteInfo;
import android.net.UidRange; import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.VpnManager; import android.net.VpnManager;
import android.net.VpnService; import android.net.VpnService;
import android.net.ipsec.ike.IkeSessionCallback; import android.net.ipsec.ike.IkeSessionCallback;
@@ -172,11 +174,13 @@ public class VpnTest {
mPackages.put(PKGS[i], PKG_UIDS[i]); mPackages.put(PKGS[i], PKG_UIDS[i]);
} }
} }
private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id);
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager; @Mock private UserManager mUserManager;
@Mock private PackageManager mPackageManager; @Mock private PackageManager mPackageManager;
@Mock private INetworkManagementService mNetService; @Mock private INetworkManagementService mNetService;
@Mock private INetd mNetd;
@Mock private AppOpsManager mAppOps; @Mock private AppOpsManager mAppOps;
@Mock private NotificationManager mNotificationManager; @Mock private NotificationManager mNotificationManager;
@Mock private Vpn.SystemServices mSystemServices; @Mock private Vpn.SystemServices mSystemServices;
@@ -256,8 +260,7 @@ public class VpnTest {
null, null); null, null);
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
UidRange.createForUser(primaryUser.id), PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id)
UidRange.createForUser(restrictedProfileA.id)
})), ranges); })), ranges);
} }
@@ -269,9 +272,7 @@ public class VpnTest {
final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, null); null, null);
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
UidRange.createForUser(primaryUser.id)
})), ranges);
} }
@Test @Test
@@ -282,15 +283,13 @@ public class VpnTest {
final Set<UidRange> ranges = new ArraySet<>(); final Set<UidRange> ranges = new ArraySet<>();
vpn.addUserToRanges(ranges, primaryUser.id, null, null); vpn.addUserToRanges(ranges, primaryUser.id, null, null);
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
UidRange.createForUser(primaryUser.id)
})), ranges);
} }
@Test @Test
public void testUidAllowAndDenylist() throws Exception { public void testUidAllowAndDenylist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id); final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id); final UidRange user = PRI_USER_RANGE;
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
// Allowed list // Allowed list
@@ -339,62 +338,67 @@ public class VpnTest {
@Test @Test
public void testLockdownChangingPackage() throws Exception { public void testLockdownChangingPackage() throws Exception {
final Vpn vpn = createVpn(primaryUser.id); final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id); final UidRange user = PRI_USER_RANGE;
// Default state. // Default state.
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); 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. // Set always-on without lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore)); 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]); 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. // Set always-on with lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore)); assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) 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]);
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2],
user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[1]); assertUnblocked(vpn, user.start + PKG_UIDS[1]);
// Switch to another app. // Switch to another app.
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
})); }));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
new UidRange(user.start, user.start + PKG_UIDS[3] - 1), verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) 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]); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1],
user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[3]);
} }
@Test @Test
public void testLockdownAllowlist() throws Exception { public void testLockdownAllowlist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id); final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id); final UidRange user = PRI_USER_RANGE;
// Set always-on with lockdown and allow app PKGS[2] from lockdown. // Set always-on with lockdown and allow app PKGS[2] from lockdown.
assertTrue(vpn.setAlwaysOnPackage( assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore)); PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
})); }));
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
// Change allowed app list to PKGS[3]. // Change allowed app list to PKGS[3].
assertTrue(vpn.setAlwaysOnPackage( assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
})); }));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
})); }));
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
@@ -402,25 +406,25 @@ public class VpnTest {
// Change the VPN app. // Change the VPN app.
assertTrue(vpn.setAlwaysOnPackage( assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore)); PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
})); }));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start, user.start + PKG_UIDS[0] - 1), new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1),
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 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]); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
// Remove the list of allowed packages. // Remove the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
})); }));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[0] + 1, user.stop), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop),
})); }));
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2],
user.start + PKG_UIDS[3]); user.start + PKG_UIDS[3]);
@@ -429,12 +433,12 @@ public class VpnTest {
// Add the list of allowed packages. // Add the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage( assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore)); PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[0] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop)
})); }));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
})); }));
assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
@@ -447,13 +451,13 @@ public class VpnTest {
// allowed package should change from PGKS[1] to PKGS[2]. // allowed package should change from PGKS[1] to PKGS[2].
assertTrue(vpn.setAlwaysOnPackage( assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore)); PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{ verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[]{
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
})); }));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{ verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[]{
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1), new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
})); }));
} }
@@ -467,86 +471,86 @@ public class VpnTest {
restrictedProfileA.flags); restrictedProfileA.flags);
tempProfile.restrictedProfileParentId = primaryUser.id; tempProfile.restrictedProfileParentId = primaryUser.id;
final UidRange user = UidRange.createForUser(primaryUser.id); final UidRange user = PRI_USER_RANGE;
final UidRange profile = UidRange.createForUser(tempProfile.id); final UidRange profile = UidRange.createForUser(tempProfile.id);
// Set lockdown. // Set lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(user.start, user.start + PKG_UIDS[3] - 1), new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
})); }));
// Verify restricted user isn't affected at first. // Verify restricted user isn't affected at first.
assertUnblocked(vpn, profile.start + PKG_UIDS[0]); assertUnblocked(vpn, profile.start + PKG_UIDS[0]);
// Add the restricted user. // Add the restricted user.
setMockedUsers(primaryUser, tempProfile); setMockedUsers(primaryUser, tempProfile);
vpn.onUserAdded(tempProfile.id); vpn.onUserAdded(tempProfile.id);
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] {
new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1), new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop) new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
})); }));
// Remove the restricted user. // Remove the restricted user.
tempProfile.partial = true; tempProfile.partial = true;
vpn.onUserRemoved(tempProfile.id); vpn.onUserRemoved(tempProfile.id);
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] {
new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1), new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1),
new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop) new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop)
})); }));
} }
@Test @Test
public void testLockdownRuleRepeatability() throws Exception { public void testLockdownRuleRepeatability() throws Exception {
final Vpn vpn = createVpn(primaryUser.id); final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
// Given legacy lockdown is already enabled, // Given legacy lockdown is already enabled,
vpn.setLockdown(true); vpn.setLockdown(true);
verify(mNetService, times(1)).setAllowOnlyVpnForUids(
eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(primaryUserRangeParcel));
// Enabling legacy lockdown twice should do nothing. // Enabling legacy lockdown twice should do nothing.
vpn.setLockdown(true); vpn.setLockdown(true);
verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); verify(mNetd, times(1))
.networkRejectNonSecureVpn(anyBoolean(), any(UidRangeParcel[].class));
// And disabling should remove the rules exactly once. // And disabling should remove the rules exactly once.
vpn.setLockdown(false); vpn.setLockdown(false);
verify(mNetService, times(1)).setAllowOnlyVpnForUids( verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(primaryUserRangeParcel));
eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)}));
// Removing the lockdown again should have no effect. // Removing the lockdown again should have no effect.
vpn.setLockdown(false); vpn.setLockdown(false);
verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); verify(mNetd, times(2)).networkRejectNonSecureVpn(
anyBoolean(), any(UidRangeParcel[].class));
} }
@Test @Test
public void testLockdownRuleReversibility() throws Exception { public void testLockdownRuleReversibility() throws Exception {
final Vpn vpn = createVpn(primaryUser.id); final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] entireUser = {
final UidRange[] entireUser = { new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
UidRange.createForUser(primaryUser.id)
}; };
final UidRange[] exceptPkg0 = { final UidRangeParcel[] exceptPkg0 = {
new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),
new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop)
}; };
final InOrder order = inOrder(mNetService); final InOrder order = inOrder(mNetd);
// Given lockdown is enabled with no package (legacy VPN), // Given lockdown is enabled with no package (legacy VPN),
vpn.setLockdown(true); vpn.setLockdown(true);
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
// When a new VPN package is set the rules should change to cover that package. // When a new VPN package is set the rules should change to cover that package.
vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE); vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE);
order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser)); order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(entireUser));
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0)); order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(exceptPkg0));
// When that VPN package is unset, everything should be undone again in reverse. // When that VPN package is unset, everything should be undone again in reverse.
vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE); vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE);
order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0)); order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(exceptPkg0));
order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser));
} }
@Test @Test
@@ -1186,7 +1190,7 @@ public class VpnTest {
.thenReturn(asUserContext); .thenReturn(asUserContext);
final TestLooper testLooper = new TestLooper(); final TestLooper testLooper = new TestLooper();
final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService, final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService,
userId, mKeyStore, mSystemServices, mIkev2SessionCreator); mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat(
provider -> provider.getName().contains("VpnNetworkProvider") provider -> provider.getName().contains("VpnNetworkProvider")
)); ));