Make sure listen requests from VPN apps see their own networks
Test: runtest frameworks-net
Test: CTS pass, including with the next patch which is what this
actually matters for
Change-Id: I09a94042acbefa24ab884f95326e30d6ab280b82
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index d0f6f9b..6e80f02 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -49,6 +49,7 @@
*/
public final class NetworkCapabilities implements Parcelable {
private static final String TAG = "NetworkCapabilities";
+ private static final int INVALID_UID = -1;
/**
* @hide
@@ -67,6 +68,7 @@
mNetworkSpecifier = nc.mNetworkSpecifier;
mSignalStrength = nc.mSignalStrength;
mUids = nc.mUids;
+ mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
}
}
@@ -81,6 +83,7 @@
mNetworkSpecifier = null;
mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
mUids = null;
+ mEstablishingVpnAppUid = INVALID_UID;
}
/**
@@ -623,6 +626,29 @@
}
/**
+ * UID of the app that manages this network, or INVALID_UID if none/unknown.
+ *
+ * This field keeps track of the UID of the app that created this network and is in charge
+ * of managing it. In the practice, it is used to store the UID of VPN apps so it is named
+ * accordingly, but it may be renamed if other mechanisms are offered for third party apps
+ * to create networks.
+ *
+ * Because this field is only used in the services side (and to avoid apps being able to
+ * set this to whatever they want), this field is not parcelled and will not be conserved
+ * across the IPC boundary.
+ * @hide
+ */
+ private int mEstablishingVpnAppUid = INVALID_UID;
+
+ /**
+ * Set the UID of the managing app.
+ * @hide
+ */
+ public void setEstablishingVpnAppUid(final int uid) {
+ mEstablishingVpnAppUid = uid;
+ }
+
+ /**
* Value indicating that link bandwidth is unspecified.
* @hide
*/
@@ -848,6 +874,10 @@
* bypass the VPN can do so iff the VPN app allows them to or if they are privileged. If this
* member is null, then the network is not restricted by app UID. If it's an empty list, then
* it means nobody can use it.
+ * As a special exception, the app managing this network (as identified by its UID stored in
+ * mEstablishingVpnAppUid) can always see this network. This is embodied by a special check in
+ * satisfiedByUids. That still does not mean the network necessarily <strong>applies</strong>
+ * to the app that manages it as determined by #appliesToUid.
* <p>
* Please note that in principle a single app can be associated with multiple UIDs because
* each app will have a different UID when it's run as a different (macro-)user. A single
@@ -935,9 +965,17 @@
/**
* Test whether the passed NetworkCapabilities satisfies the UIDs this capabilities require.
*
- * This is called on the NetworkCapabilities embedded in a request with the capabilities
- * of an available network.
- * nc is assumed nonnull.
+ * This method is called on the NetworkCapabilities embedded in a request with the
+ * capabilities of an available network. It checks whether all the UIDs from this listen
+ * (representing the UIDs that must have access to the network) are satisfied by the UIDs
+ * in the passed nc (representing the UIDs that this network is available to).
+ * <p>
+ * As a special exception, the UID that created the passed network (as represented by its
+ * mEstablishingVpnAppUid field) always satisfies a NetworkRequest requiring it (of LISTEN
+ * or REQUEST types alike), even if the network does not apply to it. That is so a VPN app
+ * can see its own network when it listens for it.
+ * <p>
+ * nc is assumed nonnull. Else, NPE.
* @see #appliesToUid
* @hide
*/
@@ -945,6 +983,7 @@
if (null == nc.mUids) return true; // The network satisfies everything.
if (null == mUids) return false; // Not everything allowed but requires everything
for (UidRange requiredRange : mUids) {
+ if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
if (!nc.appliesToUidRange(requiredRange)) {
return false;
}
@@ -1181,8 +1220,10 @@
String uids = (null != mUids ? " Uids: <" + mUids + ">" : "");
+ String establishingAppUid = " EstablishingAppUid: " + mEstablishingVpnAppUid;
+
return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength
- + uids + "]";
+ + uids + establishingAppUid + "]";
}
/**