Add accessUids to NetworkCapabilities.

For now, all entry points reject this. Followup changes
will allow the supported use cases.

Test: new unit tests and CTS for this in this patch
Change-Id: I7262811a2e46336d3bb63c80886fc0578a36da94
This commit is contained in:
Chalard Jean
2021-12-13 22:53:51 +09:00
parent 1522857564
commit 9a30acf744
6 changed files with 269 additions and 18 deletions

View File

@@ -264,6 +264,7 @@ public final class NetworkCapabilities implements Parcelable {
mTransportInfo = null;
mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
mUids = null;
mAccessUids.clear();
mAdministratorUids = new int[0];
mOwnerUid = Process.INVALID_UID;
mSSID = null;
@@ -294,6 +295,7 @@ public final class NetworkCapabilities implements Parcelable {
}
mSignalStrength = nc.mSignalStrength;
mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids);
setAccessUids(nc.mAccessUids);
setAdministratorUids(nc.getAdministratorUids());
mOwnerUid = nc.mOwnerUid;
mForbiddenNetworkCapabilities = nc.mForbiddenNetworkCapabilities;
@@ -1025,6 +1027,7 @@ public final class NetworkCapabilities implements Parcelable {
final int[] originalAdministratorUids = getAdministratorUids();
final TransportInfo originalTransportInfo = getTransportInfo();
final Set<Integer> originalSubIds = getSubscriptionIds();
final Set<Integer> originalAccessUids = new ArraySet<>(mAccessUids);
clearAll();
if (0 != (originalCapabilities & (1 << NET_CAPABILITY_NOT_RESTRICTED))) {
// If the test network is not restricted, then it is only allowed to declare some
@@ -1044,6 +1047,7 @@ public final class NetworkCapabilities implements Parcelable {
mNetworkSpecifier = originalSpecifier;
mSignalStrength = originalSignalStrength;
mTransportInfo = originalTransportInfo;
mAccessUids.addAll(originalAccessUids);
// Only retain the owner and administrator UIDs if they match the app registering the remote
// caller that registered the network.
@@ -1808,6 +1812,79 @@ public final class NetworkCapabilities implements Parcelable {
return false;
}
/**
* List of UIDs that can always access this network.
* <p>
* UIDs in this list have access to this network, even if the network doesn't have the
* {@link #NET_CAPABILITY_NOT_RESTRICTED} capability and the UID does not hold the
* {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS} permission.
* This is only useful for restricted networks. For non-restricted networks it has no effect.
* <p>
* This is disallowed in {@link NetworkRequest}, and can only be set by network agents. Network
* agents also have restrictions on how they can set these ; they can only back a public
* Android API. As such, Ethernet agents can set this when backing the per-UID access API, and
* Telephony can set exactly one UID which has to match the manager app for the associated
* subscription. Failure to comply with these rules will see this member cleared.
* <p>
* This member is never null, but can be empty.
* @hide
*/
@NonNull
private final ArraySet<Integer> mAccessUids = new ArraySet<>();
/**
* Set the list of UIDs that can always access this network.
* @param uids
* @hide
*/
public void setAccessUids(@NonNull final Set<Integer> uids) {
// could happen with nc.set(nc), cheaper than always making a defensive copy
if (uids == mAccessUids) return;
Objects.requireNonNull(uids);
mAccessUids.clear();
mAccessUids.addAll(uids);
}
/**
* The list of UIDs that can always access this network.
*
* The UIDs in this list can always access this network, even if it is restricted and
* the UID doesn't hold the USE_RESTRICTED_NETWORKS permission. This is defined by the
* network agent in charge of creating the network.
*
* Only network factories and the system server can see these UIDs, since the system
* server makes sure to redact them before sending a NetworkCapabilities to a process
* that doesn't hold the permission.
*
* @hide
*/
// @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public @NonNull Set<Integer> getAccessUids() {
return new ArraySet<>(mAccessUids);
}
/**
* Test whether this UID has special permission to access this network, as per mAccessUids.
* @hide
*/
public boolean isAccessUid(int uid) {
return mAccessUids.contains(uid);
}
/**
* @return whether any UID is in the list of access UIDs
* @hide
*/
public boolean hasAccessUids() {
return !mAccessUids.isEmpty();
}
private boolean equalsAccessUids(@NonNull NetworkCapabilities other) {
return mAccessUids.equals(other.mAccessUids);
}
/**
* The SSID of the network, or null if not applicable or unknown.
* <p>
@@ -1962,6 +2039,7 @@ public final class NetworkCapabilities implements Parcelable {
&& equalsSpecifier(that)
&& equalsTransportInfo(that)
&& equalsUids(that)
&& equalsAccessUids(that)
&& equalsSSID(that)
&& equalsOwnerUid(that)
&& equalsPrivateDnsBroken(that)
@@ -1986,15 +2064,16 @@ public final class NetworkCapabilities implements Parcelable {
+ mSignalStrength * 29
+ mOwnerUid * 31
+ Objects.hashCode(mUids) * 37
+ Objects.hashCode(mSSID) * 41
+ Objects.hashCode(mTransportInfo) * 43
+ Objects.hashCode(mPrivateDnsBroken) * 47
+ Objects.hashCode(mRequestorUid) * 53
+ Objects.hashCode(mRequestorPackageName) * 59
+ Arrays.hashCode(mAdministratorUids) * 61
+ Objects.hashCode(mSubIds) * 67
+ Objects.hashCode(mUnderlyingNetworks) * 71
+ mEnterpriseId * 73;
+ Objects.hashCode(mAccessUids) * 41
+ Objects.hashCode(mSSID) * 43
+ Objects.hashCode(mTransportInfo) * 47
+ Objects.hashCode(mPrivateDnsBroken) * 53
+ Objects.hashCode(mRequestorUid) * 59
+ Objects.hashCode(mRequestorPackageName) * 61
+ Arrays.hashCode(mAdministratorUids) * 67
+ Objects.hashCode(mSubIds) * 71
+ Objects.hashCode(mUnderlyingNetworks) * 73
+ mEnterpriseId * 79;
}
@Override
@@ -2022,6 +2101,7 @@ public final class NetworkCapabilities implements Parcelable {
dest.writeParcelable((Parcelable) mTransportInfo, flags);
dest.writeInt(mSignalStrength);
writeParcelableArraySet(dest, mUids, flags);
dest.writeIntArray(CollectionUtils.toIntArray(mAccessUids));
dest.writeString(mSSID);
dest.writeBoolean(mPrivateDnsBroken);
dest.writeIntArray(getAdministratorUids());
@@ -2034,7 +2114,7 @@ public final class NetworkCapabilities implements Parcelable {
}
public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
new Creator<NetworkCapabilities>() {
new Creator<>() {
@Override
public NetworkCapabilities createFromParcel(Parcel in) {
NetworkCapabilities netCap = new NetworkCapabilities();
@@ -2048,6 +2128,11 @@ public final class NetworkCapabilities implements Parcelable {
netCap.mTransportInfo = in.readParcelable(null);
netCap.mSignalStrength = in.readInt();
netCap.mUids = readParcelableArraySet(in, null /* ClassLoader, null for default */);
final int[] accessUids = in.createIntArray();
netCap.mAccessUids.ensureCapacity(accessUids.length);
for (int uid : accessUids) {
netCap.mAccessUids.add(uid);
}
netCap.mSSID = in.readString();
netCap.mPrivateDnsBroken = in.readBoolean();
netCap.setAdministratorUids(in.createIntArray());
@@ -2124,6 +2209,11 @@ public final class NetworkCapabilities implements Parcelable {
sb.append(" Uids: <").append(mUids).append(">");
}
}
if (hasAccessUids()) {
sb.append(" AccessUids: <").append(mAccessUids).append(">");
}
if (mOwnerUid != Process.INVALID_UID) {
sb.append(" OwnerUid: ").append(mOwnerUid);
}
@@ -2300,7 +2390,7 @@ public final class NetworkCapabilities implements Parcelable {
private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) {
if (!isValidCapability(capability)) {
throw new IllegalArgumentException("NetworkCapability " + capability + "out of range");
throw new IllegalArgumentException("NetworkCapability " + capability + " out of range");
}
}
@@ -2908,6 +2998,44 @@ public final class NetworkCapabilities implements Parcelable {
return this;
}
/**
* Set a list of UIDs that can always access this network
* <p>
* Provide a list of UIDs that can access this network even if the network doesn't have the
* {@link #NET_CAPABILITY_NOT_RESTRICTED} capability and the UID does not hold the
* {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS} permission.
* <p>
* This is disallowed in {@link NetworkRequest}, and can only be set by
* {@link NetworkAgent}s, who hold the
* {@link android.Manifest.permission.NETWORK_FACTORY} permission.
* Network agents also have restrictions on how they can set these ; they can only back
* a public Android API. As such, Ethernet agents can set this when backing the per-UID
* access API, and Telephony can set exactly one UID which has to match the manager app for
* the associated subscription. Failure to comply with these rules will see this member
* cleared.
* <p>
* Only network factories and the system server can see these UIDs, since the system server
* makes sure to redact them before sending a {@link NetworkCapabilities} instance to a
* process that doesn't hold the {@link android.Manifest.permission.NETWORK_FACTORY}
* permission.
* <p>
* This list cannot be null, but it can be empty to mean that no UID without the
* {@link android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS} permission
* gets to access this network.
*
* @param uids the list of UIDs that can always access this network
* @return this builder
* @hide
*/
@NonNull
// @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
public Builder setAccessUids(@NonNull Set<Integer> uids) {
Objects.requireNonNull(uids);
mCaps.setAccessUids(uids);
return this;
}
/**
* Set the underlying networks of this network.
*