From 021d8b08c19a91f4b862d4b6b681ea46de017cb8 Mon Sep 17 00:00:00 2001 From: Martijn Coenen Date: Thu, 21 Apr 2022 09:03:35 +0000 Subject: [PATCH] Modify VPN unit tests to include SDK sandbox UIDs. VPN configurations in T should automatically include the corresponding SDK sandbox UID of an application. The existing tests used a UID range outside the regular application range, which means the new sandbox UIDs wouldn't be tested. Modified the UIDs to run in the regular UID range of [10000, 19999]. Changed the tests to include the SDK sandbox UID where necessary. Also, changed the entire class to only run on T+, since that is the only place where the SDK sandbox UIDs will be added. Since VPN code is not mainline updatable, having coverage on earlier releases doesn't really help anyway. Finally, fixed up testNetworkBlockedStatusAlwaysOnVpn() in ConnectivityServiceTest to include the sandbox UIDs as well. Bug: 225317905 Test: atest VpnTest Test: atest ConnectivityServiceTest Change-Id: I83009344c270e520ac8ad1558c067cf7e46b1d2e --- .../server/ConnectivityServiceTest.java | 59 +++++++++--- .../android/server/connectivity/VpnTest.java | 91 +++++++++++++++---- 2 files changed, 118 insertions(+), 32 deletions(-) diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java index 32160c7d21..3374672419 100644 --- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -805,6 +805,32 @@ public class ConnectivityServiceTest { } } + // This was only added in the T SDK, but this test needs to build against the R+S SDKs, too. + private static int toSdkSandboxUid(int appUid) { + final int firstSdkSandboxUid = 20000; + return appUid + (firstSdkSandboxUid - Process.FIRST_APPLICATION_UID); + } + + // This function assumes the UID range for user 0 ([1, 99999]) + private static UidRangeParcel[] uidRangeParcelsExcludingUids(Integer... excludedUids) { + int start = 1; + Arrays.sort(excludedUids); + List parcels = new ArrayList(); + for (int excludedUid : excludedUids) { + if (excludedUid == start) { + start++; + } else { + parcels.add(new UidRangeParcel(start, excludedUid - 1)); + start = excludedUid + 1; + } + } + if (start <= 99999) { + parcels.add(new UidRangeParcel(start, 99999)); + } + + return parcels.toArray(new UidRangeParcel[0]); + } + private void waitForIdle() { HandlerUtils.waitForIdle(mCsHandlerThread, TIMEOUT_MS); waitForIdle(mCellNetworkAgent, TIMEOUT_MS); @@ -9016,10 +9042,16 @@ public class ConnectivityServiceTest { allowList); waitForIdle(); - UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1); - UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999); + final Set excludedUids = new ArraySet(); + excludedUids.add(VPN_UID); + if (SdkLevel.isAtLeastT()) { + // On T onwards, the corresponding SDK sandbox UID should also be excluded + excludedUids.add(toSdkSandboxUid(VPN_UID)); + } + final UidRangeParcel[] uidRangeParcels = uidRangeParcelsExcludingUids( + excludedUids.toArray(new Integer[0])); InOrder inOrder = inOrder(mMockNetd); - expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); + expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels); // Connect a network when lockdown is active, expect to see it blocked. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); @@ -9043,7 +9075,7 @@ public class ConnectivityServiceTest { vpnUidCallback.assertNoCallback(); vpnUidDefaultCallback.assertNoCallback(); vpnDefaultCallbackAsUid.assertNoCallback(); - expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf); + expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcels); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); @@ -9060,13 +9092,14 @@ public class ConnectivityServiceTest { vpnUidDefaultCallback.assertNoCallback(); vpnDefaultCallbackAsUid.assertNoCallback(); - // The following requires that the UID of this test package is greater than VPN_UID. This - // is always true in practice because a plain AOSP build with no apps installed has almost - // 200 packages installed. - final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1); - final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1); - final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999); - expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3); + excludedUids.add(uid); + if (SdkLevel.isAtLeastT()) { + // On T onwards, the corresponding SDK sandbox UID should also be excluded + excludedUids.add(toSdkSandboxUid(uid)); + } + final UidRangeParcel[] uidRangeParcelsAlsoExcludingUs = uidRangeParcelsExcludingUids( + excludedUids.toArray(new Integer[0])); + expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcelsAlsoExcludingUs); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID)); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED); @@ -9092,12 +9125,12 @@ public class ConnectivityServiceTest { // Everything should now be blocked. mVpnManagerService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList); waitForIdle(); - expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3); + expectNetworkRejectNonSecureVpn(inOrder, false, uidRangeParcelsAlsoExcludingUs); allowList.clear(); mVpnManagerService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList); waitForIdle(); - expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf); + expectNetworkRejectNonSecureVpn(inOrder, true, uidRangeParcels); defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent); assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent); vpnUidCallback.assertNoCallback(); diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java index c3510d9fe3..11fbcb9e70 100644 --- a/tests/unit/java/com/android/server/connectivity/VpnTest.java +++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java @@ -173,7 +173,7 @@ import java.util.stream.Stream; */ @RunWith(DevSdkIgnoreRunner.class) @SmallTest -@IgnoreUpTo(VERSION_CODES.R) +@IgnoreUpTo(VERSION_CODES.S_V2) public class VpnTest { private static final String TAG = "VpnTest"; @@ -212,7 +212,7 @@ public class VpnTest { */ static final String[] PKGS = {"com.example", "org.example", "net.example", "web.vpn"}; static final String PKGS_BYTES = getPackageByteString(List.of(PKGS)); - static final int[] PKG_UIDS = {66, 77, 78, 400}; + static final int[] PKG_UIDS = {10066, 10077, 10078, 10400}; // Mock packages static final Map mPackages = new ArrayMap<>(); @@ -385,7 +385,11 @@ public class VpnTest { Arrays.asList(packages), null /* disallowedApplications */); assertEquals(rangeSet( uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]), - uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])), + uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2]), + uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0]), + Process.toSdkSandboxUid(userStart + PKG_UIDS[0])), + uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[1]), + Process.toSdkSandboxUid(userStart + PKG_UIDS[2]))), allow); // Denied list @@ -396,7 +400,11 @@ public class VpnTest { uidRange(userStart, userStart + PKG_UIDS[0] - 1), uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), /* Empty range between UIDS[1] and UIDS[2], should be excluded, */ - uidRange(userStart + PKG_UIDS[2] + 1, userStop)), + uidRange(userStart + PKG_UIDS[2] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + uidRange(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop)), disallow); } @@ -437,18 +445,24 @@ public class VpnTest { assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) })); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1), - new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) })); } @@ -463,17 +477,25 @@ public class VpnTest { PKGS[1], true, Collections.singletonList(PKGS[2]))); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[1]) - 1), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) })); // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), - new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) })); // Change the VPN app. @@ -481,32 +503,52 @@ public class VpnTest { PKGS[0], true, Collections.singletonList(PKGS[3]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1), - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)) })); // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1), - new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[3] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[3] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[3] + 1), userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop), + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop), })); // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[1]))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { - new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[0] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), userStop), })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) })); // Try allowing a package with a comma, should be rejected. @@ -519,11 +561,19 @@ public class VpnTest { PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1), - new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[1] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[1] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[1] + 1), userStop) })); verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] { new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1), - new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop) + new UidRangeParcel(userStart + PKG_UIDS[2] + 1, + Process.toSdkSandboxUid(userStart + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[0] + 1), + Process.toSdkSandboxUid(userStart + PKG_UIDS[2] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(userStart + PKG_UIDS[2] + 1), userStop) })); } @@ -568,7 +618,10 @@ public class VpnTest { }; final UidRangeParcel[] exceptPkg0 = { new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), - new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) + new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, + Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] - 1)), + new UidRangeParcel(Process.toSdkSandboxUid(entireUser[0].start + PKG_UIDS[0] + 1), + entireUser[0].stop), }; final InOrder order = inOrder(mConnectivityManager);