diff options
| author | 2020-01-24 10:24:12 -0800 | |
|---|---|---|
| committer | 2020-01-24 10:24:12 -0800 | |
| commit | 23f27778e37992d0745ea054d87e8fb8c28aa7f8 (patch) | |
| tree | f73d8a894b6c2847981f83f2f08affd9f6c8e8d1 | |
| parent | 1702fe47fd1f4486198db20a1ad2f19ace22f173 (diff) | |
| parent | e021269f8d1912454087cb17b39e987b9f42b08c (diff) | |
Merge "Add API for apps to check if they are the network owner"
am: e021269f8d
Change-Id: I1316c7fccd9b7a35ff6d8a79a8afa13644d9ab54
6 files changed, 65 insertions, 37 deletions
diff --git a/api/current.txt b/api/current.txt index 683d7f64e465..3882dbdefabe 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29139,6 +29139,7 @@ package android.net { method public int getLinkDownstreamBandwidthKbps(); method public int getLinkUpstreamBandwidthKbps(); method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); + method public int getOwnerUid(); method public int getSignalStrength(); method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); @@ -29148,6 +29149,7 @@ package android.net { method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int); method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int); method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier); + method public void setOwnerUid(int); method @NonNull public android.net.NetworkCapabilities setSignalStrength(int); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR; diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 6207661e47ce..f94bdb767c02 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -26,6 +26,7 @@ import android.net.ConnectivityManager.NetworkCallback; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.os.Process; import android.util.ArraySet; import android.util.proto.ProtoOutputStream; @@ -58,7 +59,6 @@ import java.util.StringJoiner; */ public final class NetworkCapabilities implements Parcelable { private static final String TAG = "NetworkCapabilities"; - private static final int INVALID_UID = -1; // Set to true when private DNS is broken. private boolean mPrivateDnsBroken; @@ -85,8 +85,8 @@ public final class NetworkCapabilities implements Parcelable { mTransportInfo = null; mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; mUids = null; - mEstablishingVpnAppUid = INVALID_UID; mAdministratorUids.clear(); + mOwnerUid = Process.INVALID_UID; mSSID = null; mPrivateDnsBroken = false; } @@ -104,8 +104,8 @@ public final class NetworkCapabilities implements Parcelable { mTransportInfo = nc.mTransportInfo; mSignalStrength = nc.mSignalStrength; setUids(nc.mUids); // Will make the defensive copy - mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid; setAdministratorUids(nc.mAdministratorUids); + mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; mSSID = nc.mSSID; mPrivateDnsBroken = nc.mPrivateDnsBroken; @@ -810,31 +810,26 @@ public final class NetworkCapabilities implements Parcelable { } /** - * UID of the app that manages this network, or INVALID_UID if none/unknown. + * UID of the app that owns 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 + * <p>This field keeps track of the UID of the app that created this network and is in charge of + * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running + * VPN, or Carrier Service app managing a cellular data connection. */ - private int mEstablishingVpnAppUid = INVALID_UID; + private int mOwnerUid = Process.INVALID_UID; /** - * Set the UID of the managing app. - * @hide + * Set the UID of the owner app. */ - public void setEstablishingVpnAppUid(final int uid) { - mEstablishingVpnAppUid = uid; + public void setOwnerUid(final int uid) { + mOwnerUid = uid; } - /** @hide */ - public int getEstablishingVpnAppUid() { - return mEstablishingVpnAppUid; + /** + * Retrieves the UID of the owner app. + */ + public int getOwnerUid() { + return mOwnerUid; } /** @@ -1157,7 +1152,7 @@ public final class NetworkCapabilities implements Parcelable { * 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 + * mOwnerUid) can always see this network. This is embodied by a special check in * satisfiedByUids. That still does not mean the network necessarily <strong>applies</strong> * to the app that manages it as determined by #appliesToUid. * <p> @@ -1264,7 +1259,7 @@ public final class NetworkCapabilities implements Parcelable { * in the passed nc (representing the UIDs that this network is available to). * <p> * As a special exception, the UID that created the passed network (as represented by its - * mEstablishingVpnAppUid field) always satisfies a NetworkRequest requiring it (of LISTEN + * mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN * or REQUEST types alike), even if the network does not apply to it. That is so a VPN app * can see its own network when it listens for it. * <p> @@ -1275,7 +1270,7 @@ public final class NetworkCapabilities implements Parcelable { public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) { if (null == nc.mUids || null == mUids) return true; // The network satisfies everything. for (UidRange requiredRange : mUids) { - if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true; + if (requiredRange.contains(nc.mOwnerUid)) return true; if (!nc.appliesToUidRange(requiredRange)) { return false; } @@ -1541,6 +1536,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeString(mSSID); dest.writeBoolean(mPrivateDnsBroken); dest.writeList(mAdministratorUids); + dest.writeInt(mOwnerUid); } public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR = @@ -1562,6 +1558,7 @@ public final class NetworkCapabilities implements Parcelable { netCap.mSSID = in.readString(); netCap.mPrivateDnsBroken = in.readBoolean(); netCap.setAdministratorUids(in.readArrayList(null)); + netCap.mOwnerUid = in.readInt(); return netCap; } @Override @@ -1611,8 +1608,8 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" Uids: <").append(mUids).append(">"); } } - if (mEstablishingVpnAppUid != INVALID_UID) { - sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid); + if (mOwnerUid != Process.INVALID_UID) { + sb.append(" OwnerUid: ").append(mOwnerUid); } if (!mAdministratorUids.isEmpty()) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0981cd88724f..478b87c01025 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1626,7 +1626,8 @@ public class ConnectivityService extends IConnectivityManager.Stub return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network)); } - private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions( + @VisibleForTesting + NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions( NetworkCapabilities nc, int callerPid, int callerUid) { final NetworkCapabilities newNc = new NetworkCapabilities(nc); if (!checkSettingsPermission(callerPid, callerUid)) { @@ -1637,9 +1638,23 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); } newNc.setAdministratorUids(Collections.EMPTY_LIST); + + maybeSanitizeLocationInfoForCaller(newNc, callerUid); + return newNc; } + private void maybeSanitizeLocationInfoForCaller( + NetworkCapabilities nc, int callerUid) { + // TODO(b/142072839): Conditionally reset the owner UID if the following + // conditions are not met: + // 1. The destination app is the network owner + // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted + // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted + // 3. The user's location toggle is on + nc.setOwnerUid(INVALID_UID); + } + private LinkProperties linkPropertiesRestrictedForCallerPermissions( LinkProperties lp, int callerPid, int callerUid) { if (lp == null) return new LinkProperties(); @@ -1668,6 +1683,9 @@ public class ConnectivityService extends IConnectivityManager.Stub nc.setSingleUid(Binder.getCallingUid()); } nc.setAdministratorUids(Collections.EMPTY_LIST); + + // Clear owner UID; this can never come from an app. + nc.setOwnerUid(INVALID_UID); } private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) { @@ -5795,7 +5813,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } final Set<UidRange> ranges = nai.networkCapabilities.getUids(); - final int vpnAppUid = nai.networkCapabilities.getEstablishingVpnAppUid(); + final int vpnAppUid = nai.networkCapabilities.getOwnerUid(); // TODO: this create a window of opportunity for apps to receive traffic between the time // when the old rules are removed and the time when new rules are added. To fix this, // make eBPF support two whitelisted interfaces so here new rules can be added before the @@ -5994,7 +6012,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nc == null || lp == null) return false; return nai.isVPN() && !nai.networkAgentConfig.allowBypass - && nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID + && nc.getOwnerUid() != Process.SYSTEM_UID && lp.getInterfaceName() != null && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()); } @@ -6042,12 +6060,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range // to be removed will never overlap with the new range to be added. if (wasFiltering && !prevRanges.isEmpty()) { - mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, - prevNc.getEstablishingVpnAppUid()); + mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid()); } if (shouldFilter && !newRanges.isEmpty()) { - mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, - newNc.getEstablishingVpnAppUid()); + mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid()); } } catch (Exception e) { // Never crash! diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 69ab47a61362..2933fab465e5 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -950,7 +950,7 @@ public class Vpn { NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown; - mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid()); + mNetworkCapabilities.setOwnerUid(Binder.getCallingUid()); mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle, mConfig.allowedApplications, mConfig.disallowedApplications)); long token = Binder.clearCallingIdentity(); diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 797fd83321f7..3e4f3d818840 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -269,6 +269,7 @@ public class NetworkCapabilitiesTest { .setUids(uids) .addCapability(NET_CAPABILITY_EIMS) .addCapability(NET_CAPABILITY_NOT_METERED); + netCap.setOwnerUid(123); assertParcelingIsLossless(netCap); netCap.setSSID(TEST_SSID); assertParcelSane(netCap, 13); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 783f8d177f4a..e80b7c9d0156 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6313,12 +6313,24 @@ public class ConnectivityServiceTest { assertEquals(wifiLp, mService.getActiveLinkProperties()); } + @Test + public void testNetworkCapabilitiesRestrictedForCallerPermissions() { + int callerUid = Process.myUid(); + final NetworkCapabilities originalNc = new NetworkCapabilities(); + originalNc.setOwnerUid(callerUid); + + final NetworkCapabilities newNc = + mService.networkCapabilitiesRestrictedForCallerPermissions( + originalNc, Process.myPid(), callerUid); + + assertEquals(Process.INVALID_UID, newNc.getOwnerUid()); + } - private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid, - Set<UidRange> vpnRange) throws Exception { + private TestNetworkAgentWrapper establishVpn( + LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception { final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp); - vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid); + vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid); mMockVpn.setNetworkAgent(vpnNetworkAgent); mMockVpn.connect(); mMockVpn.setUids(vpnRange); |