From fcf78b172731cd2b8f8c8e28eaedec60c44100f4 Mon Sep 17 00:00:00 2001 From: Di Lu Date: Thu, 11 Jan 2018 11:35:25 -0800 Subject: [PATCH 01/14] Add xfrm mark in IpSecConfig Bug: 63589600 Test: runtest frameworks-net Change-Id: I2d38d781b8b31d8bf39fd4e9a7e31509f15a9e16 --- .../server/IpSecServiceParameterizedTest.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 4fbb228e6e..cb0bdfc752 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -136,7 +136,12 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); + eq(spiResp.resourceId), + anyString(), + anyString(), + eq(TEST_SPI), + anyInt(), + anyInt()); // Verify quota and RefcountedResource objects cleaned up IpSecService.UserRecord userRecord = @@ -168,7 +173,12 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(spiResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); + eq(spiResp.resourceId), + anyString(), + anyString(), + eq(TEST_SPI), + anyInt(), + anyInt()); // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mSpiQuotaTracker.mCurrent); @@ -221,6 +231,8 @@ public class IpSecServiceParameterizedTest { anyString(), anyLong(), eq(TEST_SPI), + anyInt(), + anyInt(), eq(IpSecAlgorithm.AUTH_HMAC_SHA256), eq(AUTH_KEY), anyInt(), @@ -254,6 +266,8 @@ public class IpSecServiceParameterizedTest { anyString(), anyLong(), eq(TEST_SPI), + anyInt(), + anyInt(), eq(""), eq(new byte[] {}), eq(0), @@ -280,7 +294,12 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); + eq(createTransformResp.resourceId), + anyString(), + anyString(), + eq(TEST_SPI), + anyInt(), + anyInt()); // Verify quota and RefcountedResource objects cleaned up IpSecService.UserRecord userRecord = @@ -314,7 +333,12 @@ public class IpSecServiceParameterizedTest { verify(mMockNetd) .ipSecDeleteSecurityAssociation( - eq(createTransformResp.resourceId), anyString(), anyString(), eq(TEST_SPI)); + eq(createTransformResp.resourceId), + anyString(), + anyString(), + eq(TEST_SPI), + anyInt(), + anyInt()); // Verify quota and RefcountedResource objects cleaned up assertEquals(0, userRecord.mTransformQuotaTracker.mCurrent); From cbe99b35a0ddd174f9dd796b66b7aa8ff18962fc Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 23 Jan 2018 21:25:37 +0900 Subject: [PATCH 02/14] Pre-import to remove a conflict. Test: compiles and passes checkstyle Change-Id: I1ffdd88e6268fee0cf88992420ab21eb42928957 --- core/java/android/net/NetworkAgent.java | 2 +- core/java/android/net/NetworkCapabilities.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 2dacf8f460..51ef4a6209 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -17,6 +17,7 @@ package android.net; import android.content.Context; +import android.net.ConnectivityManager.PacketKeepalive; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -26,7 +27,6 @@ import android.util.Log; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; -import android.net.ConnectivityManager.PacketKeepalive; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index be85583a82..6bcaffd97a 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.net.ConnectivityManager.NetworkCallback; import android.os.Parcel; import android.os.Parcelable; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.BitUtils; From 753d9734d24f8ef4388d30e3bf20e8ac90514cd6 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 27 Dec 2017 14:23:31 +0900 Subject: [PATCH 03/14] Move VPN allowed UIDs into NetworkCapabilities. Test: runtest frameworks-net Test: also new specific tests for this new code Test: also tested with VPN app Test: also cts passing Change-Id: If0311bae2bf99dedac959febadecf4f92f3064b8 --- core/java/android/net/NetworkAgent.java | 6 + .../java/android/net/NetworkCapabilities.java | 200 ++++++++++++++++-- .../android/net/NetworkCapabilitiesTest.java | 83 ++++++++ 3 files changed, 268 insertions(+), 21 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 51ef4a6209..4c49bc9f28 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -29,6 +29,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import java.util.ArrayList; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -224,6 +225,11 @@ public abstract class NetworkAgent extends Handler { Context.CONNECTIVITY_SERVICE); netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc); + + final Set uids = nc.getUids(); + if (null != uids) { + addUidRanges(uids.toArray(new UidRange[uids.size()])); + } } @Override diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 6bcaffd97a..d0f6f9bf77 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.net.ConnectivityManager.NetworkCallback; import android.os.Parcel; import android.os.Parcelable; +import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; @@ -29,6 +30,7 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Objects; +import java.util.Set; import java.util.StringJoiner; /** @@ -64,6 +66,7 @@ public final class NetworkCapabilities implements Parcelable { mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mNetworkSpecifier = nc.mNetworkSpecifier; mSignalStrength = nc.mSignalStrength; + mUids = nc.mUids; } } @@ -77,6 +80,7 @@ public final class NetworkCapabilities implements Parcelable { mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; mNetworkSpecifier = null; mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; + mUids = null; } /** @@ -836,6 +840,150 @@ public final class NetworkCapabilities implements Parcelable { return this.mSignalStrength == nc.mSignalStrength; } + /** + * List of UIDs this network applies to. No restriction if null. + *

+ * This is typically (and at this time, only) used by VPN. This network is only available to + * the UIDs in this list, and it is their default network. Apps in this list that wish to + * 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. + *

+ * 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 + * macro user can only have a single active VPN app at any given time however. + *

+ * Also please be aware this class does not try to enforce any normalization on this. Callers + * can only alter the UIDs by setting them wholesale : this class does not provide any utility + * to add or remove individual UIDs or ranges. If callers have any normalization needs on + * their own (like requiring sortedness or no overlap) they need to enforce it + * themselves. Some of the internal methods also assume this is normalized as in no adjacent + * or overlapping ranges are present. + * + * @hide + */ + private Set mUids = null; + + /** + * Set the list of UIDs this network applies to. + * This makes a copy of the set so that callers can't modify it after the call. + * @hide + */ + public NetworkCapabilities setUids(Set uids) { + if (null == uids) { + mUids = null; + } else { + mUids = new ArraySet<>(uids); + } + return this; + } + + /** + * Get the list of UIDs this network applies to. + * This returns a copy of the set so that callers can't modify the original object. + * @hide + */ + public Set getUids() { + return null == mUids ? null : new ArraySet<>(mUids); + } + + /** + * Test whether this network applies to this UID. + * @hide + */ + public boolean appliesToUid(int uid) { + if (null == mUids) return true; + for (UidRange range : mUids) { + if (range.contains(uid)) { + return true; + } + } + return false; + } + + /** + * Tests if the set of UIDs that this network applies to is the same of the passed set of UIDs. + *

+ * This test only checks whether equal range objects are in both sets. It will + * return false if the ranges are not exactly the same, even if the covered UIDs + * are for an equivalent result. + *

+ * Note that this method is not very optimized, which is fine as long as it's not used very + * often. + *

+ * nc is assumed nonnull. + * + * @hide + */ + @VisibleForTesting + public boolean equalsUids(NetworkCapabilities nc) { + Set comparedUids = nc.mUids; + if (null == comparedUids) return null == mUids; + if (null == mUids) return false; + // Make a copy so it can be mutated to check that all ranges in mUids + // also are in uids. + final Set uids = new ArraySet<>(mUids); + for (UidRange range : comparedUids) { + if (!uids.contains(range)) { + return false; + } + uids.remove(range); + } + return uids.isEmpty(); + } + + /** + * 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. + * @see #appliesToUid + * @hide + */ + public boolean satisfiedByUids(NetworkCapabilities nc) { + 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 (!nc.appliesToUidRange(requiredRange)) { + return false; + } + } + return true; + } + + /** + * Returns whether this network applies to the passed ranges. + * This assumes that to apply, the passed range has to be entirely contained + * within one of the ranges this network applies to. If the ranges are not normalized, + * this method may return false even though all required UIDs are covered because no + * single range contained them all. + * @hide + */ + @VisibleForTesting + public boolean appliesToUidRange(UidRange requiredRange) { + if (null == mUids) return true; + for (UidRange uidRange : mUids) { + if (uidRange.containsRange(requiredRange)) { + return true; + } + } + return false; + } + + /** + * Combine the UIDs this network currently applies to with the UIDs the passed + * NetworkCapabilities apply to. + * nc is assumed nonnull. + */ + private void combineUids(NetworkCapabilities nc) { + if (null == nc.mUids || null == mUids) { + mUids = null; + return; + } + mUids.addAll(nc.mUids); + } + /** * Combine a set of Capabilities to this one. Useful for coming up with the complete set * @hide @@ -846,6 +994,7 @@ public final class NetworkCapabilities implements Parcelable { combineLinkBandwidths(nc); combineSpecifiers(nc); combineSignalStrength(nc); + combineUids(nc); } /** @@ -858,12 +1007,13 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) { - return (nc != null && - satisfiedByNetCapabilities(nc, onlyImmutable) && - satisfiedByTransportTypes(nc) && - (onlyImmutable || satisfiedByLinkBandwidths(nc)) && - satisfiedBySpecifier(nc) && - (onlyImmutable || satisfiedBySignalStrength(nc))); + return (nc != null + && satisfiedByNetCapabilities(nc, onlyImmutable) + && satisfiedByTransportTypes(nc) + && (onlyImmutable || satisfiedByLinkBandwidths(nc)) + && satisfiedBySpecifier(nc) + && (onlyImmutable || satisfiedBySignalStrength(nc)) + && (onlyImmutable || satisfiedByUids(nc))); } /** @@ -946,24 +1096,26 @@ public final class NetworkCapabilities implements Parcelable { @Override public boolean equals(Object obj) { if (obj == null || (obj instanceof NetworkCapabilities == false)) return false; - NetworkCapabilities that = (NetworkCapabilities)obj; - return (equalsNetCapabilities(that) && - equalsTransportTypes(that) && - equalsLinkBandwidths(that) && - equalsSignalStrength(that) && - equalsSpecifier(that)); + NetworkCapabilities that = (NetworkCapabilities) obj; + return (equalsNetCapabilities(that) + && equalsTransportTypes(that) + && equalsLinkBandwidths(that) + && equalsSignalStrength(that) + && equalsSpecifier(that) + && equalsUids(that)); } @Override public int hashCode() { - return ((int)(mNetworkCapabilities & 0xFFFFFFFF) + - ((int)(mNetworkCapabilities >> 32) * 3) + - ((int)(mTransportTypes & 0xFFFFFFFF) * 5) + - ((int)(mTransportTypes >> 32) * 7) + - (mLinkUpBandwidthKbps * 11) + - (mLinkDownBandwidthKbps * 13) + - Objects.hashCode(mNetworkSpecifier) * 17 + - (mSignalStrength * 19)); + return ((int) (mNetworkCapabilities & 0xFFFFFFFF) + + ((int) (mNetworkCapabilities >> 32) * 3) + + ((int) (mTransportTypes & 0xFFFFFFFF) * 5) + + ((int) (mTransportTypes >> 32) * 7) + + (mLinkUpBandwidthKbps * 11) + + (mLinkDownBandwidthKbps * 13) + + Objects.hashCode(mNetworkSpecifier) * 17 + + (mSignalStrength * 19) + + Objects.hashCode(mUids) * 23); } @Override @@ -978,6 +1130,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeInt(mLinkDownBandwidthKbps); dest.writeParcelable((Parcelable) mNetworkSpecifier, flags); dest.writeInt(mSignalStrength); + dest.writeArraySet(new ArraySet<>(mUids)); } public static final Creator CREATOR = @@ -992,6 +1145,8 @@ public final class NetworkCapabilities implements Parcelable { netCap.mLinkDownBandwidthKbps = in.readInt(); netCap.mNetworkSpecifier = in.readParcelable(null); netCap.mSignalStrength = in.readInt(); + netCap.mUids = (ArraySet) in.readArraySet( + null /* ClassLoader, null for default */); return netCap; } @Override @@ -1024,7 +1179,10 @@ public final class NetworkCapabilities implements Parcelable { String signalStrength = (hasSignalStrength() ? " SignalStrength: " + mSignalStrength : ""); - return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]"; + String uids = (null != mUids ? " Uids: <" + mUids + ">" : ""); + + return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + + uids + "]"; } /** diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java index e6170cb42c..4c6a64464b 100644 --- a/tests/net/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java @@ -34,12 +34,15 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import android.os.Parcel; import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.SmallTest; +import android.util.ArraySet; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Set; @RunWith(AndroidJUnit4.class) @SmallTest @@ -189,4 +192,84 @@ public class NetworkCapabilitiesTest { assertEquals(20, NetworkCapabilities .maxBandwidth(10, 20)); } + + @Test + public void testSetUids() { + final NetworkCapabilities netCap = new NetworkCapabilities(); + final Set uids = new ArraySet<>(); + uids.add(new UidRange(50, 100)); + uids.add(new UidRange(3000, 4000)); + netCap.setUids(uids); + assertTrue(netCap.appliesToUid(50)); + assertTrue(netCap.appliesToUid(80)); + assertTrue(netCap.appliesToUid(100)); + assertTrue(netCap.appliesToUid(3000)); + assertTrue(netCap.appliesToUid(3001)); + assertFalse(netCap.appliesToUid(10)); + assertFalse(netCap.appliesToUid(25)); + assertFalse(netCap.appliesToUid(49)); + assertFalse(netCap.appliesToUid(101)); + assertFalse(netCap.appliesToUid(2000)); + assertFalse(netCap.appliesToUid(100000)); + + assertTrue(netCap.appliesToUidRange(new UidRange(50, 100))); + assertTrue(netCap.appliesToUidRange(new UidRange(70, 72))); + assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912))); + assertFalse(netCap.appliesToUidRange(new UidRange(1, 100))); + assertFalse(netCap.appliesToUidRange(new UidRange(49, 100))); + assertFalse(netCap.appliesToUidRange(new UidRange(1, 10))); + assertFalse(netCap.appliesToUidRange(new UidRange(60, 101))); + assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400))); + + NetworkCapabilities netCap2 = new NetworkCapabilities(); + assertFalse(netCap2.satisfiedByUids(netCap)); + assertFalse(netCap2.equalsUids(netCap)); + netCap2.setUids(uids); + assertTrue(netCap2.satisfiedByUids(netCap)); + assertTrue(netCap.equalsUids(netCap2)); + assertTrue(netCap2.equalsUids(netCap)); + + uids.add(new UidRange(600, 700)); + netCap2.setUids(uids); + assertFalse(netCap2.satisfiedByUids(netCap)); + assertFalse(netCap.appliesToUid(650)); + assertTrue(netCap2.appliesToUid(650)); + netCap.combineCapabilities(netCap2); + assertTrue(netCap2.satisfiedByUids(netCap)); + assertTrue(netCap.appliesToUid(650)); + assertFalse(netCap.appliesToUid(500)); + + assertFalse(new NetworkCapabilities().satisfiedByUids(netCap)); + netCap.combineCapabilities(new NetworkCapabilities()); + assertTrue(netCap.appliesToUid(500)); + assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000))); + assertFalse(netCap2.appliesToUid(500)); + assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000))); + assertTrue(new NetworkCapabilities().satisfiedByUids(netCap)); + } + + @Test + public void testParcelNetworkCapabilities() { + final Set uids = new ArraySet<>(); + uids.add(new UidRange(50, 100)); + uids.add(new UidRange(3000, 4000)); + final NetworkCapabilities netCap = new NetworkCapabilities() + .addCapability(NET_CAPABILITY_INTERNET) + .setUids(uids) + .addCapability(NET_CAPABILITY_EIMS) + .addCapability(NET_CAPABILITY_NOT_METERED); + assertEqualsThroughMarshalling(netCap); + } + + private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) { + Parcel p = Parcel.obtain(); + netCap.writeToParcel(p, /* flags */ 0); + p.setDataPosition(0); + byte[] marshalledData = p.marshall(); + + p = Parcel.obtain(); + p.unmarshall(marshalledData, 0, marshalledData.length); + p.setDataPosition(0); + assertEquals(NetworkCapabilities.CREATOR.createFromParcel(p), netCap); + } } From b2a49917814dd0262dd841c68d044e7088309f34 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 16 Jan 2018 18:43:05 +0900 Subject: [PATCH 04/14] Remove UID_RANGES_ADDED and REMOVED. Test: runtest frameworks-net Test: also tested with VPN app Test: also cts passing Change-Id: I3530030996daeba05a8f2fffc5c6e21ed62e3f40 --- core/java/android/net/NetworkAgent.java | 36 ------------- .../android/server/ConnectivityService.java | 52 ++++++++++++------- 2 files changed, 34 insertions(+), 54 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 4c49bc9f28..52a2354840 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -29,7 +29,6 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import java.util.ArrayList; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -101,20 +100,6 @@ public abstract class NetworkAgent extends Handler { */ public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; - /** - * Sent by the NetworkAgent to ConnectivityService to add new UID ranges - * to be forced into this Network. For VPNs only. - * obj = UidRange[] to forward - */ - public static final int EVENT_UID_RANGES_ADDED = BASE + 5; - - /** - * Sent by the NetworkAgent to ConnectivityService to remove UID ranges - * from being forced into this Network. For VPNs only. - * obj = UidRange[] to stop forwarding - */ - public static final int EVENT_UID_RANGES_REMOVED = BASE + 6; - /** * Sent by ConnectivityService to the NetworkAgent to inform the agent of the * networks status - whether we could use the network or could not, due to @@ -225,11 +210,6 @@ public abstract class NetworkAgent extends Handler { Context.CONNECTIVITY_SERVICE); netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc); - - final Set uids = nc.getUids(); - if (null != uids) { - addUidRanges(uids.toArray(new UidRange[uids.size()])); - } } @Override @@ -395,22 +375,6 @@ public abstract class NetworkAgent extends Handler { queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score)); } - /** - * Called by the VPN code when it wants to add ranges of UIDs to be routed - * through the VPN network. - */ - public void addUidRanges(UidRange[] ranges) { - queueOrSendMessage(EVENT_UID_RANGES_ADDED, ranges); - } - - /** - * Called by the VPN code when it wants to remove ranges of UIDs from being routed - * through the VPN network. - */ - public void removeUidRanges(UidRange[] ranges) { - queueOrSendMessage(EVENT_UID_RANGES_REMOVED, ranges); - } - /** * Called by the bearer to indicate this network was manually selected by the user. * This should be called before the NetworkInfo is marked CONNECTED so that this diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ea6bc175d6..216e19b10b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -105,6 +105,7 @@ import android.security.Credentials; import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArraySet; import android.util.LocalLog; import android.util.LocalLog.ReadOnlyLocalLog; import android.util.Log; @@ -174,6 +175,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -2050,24 +2052,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (score != null) updateNetworkScore(nai, score.intValue()); break; } - case NetworkAgent.EVENT_UID_RANGES_ADDED: { - try { - mNetd.addVpnUidRanges(nai.network.netId, (UidRange[])msg.obj); - } catch (Exception e) { - // Never crash! - loge("Exception in addVpnUidRanges: " + e); - } - break; - } - case NetworkAgent.EVENT_UID_RANGES_REMOVED: { - try { - mNetd.removeVpnUidRanges(nai.network.netId, (UidRange[])msg.obj); - } catch (Exception e) { - // Never crash! - loge("Exception in removeVpnUidRanges: " + e); - } - break; - } case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: { if (nai.everConnected && !nai.networkMisc.explicitlySelected) { loge("ERROR: already-connected network explicitly selected."); @@ -4514,6 +4498,7 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkInfo networkInfo = na.networkInfo; na.networkInfo = null; updateNetworkInfo(na, networkInfo); + updateUids(na, null, na.networkCapabilities); } private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties oldLp) { @@ -4762,6 +4747,8 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.networkCapabilities = newNc; } + updateUids(nai, prevNc, newNc); + if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) { // If the requestable capabilities haven't changed, and the score hasn't changed, then // the change we're processing can't affect any requests, it can only affect the listens @@ -4798,6 +4785,34 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, + NetworkCapabilities newNc) { + Set prevRanges = null == prevNc ? null : prevNc.getUids(); + Set newRanges = null == newNc ? null : newNc.getUids(); + if (null == prevRanges) prevRanges = new ArraySet<>(); + if (null == newRanges) newRanges = new ArraySet<>(); + final Set prevRangesCopy = new ArraySet<>(prevRanges); + + prevRanges.removeAll(newRanges); + newRanges.removeAll(prevRangesCopy); + + try { + if (!newRanges.isEmpty()) { + final UidRange[] addedRangesArray = new UidRange[newRanges.size()]; + newRanges.toArray(addedRangesArray); + mNetd.addVpnUidRanges(nai.network.netId, addedRangesArray); + } + if (!prevRanges.isEmpty()) { + final UidRange[] removedRangesArray = new UidRange[prevRanges.size()]; + prevRanges.toArray(removedRangesArray); + mNetd.removeVpnUidRanges(nai.network.netId, removedRangesArray); + } + } catch (Exception e) { + // Never crash! + loge("Exception in updateUids: " + e); + } + } + public void handleUpdateLinkProperties(NetworkAgentInfo nai, LinkProperties newLp) { if (mNetworkForNetId.get(nai.network.netId) != nai) { // Ignore updates for disconnected networks @@ -5413,6 +5428,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } } + updateUids(networkAgent, networkAgent.networkCapabilities, null); } } else if ((oldInfo != null && oldInfo.getState() == NetworkInfo.State.SUSPENDED) || state == NetworkInfo.State.SUSPENDED) { From 92a116d264551e84f6f358d31d960f7720f8c63e Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 12 Jan 2018 17:22:49 +0900 Subject: [PATCH 05/14] Add a test for new UID checking code. Test: manual, this is a new test and it passes Change-Id: I69a39039647ec05f970700e36c5f1e1e6e110f4a --- .../server/ConnectivityServiceTest.java | 89 ++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 70cacb3af0..4733deba6d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -44,6 +44,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; @@ -101,6 +102,7 @@ import android.net.NetworkSpecifier; import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.StringNetworkSpecifier; +import android.net.UidRange; import android.net.metrics.IpConnectivityLog; import android.net.util.MultinetworkPolicyTracker; import android.os.ConditionVariable; @@ -360,7 +362,7 @@ public class ConnectivityServiceTest { MockNetworkAgent(int transport, LinkProperties linkProperties) { final int type = transportToLegacyType(transport); - final String typeName = ConnectivityManager.getNetworkTypeName(type); + final String typeName = ConnectivityManager.getNetworkTypeName(transport); mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); mNetworkCapabilities = new NetworkCapabilities(); mNetworkCapabilities.addTransportType(transport); @@ -377,6 +379,9 @@ public class ConnectivityServiceTest { case TRANSPORT_WIFI_AWARE: mScore = 20; break; + case TRANSPORT_VPN: + mScore = 0; + break; default: throw new UnsupportedOperationException("unimplemented network type"); } @@ -438,6 +443,11 @@ public class ConnectivityServiceTest { mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); } + public void setUids(Set uids) { + mNetworkCapabilities.setUids(uids); + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + } + public void setSignalStrength(int signalStrength) { mNetworkCapabilities.setSignalStrength(signalStrength); mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); @@ -1463,6 +1473,11 @@ public class ConnectivityServiceTest { return nc; } + void expectCapabilitiesLike(Predicate fn, MockNetworkAgent agent) { + CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent); + assertTrue(fn.test((NetworkCapabilities) cbi.arg)); + } + void assertNoCallback() { waitForIdle(); CallbackInfo c = mCallbacks.peek(); @@ -3625,4 +3640,76 @@ public class ConnectivityServiceTest { return; } } + + @Test + public void testVpnNetworkActive() { + final int uid = Process.myUid(); + + final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback(); + final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback(); + final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); + final NetworkRequest genericRequest = new NetworkRequest.Builder().build(); + final NetworkRequest wifiRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_WIFI).build(); + final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() + .addTransportType(TRANSPORT_VPN).build(); + mCm.registerNetworkCallback(genericRequest, genericNetworkCallback); + mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback); + mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); + + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false); + + genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + vpnNetworkCallback.assertNoCallback(); + + // TODO : check callbacks agree with the return value of mCm.getActiveNetwork(). + // Right now this is not possible because establish() is not adequately instrumented + // in this test. + + final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN); + final ArraySet ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); + vpnNetworkAgent.setUids(ranges); + vpnNetworkAgent.connect(false); + + genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); + wifiNetworkCallback.assertNoCallback(); + vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); + + genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent); + vpnNetworkCallback.expectCapabilitiesLike( + nc -> nc.appliesToUid(uid) && !nc.appliesToUid(uid + 1), vpnNetworkAgent); + + ranges.clear(); + vpnNetworkAgent.setUids(ranges); + + genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); + wifiNetworkCallback.assertNoCallback(); + vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); + + ranges.add(new UidRange(uid, uid)); + vpnNetworkAgent.setUids(ranges); + + genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); + wifiNetworkCallback.assertNoCallback(); + vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent); + + mWiFiNetworkAgent.disconnect(); + + genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); + wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); + vpnNetworkCallback.assertNoCallback(); + + vpnNetworkAgent.disconnect(); + + genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); + wifiNetworkCallback.assertNoCallback(); + vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent); + + mCm.unregisterNetworkCallback(genericNetworkCallback); + mCm.unregisterNetworkCallback(wifiNetworkCallback); + mCm.unregisterNetworkCallback(vpnNetworkCallback); + } } From b399bf16d1bd5b34a47ec137e78b9fa3b2c94d28 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 17 Jan 2018 15:10:05 +0900 Subject: [PATCH 06/14] 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 --- .../java/android/net/NetworkCapabilities.java | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index d0f6f9bf77..6e80f024ee 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -49,6 +49,7 @@ import java.util.StringJoiner; */ public final class NetworkCapabilities implements Parcelable { private static final String TAG = "NetworkCapabilities"; + private static final int INVALID_UID = -1; /** * @hide @@ -67,6 +68,7 @@ public final class NetworkCapabilities implements Parcelable { mNetworkSpecifier = nc.mNetworkSpecifier; mSignalStrength = nc.mSignalStrength; mUids = nc.mUids; + mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid; } } @@ -81,6 +83,7 @@ public final class NetworkCapabilities implements Parcelable { mNetworkSpecifier = null; mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; mUids = null; + mEstablishingVpnAppUid = INVALID_UID; } /** @@ -622,6 +625,29 @@ public final class NetworkCapabilities implements Parcelable { return (nc.mTransportTypes == this.mTransportTypes); } + /** + * 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 @@ public final class NetworkCapabilities implements Parcelable { * 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 applies + * to the app that manages it as determined by #appliesToUid. *

* 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 @@ public final class NetworkCapabilities implements Parcelable { /** * 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). + *

+ * 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. + *

+ * nc is assumed nonnull. Else, NPE. * @see #appliesToUid * @hide */ @@ -945,6 +983,7 @@ public final class NetworkCapabilities implements Parcelable { 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 @@ public final class NetworkCapabilities implements Parcelable { String uids = (null != mUids ? " Uids: <" + mUids + ">" : ""); + String establishingAppUid = " EstablishingAppUid: " + mEstablishingVpnAppUid; + return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength - + uids + "]"; + + uids + establishingAppUid + "]"; } /** From 3a6b34c989442d2a460b363613c760f4ad137d47 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 19 Jan 2018 17:00:47 +0900 Subject: [PATCH 07/14] Move constants into a new file. Also audit all constants, make some private, annotate some with @VisibleForTesting. Test: runtest framework && cts Change-Id: Iaf5ea7abd36fd8d544dcc84654f6cb529196d654 --- .../server/connectivity/KeepalivePacketData.java | 10 +++++----- .../server/connectivity/NetworkAgentInfo.java | 12 ++---------- .../server/connectivity/NetworkDiagnostics.java | 11 +++++------ 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/KeepalivePacketData.java b/services/core/java/com/android/server/connectivity/KeepalivePacketData.java index 2ccfdd1f31..f6b73b7d69 100644 --- a/services/core/java/com/android/server/connectivity/KeepalivePacketData.java +++ b/services/core/java/com/android/server/connectivity/KeepalivePacketData.java @@ -16,6 +16,9 @@ package com.android.server.connectivity; +import static android.net.util.NetworkConstants.IPV4_HEADER_MIN_LEN; +import static android.net.util.NetworkConstants.UDP_HEADER_LEN; + import android.system.OsConstants; import android.net.ConnectivityManager; import android.net.NetworkUtils; @@ -57,9 +60,6 @@ public class KeepalivePacketData { /** Packet data. A raw byte string of packet data, not including the link-layer header. */ public final byte[] data; - private static final int IPV4_HEADER_LENGTH = 20; - private static final int UDP_HEADER_LENGTH = 8; - protected KeepalivePacketData(InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException { this.srcAddress = srcAddress; @@ -111,7 +111,7 @@ public class KeepalivePacketData { throw new InvalidPacketException(ERROR_INVALID_PORT); } - int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; + int length = IPV4_HEADER_MIN_LEN + UDP_HEADER_LEN + 1; ByteBuffer buf = ByteBuffer.allocate(length); buf.order(ByteOrder.BIG_ENDIAN); buf.putShort((short) 0x4500); // IP version and TOS @@ -130,7 +130,7 @@ public class KeepalivePacketData { buf.putShort((short) 0); // UDP checksum buf.put((byte) 0xff); // NAT-T keepalive buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); - buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); + buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_MIN_LEN)); return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index a4d7242086..85b70ca0ff 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -223,14 +223,6 @@ public class NetworkAgentInfo implements Comparable { // This represents the last score received from the NetworkAgent. private int currentScore; - // Penalty applied to scores of Networks that have not been validated. - private static final int UNVALIDATED_SCORE_PENALTY = 40; - - // Score for explicitly connected network. - // - // This ensures that a) the explicitly selected network is never trumped by anything else, and - // b) the explicitly selected network is never torn down. - private static final int MAXIMUM_NETWORK_SCORE = 100; // The list of NetworkRequests being satisfied by this Network. private final SparseArray mNetworkRequests = new SparseArray<>(); @@ -428,12 +420,12 @@ public class NetworkAgentInfo implements Comparable { // down an explicitly selected network before the user gets a chance to prefer it when // a higher-scoring network (e.g., Ethernet) is available. if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) { - return MAXIMUM_NETWORK_SCORE; + return ConnectivityConstants.MAXIMUM_NETWORK_SCORE; } int score = currentScore; if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty()) { - score -= UNVALIDATED_SCORE_PENALTY; + score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } if (score < 0) score = 0; return score; diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java index 85d1d1ef1d..c471f0caa3 100644 --- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java +++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java @@ -24,6 +24,7 @@ import android.net.Network; import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.TrafficStats; +import android.net.util.NetworkConstants; import android.os.SystemClock; import android.system.ErrnoException; import android.system.Os; @@ -421,8 +422,6 @@ public class NetworkDiagnostics { private class IcmpCheck extends SimpleSocketCheck implements Runnable { private static final int TIMEOUT_SEND = 100; private static final int TIMEOUT_RECV = 300; - private static final int ICMPV4_ECHO_REQUEST = 8; - private static final int ICMPV6_ECHO_REQUEST = 128; private static final int PACKET_BUFSIZE = 512; private final int mProtocol; private final int mIcmpType; @@ -432,11 +431,11 @@ public class NetworkDiagnostics { if (mAddressFamily == AF_INET6) { mProtocol = IPPROTO_ICMPV6; - mIcmpType = ICMPV6_ECHO_REQUEST; + mIcmpType = NetworkConstants.ICMPV6_ECHO_REQUEST_TYPE; mMeasurement.description = "ICMPv6"; } else { mProtocol = IPPROTO_ICMP; - mIcmpType = ICMPV4_ECHO_REQUEST; + mIcmpType = NetworkConstants.ICMPV4_ECHO_REQUEST_TYPE; mMeasurement.description = "ICMPv4"; } @@ -504,7 +503,6 @@ public class NetworkDiagnostics { private class DnsUdpCheck extends SimpleSocketCheck implements Runnable { private static final int TIMEOUT_SEND = 100; private static final int TIMEOUT_RECV = 500; - private static final int DNS_SERVER_PORT = 53; private static final int RR_TYPE_A = 1; private static final int RR_TYPE_AAAA = 28; private static final int PACKET_BUFSIZE = 512; @@ -546,7 +544,8 @@ public class NetworkDiagnostics { } try { - setupSocket(SOCK_DGRAM, IPPROTO_UDP, TIMEOUT_SEND, TIMEOUT_RECV, DNS_SERVER_PORT); + setupSocket(SOCK_DGRAM, IPPROTO_UDP, TIMEOUT_SEND, TIMEOUT_RECV, + NetworkConstants.DNS_SERVER_PORT); } catch (ErrnoException | IOException e) { mMeasurement.recordFailure(e.toString()); return; From fd3a4ae0fe7645d24d77d2617eedc227dc6a4bb9 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 10 Jan 2018 21:19:32 +0900 Subject: [PATCH 08/14] Let network requests see VPNs. Test: runtest frameworks-net Test: also tested with VPN app Test: also cts passing Change-Id: I3b16caad7787c3c1f2921ca1583815c89efbadc5 --- .../java/android/net/NetworkCapabilities.java | 11 +++++ .../android/server/ConnectivityService.java | 40 ++++++++++++++++--- .../server/ConnectivityServiceTest.java | 4 +- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 6e80f024ee..31516fd457 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -894,6 +894,17 @@ public final class NetworkCapabilities implements Parcelable { */ private Set mUids = null; + /** + * Convenience method to set the UIDs this network applies to to a single UID. + * @hide + */ + public NetworkCapabilities setSingleUid(int uid) { + final ArraySet identity = new ArraySet<>(1); + identity.add(new UidRange(uid, uid)); + setUids(identity); + return this; + } + /** * Set the list of UIDs this network applies to. * This makes a copy of the set so that callers can't modify it after the call. diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 216e19b10b..6dbf53850e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -30,6 +30,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_VPN; @@ -711,12 +712,12 @@ public class ConnectivityService extends IConnectivityManager.Stub mSystemProperties = getSystemProperties(); mMetricsLog = logger; - mDefaultRequest = createInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); + mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest, new Binder()); mNetworkRequests.put(mDefaultRequest, defaultNRI); mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI); - mDefaultMobileDataRequest = createInternetRequestForTransport( + mDefaultMobileDataRequest = createDefaultInternetRequestForTransport( NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST); mHandlerThread = new HandlerThread("ConnectivityServiceThread"); @@ -881,7 +882,7 @@ public class ConnectivityService extends IConnectivityManager.Stub deps); } - private NetworkRequest createInternetRequestForTransport( + private NetworkRequest createDefaultInternetRequestForTransport( int transportType, NetworkRequest.Type type) { NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); @@ -1259,7 +1260,11 @@ public class ConnectivityService extends IConnectivityManager.Stub for (Network network : networks) { nai = getNetworkAgentInfoForNetwork(network); nc = getNetworkCapabilitiesInternal(nai); + // nc is a copy of the capabilities in nai, so it's fine to mutate it + // TODO : don't remove the UIDs when communicating with processes + // that have the NETWORK_SETTINGS permission. if (nc != null) { + nc.setSingleUid(userId); result.put(network, nc); } } @@ -4190,6 +4195,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the system default network. if (type == NetworkRequest.Type.TRACK_DEFAULT) { networkCapabilities = new NetworkCapabilities(mDefaultRequest.networkCapabilities); + networkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN); enforceAccessPermission(); } else { networkCapabilities = new NetworkCapabilities(networkCapabilities); @@ -4200,6 +4206,13 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceMeteredApnPolicy(networkCapabilities); } ensureRequestableCapabilities(networkCapabilities); + // Set the UID range for this request to the single UID of the requester. + // This will overwrite any allowed UIDs in the requested capabilities. Though there + // are no visible methods to set the UIDs, an app could use reflection to try and get + // networks for other apps so it's essential that the UIDs are overwritten. + // TODO : don't forcefully set the UID when communicating with processes + // that have the NETWORK_SETTINGS permission. + networkCapabilities.setSingleUid(Binder.getCallingUid()); if (timeoutMs < 0) { throw new IllegalArgumentException("Bad timeout specified"); @@ -4273,6 +4286,9 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceMeteredApnPolicy(networkCapabilities); ensureRequestableCapabilities(networkCapabilities); ensureValidNetworkSpecifier(networkCapabilities); + // TODO : don't forcefully set the UID when communicating with processes + // that have the NETWORK_SETTINGS permission. + networkCapabilities.setSingleUid(Binder.getCallingUid()); NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.REQUEST); @@ -4326,6 +4342,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); + // TODO : don't forcefully set the UIDs when communicating with processes + // that have the NETWORK_SETTINGS permission. + nc.setSingleUid(Binder.getCallingUid()); if (!ConnectivityManager.checkChangePermission(mContext)) { // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get @@ -4354,8 +4373,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } ensureValidNetworkSpecifier(networkCapabilities); - NetworkRequest networkRequest = new NetworkRequest( - new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId(), + final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); + // TODO : don't forcefully set the UIDs when communicating with processes + // that have the NETWORK_SETTINGS permission. + nc.setSingleUid(Binder.getCallingUid()); + + NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation); if (VDBG) log("pendingListenForNetwork for " + nri); @@ -4904,7 +4927,12 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case ConnectivityManager.CALLBACK_CAP_CHANGED: { - putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); + final NetworkCapabilities nc = + new NetworkCapabilities(networkAgent.networkCapabilities); + // TODO : don't remove the UIDs when communicating with processes + // that have the NETWORK_SETTINGS permission. + nc.setSingleUid(nri.mUid); + putParcelable(bundle, nc); break; } case ConnectivityManager.CALLBACK_IP_CHANGED: { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4733deba6d..6e643a3dae 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -128,11 +128,13 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.WakeupMessage; import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.internal.util.test.FakeSettingsProvider; +import com.android.server.connectivity.ConnectivityConstants; import com.android.server.connectivity.DefaultNetworkMetrics; import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkMonitor; +import com.android.server.connectivity.Vpn; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; @@ -380,7 +382,7 @@ public class ConnectivityServiceTest { mScore = 20; break; case TRANSPORT_VPN: - mScore = 0; + mScore = ConnectivityConstants.VPN_DEFAULT_SCORE; break; default: throw new UnsupportedOperationException("unimplemented network type"); From 145b425facf02f5494df7c749f12f46d35d44eb6 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 18 Jan 2018 18:31:45 -0800 Subject: [PATCH 09/14] Add TunnelInterface API and KernelResourceRecords This change adds one KernelResourceRecord type (TunnelInterfaceRecord), and adds methods for the creation of TunnelInterfaces, as well as the application of Transforms to the given TunnelInterfaces As part of the generation of ikeys/okeys, a ReserveKeyTracker manages a java bitset to avoid collisions and reserve/release keys. Bug: 63588681 Test: Compiles, CTS, unit tests all pass on AOSP_marlin Change-Id: I9e9b6455e27073acd4491eae666aa966b3b10e0f --- .../android/server/ConnectivityService.java | 4 ++-- .../com/android/server/IpSecServiceTest.java | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 6dbf53850e..bff5c10d4e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -456,8 +456,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private LingerMonitor mLingerMonitor; // sequence number for Networks; keep in sync with system/netd/NetworkController.cpp - private final static int MIN_NET_ID = 100; // some reserved marks - private final static int MAX_NET_ID = 65535; + private static final int MIN_NET_ID = 100; // some reserved marks + private static final int MAX_NET_ID = 65535 - 0x0400; // Top 1024 bits reserved by IpSecService private int mNextNetId = MIN_NET_ID; // sequence number of NetworkRequests diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index a375b600ca..2c94a601fb 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -635,4 +635,25 @@ public class IpSecServiceTest { verify(mMockNetd).ipSecSetEncapSocketOwner(argThat(fdMatcher), eq(Os.getuid())); mIpSecService.closeUdpEncapsulationSocket(udpEncapResp.resourceId); } + + @Test + public void testReserveNetId() { + int start = mIpSecService.TUN_INTF_NETID_START; + for (int i = 0; i < mIpSecService.TUN_INTF_NETID_RANGE; i++) { + assertEquals(start + i, mIpSecService.reserveNetId()); + } + + // Check that resource exhaustion triggers an exception + try { + mIpSecService.reserveNetId(); + fail("Did not throw error for all netIds reserved"); + } catch (IllegalStateException expected) { + } + + // Now release one and try again + int releasedNetId = + mIpSecService.TUN_INTF_NETID_START + mIpSecService.TUN_INTF_NETID_RANGE / 2; + mIpSecService.releaseNetId(releasedNetId); + assertEquals(releasedNetId, mIpSecService.reserveNetId()); + } } From 859629fa0bea0e5ea10ce147ab64ea8d85de336f Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Fri, 19 Jan 2018 17:36:02 -0800 Subject: [PATCH 10/14] Add tunnel-mode calls to netd in IpSecService Adds calls to relevant netd methods in IpSecService, enabling Tunnel mode functionality. Bug: 63588681 Test: Compiles, passing CTS + unit tests Change-Id: I6deb68584cddb03f21bd76370d4ef69cadc1bf16 --- .../com/android/server/IpSecServiceParameterizedTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 801a396ecb..66e0955b04 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -19,7 +19,6 @@ package com.android.server; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; @@ -229,7 +228,7 @@ public class IpSecServiceParameterizedTest { anyInt(), anyString(), anyString(), - anyLong(), + anyInt(), eq(TEST_SPI), anyInt(), anyInt(), @@ -264,7 +263,7 @@ public class IpSecServiceParameterizedTest { anyInt(), anyString(), anyString(), - anyLong(), + anyInt(), eq(TEST_SPI), anyInt(), anyInt(), From 389a81485e62531dcd64ea8df4e5d056f50f0ded Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 24 Jan 2018 17:35:07 +0900 Subject: [PATCH 11/14] Determine the multipath hint from data usage. Bug: 35142602 Test: builds, boots Change-Id: I0f5de5e313ead442aa210f163db035fcf7de5e73 --- .../com/android/server/ConnectivityService.java | 15 +++++++++++++++ .../net/util/MultinetworkPolicyTracker.java | 1 + 2 files changed, 16 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index c1f4b789e0..c68837ae8f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -137,6 +137,7 @@ import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.connectivity.KeepaliveTracker; import com.android.server.connectivity.LingerMonitor; import com.android.server.connectivity.MockableSystemProperties; +import com.android.server.connectivity.MultipathPolicyTracker; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkDiagnostics; import com.android.server.connectivity.NetworkMonitor; @@ -507,6 +508,9 @@ public class ConnectivityService extends IConnectivityManager.Stub @VisibleForTesting final MultinetworkPolicyTracker mMultinetworkPolicyTracker; + @VisibleForTesting + final MultipathPolicyTracker mMultipathPolicyTracker; + /** * Implements support for the legacy "one network per network type" model. * @@ -890,6 +894,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mContext, mHandler, () -> rematchForAvoidBadWifiUpdate()); mMultinetworkPolicyTracker.start(); + mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler); + mDnsManager = new DnsManager(mContext, mNetd, mSystemProperties); registerPrivateDnsSettingsCallbacks(); } @@ -1966,6 +1972,9 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(); dumpAvoidBadWifiSettings(pw); + pw.println(); + mMultipathPolicyTracker.dump(pw); + if (argsContain(args, SHORT_ARG) == false) { pw.println(); synchronized (mValidationLogs) { @@ -2901,6 +2910,11 @@ public class ConnectivityService extends IConnectivityManager.Stub return ConnectivityManager.MULTIPATH_PREFERENCE_UNMETERED; } + Integer networkPreference = mMultipathPolicyTracker.getMultipathPreference(network); + if (networkPreference != null) { + return networkPreference; + } + return mMultinetworkPolicyTracker.getMeteredMultipathPreference(); } @@ -2994,6 +3008,7 @@ public class ConnectivityService extends IConnectivityManager.Stub for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { nai.networkMonitor.systemReady = true; } + mMultipathPolicyTracker.start(); break; } case EVENT_REVALIDATE_NETWORK: { diff --git a/services/net/java/android/net/util/MultinetworkPolicyTracker.java b/services/net/java/android/net/util/MultinetworkPolicyTracker.java index 424e40d209..30c5cd98b7 100644 --- a/services/net/java/android/net/util/MultinetworkPolicyTracker.java +++ b/services/net/java/android/net/util/MultinetworkPolicyTracker.java @@ -122,6 +122,7 @@ public class MultinetworkPolicyTracker { return mAvoidBadWifi; } + // TODO: move this to MultipathPolicyTracker. public int getMeteredMultipathPreference() { return mMeteredMultipathPreference; } From f8a2bc3eeecccd229e3fa2185b933fe26efdd34a Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 2 Nov 2017 21:01:46 -0700 Subject: [PATCH 12/14] Relocate KeepalivePacketData to frameworks/base Due to an issue resolving the boot classpath, the KeepalivePacketData structure cannot be referenced by frameworks/opt/telephony while it is in services. -Move KeepalivePacketData to android.net -Also, relocate IpUtils without changing the package name. Bug: 38350389 Test: compilation Change-Id: If5fc63e9ad8b9b2d4c2fee47ff4bab2ab190a05a (cherry picked from commit bd4093be7cab51d6ad031854324134a9c8637c2c) --- .../java/android/net}/KeepalivePacketData.java | 2 +- .../java/com/android/server/connectivity/KeepaliveTracker.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {services/core/java/com/android/server/connectivity => core/java/android/net}/KeepalivePacketData.java (99%) diff --git a/services/core/java/com/android/server/connectivity/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java similarity index 99% rename from services/core/java/com/android/server/connectivity/KeepalivePacketData.java rename to core/java/android/net/KeepalivePacketData.java index f6b73b7d69..84892c6a55 100644 --- a/services/core/java/com/android/server/connectivity/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.connectivity; +package android.net; import static android.net.util.NetworkConstants.IPV4_HEADER_MIN_LEN; import static android.net.util.NetworkConstants.UDP_HEADER_LEN; diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 9e1f6b85ce..f1af7042be 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -18,10 +18,10 @@ package com.android.server.connectivity; import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.connectivity.KeepalivePacketData; import com.android.server.connectivity.NetworkAgentInfo; import android.net.ConnectivityManager; import android.net.ConnectivityManager.PacketKeepalive; +import android.net.KeepalivePacketData; import android.net.LinkAddress; import android.net.NetworkAgent; import android.net.NetworkUtils; From 5be3f5a2b1ecfbb3c9d8eb0dfa12cf6e88dbca9f Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 6 Dec 2017 19:07:32 -0800 Subject: [PATCH 13/14] Rework KeepalivePacketData for Compatibility with Cell KeepalivePacketData currently mixes multiple concepts: the list of parameters that are used to generate a keepalive packet, the keepalive packet itself, and the parameters that are needed to send a keepalive packet over an ethernet link. The KeepalivePacketData is now a parcelable that can be used generically by any NetworkAgent, regardless of how that Agent fulfills its duty to initiate and maintain a keepalive session. Bug: 69063212 Test: verified with SL4A, additional tests pending Change-Id: I23dc4827ae729583356a8ff0f02e39a2ad2b81f5 --- .../java/android/net/KeepalivePacketData.java | 99 +++++++++++++------ .../server/connectivity/KeepaliveTracker.java | 4 +- 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 84892c6a55..08d4ff5da9 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -16,13 +16,13 @@ package android.net; -import static android.net.util.NetworkConstants.IPV4_HEADER_MIN_LEN; -import static android.net.util.NetworkConstants.UDP_HEADER_LEN; - import android.system.OsConstants; import android.net.ConnectivityManager; -import android.net.NetworkUtils; import android.net.util.IpUtils; +import android.os.Parcel; +import android.os.Parcelable; +import android.system.OsConstants; +import android.util.Log; import java.net.Inet4Address; import java.net.Inet6Address; @@ -38,9 +38,8 @@ import static android.net.ConnectivityManager.PacketKeepalive.*; * * @hide */ -public class KeepalivePacketData { - /** Protocol of the packet to send; one of the OsConstants.ETH_P_* values. */ - public final int protocol; +public class KeepalivePacketData implements Parcelable { + private static final String TAG = "KeepalivePacketData"; /** Source IP address */ public final InetAddress srcAddress; @@ -54,54 +53,57 @@ public class KeepalivePacketData { /** Destination port */ public final int dstPort; - /** Destination MAC address. Can change if routing changes. */ - public byte[] dstMac; - /** Packet data. A raw byte string of packet data, not including the link-layer header. */ - public final byte[] data; + private final byte[] mPacket; + private static final int IPV4_HEADER_LENGTH = 20; + private static final int UDP_HEADER_LENGTH = 8; + + // This should only be constructed via static factory methods, such as + // nattKeepalivePacket protected KeepalivePacketData(InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException { this.srcAddress = srcAddress; this.dstAddress = dstAddress; this.srcPort = srcPort; this.dstPort = dstPort; - this.data = data; + this.mPacket = data; // Check we have two IP addresses of the same family. - if (srcAddress == null || dstAddress == null || - !srcAddress.getClass().getName().equals(dstAddress.getClass().getName())) { - throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); - } - - // Set the protocol. - if (this.dstAddress instanceof Inet4Address) { - this.protocol = OsConstants.ETH_P_IP; - } else if (this.dstAddress instanceof Inet6Address) { - this.protocol = OsConstants.ETH_P_IPV6; - } else { + if (srcAddress == null || dstAddress == null || !srcAddress.getClass().getName() + .equals(dstAddress.getClass().getName())) { + Log.e(TAG, "Invalid or mismatched InetAddresses in KeepalivePacketData"); throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); } // Check the ports. if (!IpUtils.isValidUdpOrTcpPort(srcPort) || !IpUtils.isValidUdpOrTcpPort(dstPort)) { + Log.e(TAG, "Invalid ports in KeepalivePacketData"); throw new InvalidPacketException(ERROR_INVALID_PORT); } } public static class InvalidPacketException extends Exception { - final public int error; + public final int error; public InvalidPacketException(int error) { this.error = error; } } - /** - * Creates an IPsec NAT-T keepalive packet with the specified parameters. - */ + public byte[] getPacket() { + return mPacket.clone(); + } + public static KeepalivePacketData nattKeepalivePacket( - InetAddress srcAddress, int srcPort, - InetAddress dstAddress, int dstPort) throws InvalidPacketException { + InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort) + throws InvalidPacketException { + + // FIXME: remove this and actually support IPv6 keepalives + if (srcAddress instanceof Inet6Address && dstAddress instanceof Inet6Address) { + // Optimistically returning an IPv6 Keepalive Packet with no data, + // which currently only works on cellular + return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, new byte[0]); + } if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) { throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); @@ -111,7 +113,7 @@ public class KeepalivePacketData { throw new InvalidPacketException(ERROR_INVALID_PORT); } - int length = IPV4_HEADER_MIN_LEN + UDP_HEADER_LEN + 1; + int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; ByteBuffer buf = ByteBuffer.allocate(length); buf.order(ByteOrder.BIG_ENDIAN); buf.putShort((short) 0x4500); // IP version and TOS @@ -130,8 +132,43 @@ public class KeepalivePacketData { buf.putShort((short) 0); // UDP checksum buf.put((byte) 0xff); // NAT-T keepalive buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); - buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_MIN_LEN)); + buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); } + + /* Parcelable Implementation */ + public int describeContents() { + return 0; + } + + /** Write to parcel */ + public void writeToParcel(Parcel out, int flags) { + out.writeString(srcAddress.getHostAddress()); + out.writeString(dstAddress.getHostAddress()); + out.writeInt(srcPort); + out.writeInt(dstPort); + out.writeByteArray(mPacket); + } + + private KeepalivePacketData(Parcel in) { + srcAddress = NetworkUtils.numericToInetAddress(in.readString()); + dstAddress = NetworkUtils.numericToInetAddress(in.readString()); + srcPort = in.readInt(); + dstPort = in.readInt(); + mPacket = in.createByteArray(); + } + + /** Parcelable Creator */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public KeepalivePacketData createFromParcel(Parcel in) { + return new KeepalivePacketData(in); + } + + public KeepalivePacketData[] newArray(int size) { + return new KeepalivePacketData[size]; + } + }; + } diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index f1af7042be..d24f9c985a 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -129,7 +129,7 @@ public class KeepaliveTracker { .append("->") .append(IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort)) .append(" interval=" + mInterval) - .append(" data=" + HexDump.toHexString(mPacket.data)) + .append(" packetData=" + HexDump.toHexString(mPacket.getPacket())) .append(" uid=").append(mUid).append(" pid=").append(mPid) .append(" ]") .toString(); @@ -172,7 +172,7 @@ public class KeepaliveTracker { } private int checkInterval() { - return mInterval >= 20 ? SUCCESS : ERROR_INVALID_INTERVAL; + return mInterval >= 10 ? SUCCESS : ERROR_INVALID_INTERVAL; } private int isValid() { From 179b37dbf4705a5b7e13d196c552bca3239770b6 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 25 Jan 2018 09:41:51 +0900 Subject: [PATCH 14/14] Fix a bug where a NetworkAgent gets repeatedly torn down mUids is not marshalled correctly when null so if the NetworkAgent runs in another process and is not a VPN then the system will see its allowed Uids as being the empty list (= nobody can use this network) instead of a null list (= everybody can use this network). This breaks emulator networking. Bug: 72436966 Test: runtests frameworks-net Test: also manual testing, this does fix emulator networking and seems not to break phone networking Cherry-pick of : Id2bbf3808e80b19cd055c832c11cf72372710942 Change-Id: I4b88d5eccbdea745a947d12635cd751e38632589 --- core/java/android/net/NetworkCapabilities.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 1a4765bcf6..8e05cfa966 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -892,7 +892,7 @@ public final class NetworkCapabilities implements Parcelable { * * @hide */ - private Set mUids = null; + private ArraySet mUids = null; /** * Convenience method to set the UIDs this network applies to to a single UID. @@ -1178,7 +1178,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeInt(mLinkDownBandwidthKbps); dest.writeParcelable((Parcelable) mNetworkSpecifier, flags); dest.writeInt(mSignalStrength); - dest.writeArraySet(new ArraySet<>(mUids)); + dest.writeArraySet(mUids); } public static final Creator CREATOR =