Allow MANAGE_TEST_NETWORKS to register limited agents

This puts in force some restrictions against test networks,
and in exchange relaxes the restrictions around registering
a network agent that provides a test network.
Test networks can only ever have transport TEST, and have
only a few capabilities available to them.

This is useful in particular to test CTS. See aosp/1253423
for first, basic usage of this capability.

Test: IpSecManagerTunnelTest
Test: new CTS aosp/1253423
Bug: 139268426

Change-Id: Ibd162792a7ab02fcbb06130f21a825a386678c05
(cherry picked from commit 2c129e97cca2234ee6dd079a9c07df0c530d8b36)
This commit is contained in:
Chalard Jean
2020-03-25 10:33:55 +00:00
parent 4b1aada0aa
commit d22cb127b9
2 changed files with 50 additions and 2 deletions

View File

@@ -414,6 +414,20 @@ public final class NetworkCapabilities implements Parcelable {
| (1 << NET_CAPABILITY_FOREGROUND) | (1 << NET_CAPABILITY_FOREGROUND)
| (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY);
/**
* Capabilities that are allowed for test networks. This list must be set so that it is safe
* for an unprivileged user to create a network with these capabilities via shell. As such,
* it must never contain capabilities that are generally useful to the system, such as
* INTERNET, IMS, SUPL, etc.
*/
private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES =
(1 << NET_CAPABILITY_NOT_METERED)
| (1 << NET_CAPABILITY_NOT_RESTRICTED)
| (1 << NET_CAPABILITY_NOT_VPN)
| (1 << NET_CAPABILITY_NOT_ROAMING)
| (1 << NET_CAPABILITY_NOT_CONGESTED)
| (1 << NET_CAPABILITY_NOT_SUSPENDED);
/** /**
* Adds the given capability to this {@code NetworkCapability} instance. * Adds the given capability to this {@code NetworkCapability} instance.
* Note that when searching for a network to satisfy a request, all capabilities * Note that when searching for a network to satisfy a request, all capabilities
@@ -645,6 +659,21 @@ public final class NetworkCapabilities implements Parcelable {
} }
} }
/**
* Test networks have strong restrictions on what capabilities they can have. Enforce these
* restrictions.
* @hide
*/
public void restrictCapabilitesForTestNetwork() {
final long originalCapabilities = mNetworkCapabilities;
final NetworkSpecifier originalSpecifier = mNetworkSpecifier;
clearAll();
// Reset the transports to only contain TRANSPORT_TEST.
mTransportTypes = (1 << TRANSPORT_TEST);
mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES;
mNetworkSpecifier = originalSpecifier;
}
/** /**
* Representing the transport type. Apps should generally not care about transport. A * Representing the transport type. Apps should generally not care about transport. A
* request for a fast internet connection could be satisfied by a number of different * request for a fast internet connection could be satisfied by a number of different

View File

@@ -40,6 +40,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString; import static android.net.NetworkPolicyManager.uidRulesToString;
@@ -50,6 +51,7 @@ import static android.system.OsConstants.IPPROTO_UDP;
import static java.util.Map.Entry; import static java.util.Map.Entry;
import android.Manifest;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.AppOpsManager; import android.app.AppOpsManager;
@@ -2702,10 +2704,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
switch (msg.what) { switch (msg.what) {
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: { case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj; NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
if (networkCapabilities.hasConnectivityManagedCapability()) { if (networkCapabilities.hasConnectivityManagedCapability()) {
Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability."); Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
} }
if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
// Make sure the original object is not mutated. NetworkAgent normally
// makes a copy of the capabilities when sending the message through
// 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();
}
updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
break; break;
} }
@@ -5778,7 +5788,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities, LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
enforceNetworkFactoryPermission(); if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS);
// Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in
// 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();
} else {
enforceNetworkFactoryPermission();
}
LinkProperties lp = new LinkProperties(linkProperties); LinkProperties lp = new LinkProperties(linkProperties);
lp.ensureDirectlyConnectedRoutes(); lp.ensureDirectlyConnectedRoutes();