diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java index ec71d3d65a..5bd0af894c 100644 --- a/framework/src/android/net/NetworkCapabilities.java +++ b/framework/src/android/net/NetworkCapabilities.java @@ -818,7 +818,7 @@ public final class NetworkCapabilities implements Parcelable { * restrictions. * @hide */ - public void restrictCapabilitesForTestNetwork(int creatorUid) { + public void restrictCapabilitiesForTestNetwork(int creatorUid) { final long originalCapabilities = mNetworkCapabilities; final long originalTransportTypes = mTransportTypes; final NetworkSpecifier originalSpecifier = mNetworkSpecifier; @@ -828,7 +828,7 @@ public final class NetworkCapabilities implements Parcelable { final TransportInfo originalTransportInfo = getTransportInfo(); final Set originalSubIds = getSubscriptionIds(); clearAll(); - if (0 != (originalCapabilities & NET_CAPABILITY_NOT_RESTRICTED)) { + if (0 != (originalCapabilities & (1 << NET_CAPABILITY_NOT_RESTRICTED))) { // If the test network is not restricted, then it is only allowed to declare some // specific transports. This is to minimize impact on running apps in case an app // run from the shell creates a test a network. diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 34e15ca547..ea6156ad52 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -3255,7 +3255,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the Messenger, but if this ever changes, not making a defensive copy // here will give attack vectors to clients using this code path. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid); + networkCapabilities.restrictCapabilitiesForTestNetwork(nai.creatorUid); } processCapabilitiesFromAgent(nai, networkCapabilities); updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); @@ -6764,7 +6764,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never // sees capabilities that may be malicious, which might prevent mistakes in the future. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(uid); + networkCapabilities.restrictCapabilitiesForTestNetwork(uid); } LinkProperties lp = new LinkProperties(linkProperties); diff --git a/tests/common/java/android/net/NetworkCapabilitiesTest.java b/tests/common/java/android/net/NetworkCapabilitiesTest.java index 493a201f44..3d0cb92e78 100644 --- a/tests/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/common/java/android/net/NetworkCapabilitiesTest.java @@ -1167,4 +1167,48 @@ public class NetworkCapabilitiesTest { // Ensure test case fails if new net cap is added into default cap but no update here. assertEquals(0, nc.getCapabilities().length); } + + @Test @IgnoreUpTo(Build.VERSION_CODES.R) + public void testRestrictCapabilitiesForTestNetwork() { + final int ownerUid = 1234; + final int[] administratorUids = {1001, ownerUid}; + final NetworkCapabilities nonRestrictedNc = new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_CELLULAR) + .addTransportType(TRANSPORT_VPN) + .addCapability(NET_CAPABILITY_MMS) + .addCapability(NET_CAPABILITY_NOT_METERED) + .setAdministratorUids(administratorUids) + .setOwnerUid(ownerUid) + .setSubscriptionIds(Set.of(TEST_SUBID1)).build(); + + nonRestrictedNc.restrictCapabilitiesForTestNetwork(ownerUid); + // TRANSPORT_TEST will be appended + assertTrue(nonRestrictedNc.hasTransport(TRANSPORT_TEST)); + assertEquals(Set.of(TEST_SUBID1), nonRestrictedNc.getSubscriptionIds()); + // Non-UNRESTRICTED_TEST_NETWORKS_ALLOWED_TRANSPORTS will be removed + assertFalse(nonRestrictedNc.hasTransport(TRANSPORT_CELLULAR)); + assertTrue(nonRestrictedNc.hasTransport(TRANSPORT_VPN)); + // Only TEST_NETWORKS_ALLOWED_CAPABILITIES will be kept + assertFalse(nonRestrictedNc.hasCapability(NET_CAPABILITY_MMS)); + assertTrue(nonRestrictedNc.hasCapability(NET_CAPABILITY_NOT_METERED)); + + final NetworkCapabilities restrictedNc = new NetworkCapabilities.Builder(nonRestrictedNc) + .removeCapability(NET_CAPABILITY_NOT_RESTRICTED) + .addTransportType(TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_MMS).build(); + restrictedNc.restrictCapabilitiesForTestNetwork(ownerUid); + // It may declare any transport if the net cap is restricted + assertTrue(restrictedNc.hasTransport(TRANSPORT_CELLULAR)); + // SubIds will be cleared. + assertEquals(new ArraySet<>(), restrictedNc.getSubscriptionIds()); + // Only retain the owner and administrator UIDs if they match the app registering the remote + // caller that registered the network. + assertEquals(ownerUid, restrictedNc.getOwnerUid()); + assertArrayEquals(new int[] {ownerUid}, restrictedNc.getAdministratorUids()); + // The creator UID does not match the owner and administrator UIDs will clear the owner and + // administrator UIDs. + restrictedNc.restrictCapabilitiesForTestNetwork(5678); + assertEquals(INVALID_UID, restrictedNc.getOwnerUid()); + assertArrayEquals(new int[0], restrictedNc.getAdministratorUids()); + } }