diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index b2e49e7f50..46039b3fda 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -7482,7 +7482,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { private boolean isLegacyLockdownNai(NetworkAgentInfo nai) { return mLockdownEnabled - && getVpnType(nai) == VpnManager.TYPE_VPN_LEGACY + && isLegacyVpn(nai) && nai.networkCapabilities.appliesToUid(Process.FIRST_APPLICATION_UID); } @@ -10116,8 +10116,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { * interfaces. * Ingress discard rule is added to the address iff * 1. The address is not a link local address - * 2. The address is used by a single interface of VPN whose VPN type is not TYPE_VPN_LEGACY - * or TYPE_VPN_OEM and the address is not used by any other interfaces even non-VPN ones + * 2. The address is used by a single interface of VPN whose VPN type is not LEGACY, OEM or + * OEM_LEGACY and the address is not used by any other interfaces even non-VPN ones * Ingress discard rule is not be added to TYPE_VPN_LEGACY or TYPE_VPN_OEM VPN since these VPNs * might need to receive packet to VPN address via non-VPN interface. * This method can be called during network disconnects, when nai has already been removed from @@ -10155,9 +10155,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { final Set> ingressDiscardRules = new ArraySet<>(); for (final NetworkAgentInfo agent : nais) { final int vpnType = getVpnType(agent); - if (!agent.isVPN() || agent.isDestroyed() - || vpnType == VpnManager.TYPE_VPN_LEGACY - || vpnType == VpnManager.TYPE_VPN_OEM) { + if (!agent.isVPN() || agent.isDestroyed() || !vpnSupportsInterfaceFiltering(agent)) { continue; } final LinkProperties agentLp = (nai == agent) ? lp : agent.linkProperties; @@ -12800,6 +12798,23 @@ public class ConnectivityService extends IConnectivityManager.Stub { return ((VpnTransportInfo) ti).getType(); } + private boolean isVpnServiceVpn(NetworkAgentInfo nai) { + final int vpnType = getVpnType(nai); + return vpnType == VpnManager.TYPE_VPN_SERVICE || vpnType == VpnManager.TYPE_VPN_OEM_SERVICE; + } + + private boolean isLegacyVpn(NetworkAgentInfo nai) { + final int vpnType = getVpnType(nai); + return vpnType == VpnManager.TYPE_VPN_LEGACY || vpnType == VpnManager.TYPE_VPN_OEM_LEGACY; + } + + private boolean vpnSupportsInterfaceFiltering(NetworkAgentInfo vpn) { + final int vpnType = getVpnType(vpn); + return vpnType != VpnManager.TYPE_VPN_LEGACY + && vpnType != VpnManager.TYPE_VPN_OEM + && vpnType != VpnManager.TYPE_VPN_OEM_LEGACY; + } + private void maybeUpdateWifiRoamTimestamp(@NonNull NetworkAgentInfo nai, @NonNull NetworkCapabilities nc) { final TransportInfo prevInfo = nai.networkCapabilities.getTransportInfo(); @@ -12833,7 +12848,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (hasNetworkStackPermission()) return uid; final NetworkAgentInfo vpn = getVpnForUid(uid); - if (vpn == null || getVpnType(vpn) != VpnManager.TYPE_VPN_SERVICE + if (vpn == null || !isVpnServiceVpn(vpn) || vpn.networkCapabilities.getOwnerUid() != mDeps.getCallingUid()) { return INVALID_UID; } diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt index 8fcc703c0a..0aa491e446 100644 --- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt +++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt @@ -1055,6 +1055,47 @@ class NetworkAgentTest { callback.expect(agent.network!!) } + fun doTestOemVpnType(type: Int) { + val mySessionId = "MySession12345" + val nc = NetworkCapabilities().apply { + addTransportType(TRANSPORT_TEST) + addTransportType(TRANSPORT_VPN) + addCapability(NET_CAPABILITY_NOT_VCN_MANAGED) + removeCapability(NET_CAPABILITY_NOT_VPN) + setTransportInfo(VpnTransportInfo(type, mySessionId)) + } + + val agent = createNetworkAgent(initialNc = nc) + agent.register() + agent.markConnected() + + val request = NetworkRequest.Builder() + .clearCapabilities() + .addTransportType(TRANSPORT_VPN) + .removeCapability(NET_CAPABILITY_NOT_VPN) + .build() + val callback = TestableNetworkCallback() + registerNetworkCallback(request, callback) + + callback.expectAvailableThenValidatedCallbacks(agent.network!!) + + var vpnNc = mCM.getNetworkCapabilities(agent.network!!) + assertNotNull(vpnNc) + assertEquals(type, (vpnNc!!.transportInfo as VpnTransportInfo).type) + + agent.unregister() + callback.expect(agent.network!!) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) + fun testOemVpnTypes() { + // TODO: why is this necessary given the @IgnoreUpTo above? + assumeTrue(SdkLevel.isAtLeastB()) + doTestOemVpnType(VpnManager.TYPE_VPN_OEM_SERVICE) + doTestOemVpnType(VpnManager.TYPE_VPN_OEM_LEGACY) + } + private fun unregister(agent: TestableNetworkAgent) { agent.unregister() agent.eventuallyExpect()