summaryrefslogtreecommitdiff
path: root/core/java/android/net/ConnectivityManager.java
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2020-12-12 00:51:11 +0900
committerLorenzo Colitti <lorenzo@google.com>2021-01-07 17:44:29 +0900
commit282ed251ce24d89d33c1174e87d82b96e923b9b5 (patch)
treee5dacd7fd40954148977b50fb7c9686fa8761e64 /core/java/android/net/ConnectivityManager.java
parent60dfb880de62fb5fca5eaf19cd5f665dc247e150 (diff)
Inform ConnectivityService about always-on VPN lockdown.
Currently, when an always-on VPN is set in lockdown mode, Vpn configures prohibit UID rules in netd directly and does not inform ConnectivityService of the fact. This means that ConnectivityService cannot send NetworkCallbacks that tells apps that they are blocked or unblocked. It also means that ConnectivityService has to take the mVpns lock and call into Vpn to allow synchronous APIs such as getActiveNetwork to return BLOCKED if the app is blocked. Move all this to ConnectivityService: - Add a setRequireVpnForUids API to ConnectivityManager, and have that pass the routing rules to netd. - Update VpnTest to expect calls to ConnectivityManager instead of to netd. - Whenever setRequireVpnForUids is called, ensure that ConnectivityService sends onBlockedStatusChanged to the affected callbacks. - Update existing unit tests to check for callbacks. - Add a way to find the VPN that applies to a given UID without taking the VPN lock, by instead scanning all connected VPNs. Use this as a replacement for direct access to mVpns. For simplicity, and in order to ensure proper ordering between the NetworkCallbacks sent for VPNs connecting and disconnecting, process blocked UID ranges on the handler thread. This means that when setRequireVpnForUids returns, the rule changes might not have been applied. This shouldn't impact apps using network connectivity, but it might mean that apps setting an always-on package, and then immediately checking whether networking is blocked, will see a behaviour change. Bug: 173331190 Fix: 175670887 Test: new test coverage in ConnectivityServiceTest Test: atest MixedDeviceOwnerTest#testAlwaysOnVpn \ MixedDeviceOwnerTest#testAlwaysOnVpnLockDown \ MixedDeviceOwnerTest#testAlwaysOnVpnAcrossReboot \ MixedDeviceOwnerTest#testAlwaysOnVpnPackageUninstalled \ MixedDeviceOwnerTest#testAlwaysOnVpnUnsupportedPackage \ MixedDeviceOwnerTest#testAlwaysOnVpnUnsupportedPackageReplaced \ MixedDeviceOwnerTest#testAlwaysOnVpnPackageLogged \ MixedProfileOwnerTest#testAlwaysOnVpn \ MixedProfileOwnerTest#testAlwaysOnVpnLockDown \ MixedProfileOwnerTest#testAlwaysOnVpnAcrossReboot \ MixedProfileOwnerTest#testAlwaysOnVpnPackageUninstalled \ MixedProfileOwnerTest#testAlwaysOnVpnUnsupportedPackage \ MixedProfileOwnerTest#testAlwaysOnVpnUnsupportedPackageReplaced \ MixedProfileOwnerTest#testAlwaysOnVpnPackageLogged \ MixedManagedProfileOwnerTest#testAlwaysOnVpn \ MixedManagedProfileOwnerTest#testAlwaysOnVpnLockDown \ MixedManagedProfileOwnerTest#testAlwaysOnVpnAcrossReboot \ MixedManagedProfileOwnerTest#testAlwaysOnVpnPackageUninstalled \ MixedManagedProfileOwnerTest#testAlwaysOnVpnUnsupportedPackage \ MixedManagedProfileOwnerTest#testAlwaysOnVpnUnsupportedPackageReplaced \ MixedManagedProfileOwnerTest#testAlwaysOnVpnPackageLogged Test: atest FrameworksNetTests HostsideVpnTests \ CtsNetTestCases:VpnServiceTest \ CtsNetTestCases:Ikev2VpnTest Change-Id: Iaca8a7cc343aef52706cff62a7735f338cb1b772
Diffstat (limited to 'core/java/android/net/ConnectivityManager.java')
-rw-r--r--core/java/android/net/ConnectivityManager.java52
1 files changed, 52 insertions, 0 deletions
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 0d10e4a01aa4..06c159804a45 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -59,6 +59,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Range;
import android.util.SparseIntArray;
import com.android.connectivity.aidl.INetworkAgent;
@@ -73,10 +74,12 @@ import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -1163,6 +1166,55 @@ public class ConnectivityManager {
}
/**
+ * Adds or removes a requirement for given UID ranges to use the VPN.
+ *
+ * If set to {@code true}, informs the system that the UIDs in the specified ranges must not
+ * have any connectivity except if a VPN is connected and applies to the UIDs, or if the UIDs
+ * otherwise have permission to bypass the VPN (e.g., because they have the
+ * {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS} permission, or when
+ * using a socket protected by a method such as {@link VpnService#protect(DatagramSocket)}. If
+ * set to {@code false}, a previously-added restriction is removed.
+ * <p>
+ * Each of the UID ranges specified by this method is added and removed as is, and no processing
+ * is performed on the ranges to de-duplicate, merge, split, or intersect them. In order to
+ * remove a previously-added range, the exact range must be removed as is.
+ * <p>
+ * The changes are applied asynchronously and may not have been applied by the time the method
+ * returns. Apps will be notified about any changes that apply to them via
+ * {@link NetworkCallback#onBlockedStatusChanged} callbacks called after the changes take
+ * effect.
+ * <p>
+ * This method should be called only by the VPN code.
+ *
+ * @param ranges the UID ranges to restrict
+ * @param requireVpn whether the specified UID ranges must use a VPN
+ *
+ * TODO: expose as @SystemApi.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
+ public void setRequireVpnForUids(boolean requireVpn,
+ @NonNull Collection<Range<Integer>> ranges) {
+ Objects.requireNonNull(ranges);
+ // The Range class is not parcelable. Convert to UidRange, which is what is used internally.
+ // This method is not necessarily expected to be used outside the system server, so
+ // parceling may not be necessary, but it could be used out-of-process, e.g., by the network
+ // stack process, or by tests.
+ UidRange[] rangesArray = new UidRange[ranges.size()];
+ int index = 0;
+ for (Range<Integer> range : ranges) {
+ rangesArray[index++] = new UidRange(range.getLower(), range.getUpper());
+ }
+ try {
+ mService.setRequireVpnForUids(requireVpn, rangesArray);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns details about the currently active default data network
* for a given uid. This is for internal use only to avoid spying
* other apps.