summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Qingxi Li <qingxi@google.com> 2020-01-24 10:24:12 -0800
committer android-build-merger <android-build-merger@google.com> 2020-01-24 10:24:12 -0800
commit23f27778e37992d0745ea054d87e8fb8c28aa7f8 (patch)
treef73d8a894b6c2847981f83f2f08affd9f6c8e8d1
parent1702fe47fd1f4486198db20a1ad2f19ace22f173 (diff)
parente021269f8d1912454087cb17b39e987b9f42b08c (diff)
Merge "Add API for apps to check if they are the network owner"
am: e021269f8d Change-Id: I1316c7fccd9b7a35ff6d8a79a8afa13644d9ab54
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/net/NetworkCapabilities.java49
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java30
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java2
-rw-r--r--tests/net/common/java/android/net/NetworkCapabilitiesTest.java1
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java18
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);