From a12044215b1148826ea9a88d5d1102378b13922f Mon Sep 17 00:00:00 2001 From: Paul Jensen Date: Fri, 28 Aug 2015 11:58:50 -0400 Subject: Fix NOT_RESTRICTED network capability and enforce it. With this change: 1. NOT_RESTRICTED should be removed from NetworkRequests that bring up special restricted carrier networks (e.g. IMS, FOTA). 2. NetworkRequests without NOT_RESTRICTED require CONNECTIVITY_INTERNAL permission to register 3. Binding sockets to networks without NOT_RESTRICTED requires CONNECTIVITY_INTERNAL permission Bug:21637535 Change-Id: I5991d39facaa6b690e969fe15dcbeec52e918321 (cherry picked from commit 487ffe7d3d84bf65212158f7098e8a84b5b55e09) --- core/java/android/net/ConnectivityManager.java | 39 ++------------------ core/java/android/net/NetworkCapabilities.java | 42 ++++++++++++++++++++-- core/java/android/net/NetworkRequest.java | 8 ++++- .../java/android/os/INetworkManagementService.aidl | 11 +++++- .../com/android/server/ConnectivityService.java | 16 ++++++++- .../android/server/NetworkManagementService.java | 37 +++++++++++++++++-- 6 files changed, 109 insertions(+), 44 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 9194ca8d610d..7cde0050beb1 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -941,41 +941,6 @@ public class ConnectivityManager { return 1; } - /** - * Removes the NET_CAPABILITY_NOT_RESTRICTED capability from the given - * NetworkCapabilities object if all the capabilities it provides are - * typically provided by restricted networks. - * - * TODO: consider: - * - Moving to NetworkCapabilities - * - Renaming it to guessRestrictedCapability and make it set the - * restricted capability bit in addition to clearing it. - * @hide - */ - public static void maybeMarkCapabilitiesRestricted(NetworkCapabilities nc) { - for (int capability : nc.getCapabilities()) { - switch (capability) { - case NetworkCapabilities.NET_CAPABILITY_CBS: - case NetworkCapabilities.NET_CAPABILITY_DUN: - case NetworkCapabilities.NET_CAPABILITY_EIMS: - case NetworkCapabilities.NET_CAPABILITY_FOTA: - case NetworkCapabilities.NET_CAPABILITY_IA: - case NetworkCapabilities.NET_CAPABILITY_IMS: - case NetworkCapabilities.NET_CAPABILITY_RCS: - case NetworkCapabilities.NET_CAPABILITY_XCAP: - case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED: //there by default - continue; - default: - // At least one capability usually provided by unrestricted - // networks. Conclude that this network is unrestricted. - return; - } - } - // All the capabilities are typically provided by restricted networks. - // Conclude that this network is restricted. - nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - } - private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) { if (networkType == TYPE_MOBILE) { int cap = -1; @@ -998,14 +963,14 @@ public class ConnectivityManager { } NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addCapability(cap); - maybeMarkCapabilitiesRestricted(netCap); + netCap.maybeMarkCapabilitiesRestricted(); return netCap; } else if (networkType == TYPE_WIFI) { if ("p2p".equals(feature)) { NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P); - maybeMarkCapabilitiesRestricted(netCap); + netCap.maybeMarkCapabilitiesRestricted(); return netCap; } } diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 53f9fcdd93c0..2e22697cab64 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 { * @hide */ public NetworkCapabilities() { + mNetworkCapabilities = DEFAULT_CAPABILITIES; } public NetworkCapabilities(NetworkCapabilities nc) { @@ -65,8 +66,7 @@ public final class NetworkCapabilities implements Parcelable { * Represents the network's capabilities. If any are specified they will be satisfied * by any Network that matches all of them. */ - private long mNetworkCapabilities = (1 << NET_CAPABILITY_NOT_RESTRICTED) | - (1 << NET_CAPABILITY_TRUSTED) | (1 << NET_CAPABILITY_NOT_VPN); + private long mNetworkCapabilities; /** * Indicates this is a network that has the ability to reach the @@ -170,6 +170,28 @@ public final class NetworkCapabilities implements Parcelable { private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_NOT_VPN; + /** + * Capabilities that are set by default when the object is constructed. + */ + private static final long DEFAULT_CAPABILITIES = + (1 << NET_CAPABILITY_NOT_RESTRICTED) | + (1 << NET_CAPABILITY_TRUSTED) | + (1 << NET_CAPABILITY_NOT_VPN); + + /** + * Capabilities that suggest that a network is restricted. + * {@see #maybeMarkCapabilitiesRestricted}. + */ + private static final long RESTRICTED_CAPABILITIES = + (1 << NET_CAPABILITY_CBS) | + (1 << NET_CAPABILITY_DUN) | + (1 << NET_CAPABILITY_EIMS) | + (1 << NET_CAPABILITY_FOTA) | + (1 << NET_CAPABILITY_IA) | + (1 << NET_CAPABILITY_IMS) | + (1 << NET_CAPABILITY_RCS) | + (1 << NET_CAPABILITY_XCAP); + /** * Adds the given capability to this {@code NetworkCapability} instance. * Multiple capabilities may be applied sequentially. Note that when searching @@ -251,6 +273,22 @@ public final class NetworkCapabilities implements Parcelable { return (nc.mNetworkCapabilities == this.mNetworkCapabilities); } + /** + * Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are + * typically provided by restricted networks. + * + * TODO: consider: + * - Renaming it to guessRestrictedCapability and make it set the + * restricted capability bit in addition to clearing it. + * @hide + */ + public void maybeMarkCapabilitiesRestricted() { + // If all the capabilities are typically provided by restricted networks, conclude that this + // network is restricted. + if ((mNetworkCapabilities & ~(DEFAULT_CAPABILITIES | RESTRICTED_CAPABILITIES)) == 0) + removeCapability(NET_CAPABILITY_NOT_RESTRICTED); + } + /** * 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 diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 5a09b460b6a8..4c8e080b2dee 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -85,7 +85,13 @@ public class NetworkRequest implements Parcelable { * Build {@link NetworkRequest} give the current set of capabilities. */ public NetworkRequest build() { - return new NetworkRequest(mNetworkCapabilities, ConnectivityManager.TYPE_NONE, + // Make a copy of mNetworkCapabilities so we don't inadvertently remove NOT_RESTRICTED + // when later an unrestricted capability could be added to mNetworkCapabilities, in + // which case NOT_RESTRICTED should be returned to mNetworkCapabilities, which + // maybeMarkCapabilitiesRestricted() doesn't add back. + final NetworkCapabilities nc = new NetworkCapabilities(mNetworkCapabilities); + nc.maybeMarkCapabilitiesRestricted(); + return new NetworkRequest(nc, ConnectivityManager.TYPE_NONE, ConnectivityManager.REQUEST_ID_UNSET); } diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 16250c78af9a..21352982178c 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -367,8 +367,10 @@ interface INetworkManagementService /** * Setup a new physical network. + * @param permission null if no permissions required to access this network. PERMISSION_NETWORK + * or PERMISSION_SYSTEM to set respective permission. */ - void createPhysicalNetwork(int netId); + void createPhysicalNetwork(int netId, String permission); /** * Setup a new VPN. @@ -395,6 +397,13 @@ interface INetworkManagementService void setDefaultNetId(int netId); void clearDefaultNetId(); + /** + * Set permission for a network. + * @param permission null to clear permissions. PERMISSION_NETWORK or PERMISSION_SYSTEM to set + * permission. + */ + void setNetworkPermission(int netId, String permission); + void setPermission(String permission, in int[] uids); void clearPermission(in int[] uids); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b4a248fbec80..d7ff52700ae0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -37,6 +37,7 @@ import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; @@ -3707,6 +3708,16 @@ public class ConnectivityService extends IConnectivityManager.Stub { // TODO - turn this on in MR1 when we have more dogfooding time. // rematchAllNetworksAndRequests(); if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) { + if (networkAgent.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) != + networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) { + try { + mNetd.setNetworkPermission(networkAgent.network.netId, + networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) ? + null : NetworkManagementService.PERMISSION_SYSTEM); + } catch (RemoteException e) { + loge("Exception in setNetworkPermission: " + e); + } + } synchronized (networkAgent) { networkAgent.networkCapabilities = networkCapabilities; } @@ -4075,7 +4086,10 @@ public class ConnectivityService extends IConnectivityManager.Stub { (networkAgent.networkMisc == null || !networkAgent.networkMisc.allowBypass)); } else { - mNetd.createPhysicalNetwork(networkAgent.network.netId); + mNetd.createPhysicalNetwork(networkAgent.network.netId, + networkAgent.networkCapabilities.hasCapability( + NET_CAPABILITY_NOT_RESTRICTED) ? + null : NetworkManagementService.PERMISSION_SYSTEM); } } catch (Exception e) { loge("Error creating network " + networkAgent.network.netId + ": " diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 020c95182d21..3670a528dae2 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -120,6 +120,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub */ public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; + /** + * String to pass to netd to indicate that a network is only accessible + * to apps that have the CHANGE_NETWORK_STATE permission. + */ + public static final String PERMISSION_NETWORK = "NETWORK"; + + /** + * String to pass to netd to indicate that a network is only + * accessible to system apps and those with the CONNECTIVITY_INTERNAL + * permission. + */ + public static final String PERMISSION_SYSTEM = "SYSTEM"; + class NetdResponseCode { /* Keep in sync with system/netd/server/ResponseCode.h */ public static final int InterfaceListResult = 110; @@ -1962,11 +1975,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public void createPhysicalNetwork(int netId) { + public void createPhysicalNetwork(int netId, String permission) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - mConnector.execute("network", "create", netId); + if (permission != null) { + mConnector.execute("network", "create", netId, permission); + } else { + mConnector.execute("network", "create", netId); + } } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } @@ -2057,6 +2074,22 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + @Override + public void setNetworkPermission(int netId, String permission) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + try { + if (permission != null) { + mConnector.execute("network", "permission", "network", "set", permission, netId); + } else { + mConnector.execute("network", "permission", "network", "clear", netId); + } + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + + @Override public void setPermission(String permission, int[] uids) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); -- cgit v1.2.3-59-g8ed1b