diff options
| author | 2021-03-24 14:01:51 -0700 | |
|---|---|---|
| committer | 2021-04-02 01:18:11 -0700 | |
| commit | b3099509dee43f1a997cb75e7af286925fb758fc (patch) | |
| tree | 00c3b9ae4ca22db1be0c6e32db5fe2a7d1380c27 | |
| parent | dedc39bc2c883be13454fb4adc6157a1fe6dfffd (diff) | |
Downgrade list of subIds in NetworkCapabilities to @SystemApi
This change downgrades API visibility for the list-of-subIds in the
NetworkCapabilities to SystemApi
Bug: 175662146
Test: atest NetworkCapabilitiesTest#testSubIds
Test: atest FrameworksNetTests
Change-Id: I372fa9eaa7585aefd1710948ca007456feedd578
6 files changed, 93 insertions, 2 deletions
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt index 0a9560a5c56d..ab290f9d706a 100644 --- a/packages/Connectivity/framework/api/current.txt +++ b/packages/Connectivity/framework/api/current.txt @@ -298,7 +298,6 @@ package android.net { method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier(); method public int getOwnerUid(); method public int getSignalStrength(); - method @NonNull public java.util.Set<java.lang.Integer> getSubIds(); method @Nullable public android.net.TransportInfo getTransportInfo(); method public boolean hasCapability(int); method public boolean hasTransport(int); @@ -408,7 +407,6 @@ package android.net { method public android.net.NetworkRequest.Builder removeTransportType(int); method @Deprecated public android.net.NetworkRequest.Builder setNetworkSpecifier(String); method public android.net.NetworkRequest.Builder setNetworkSpecifier(android.net.NetworkSpecifier); - method @NonNull public android.net.NetworkRequest.Builder setSubIds(@NonNull java.util.Set<java.lang.Integer>); } public class ParseException extends java.lang.RuntimeException { diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt index afd4fa0de189..251e5e846a2d 100644 --- a/packages/Connectivity/framework/api/system-current.txt +++ b/packages/Connectivity/framework/api/system-current.txt @@ -274,6 +274,7 @@ package android.net { public final class NetworkCapabilities implements android.os.Parcelable { method @NonNull public int[] getAdministratorUids(); method @Nullable public String getSsid(); + method @NonNull public java.util.Set<java.lang.Integer> getSubIds(); method @NonNull public int[] getTransportTypes(); method public boolean isPrivateDnsBroken(); method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities); @@ -327,6 +328,7 @@ package android.net { public static class NetworkRequest.Builder { method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) public android.net.NetworkRequest.Builder setSignalStrength(int); + method @NonNull public android.net.NetworkRequest.Builder setSubIds(@NonNull java.util.Set<java.lang.Integer>); } public final class NetworkScore implements android.os.Parcelable { diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java index 7e7089176e7a..4464b6ebf887 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java +++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java @@ -2346,9 +2346,15 @@ public final class NetworkCapabilities implements Parcelable { /** * Gets the subscription ID set that associated to this network or request. + * + * <p>Instances of NetworkCapabilities will only have this field populated by the system if the + * receiver holds the NETWORK_FACTORY permission. In all other cases, it will be the empty set. + * * @return + * @hide */ @NonNull + @SystemApi public Set<Integer> getSubIds() { return new ArraySet<>(mSubIds); } @@ -2713,10 +2719,17 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the subscription ID set. * + * <p>SubIds are populated in NetworkCapability instances from the system only for callers + * that hold the NETWORK_FACTORY permission. Similarly, the system will reject any + * NetworkRequests filed with a non-empty set of subIds unless the caller holds the + * NETWORK_FACTORY permission. + * * @param subIds a set that represent the subscription IDs. Empty if clean up. * @return this builder. + * @hide */ @NonNull + @SystemApi public Builder setSubIds(@NonNull final Set<Integer> subIds) { mCaps.setSubIds(subIds); return this; diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java index 38691ef5cb39..5d40417440d4 100644 --- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java +++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java @@ -501,9 +501,14 @@ public class NetworkRequest implements Parcelable { * A network will satisfy this request only if it matches one of the subIds in this set. * An empty set matches all networks, including those without a subId. * + * <p>Registering a NetworkRequest with a non-empty set of subIds requires the + * NETWORK_FACTORY permission. + * * @param subIds A {@code Set} that represents subscription IDs. + * @hide */ @NonNull + @SystemApi public Builder setSubIds(@NonNull Set<Integer> subIds) { mNetworkCapabilities.setSubIds(subIds); return this; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 70c9fe7f3ac9..4e2d529b2e4e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1895,6 +1895,10 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); } newNc.setAdministratorUids(new int[0]); + if (!checkAnyPermissionOf( + callerPid, callerUid, android.Manifest.permission.NETWORK_FACTORY)) { + newNc.setSubIds(Collections.emptySet()); + } return newNc; } @@ -5666,6 +5670,10 @@ public class ConnectivityService extends IConnectivityManager.Stub "Insufficient permissions to request a specific signal strength"); } mAppOpsManager.checkPackage(callerUid, callerPackageName); + + if (!nc.getSubIds().isEmpty()) { + enforceNetworkFactoryPermission(); + } } private int[] getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index ad934204c4bd..fc0392f0af1f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -18,6 +18,7 @@ package com.android.server; import static android.Manifest.permission.CHANGE_NETWORK_STATE; import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; +import static android.Manifest.permission.NETWORK_FACTORY; import static android.Manifest.permission.NETWORK_SETTINGS; import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.content.Intent.ACTION_USER_ADDED; @@ -12186,4 +12187,68 @@ public class ConnectivityServiceTest { mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null)); } + + @Test + public void testSubIdsClearedWithoutNetworkFactoryPermission() throws Exception { + mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED); + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.setSubIds(Collections.singleton(Process.myUid())); + + final NetworkCapabilities result = + mService.networkCapabilitiesRestrictedForCallerPermissions( + nc, Process.myPid(), Process.myUid()); + assertTrue(result.getSubIds().isEmpty()); + } + + @Test + public void testSubIdsExistWithNetworkFactoryPermission() throws Exception { + mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED); + + final Set<Integer> subIds = Collections.singleton(Process.myUid()); + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.setSubIds(subIds); + + final NetworkCapabilities result = + mService.networkCapabilitiesRestrictedForCallerPermissions( + nc, Process.myPid(), Process.myUid()); + assertEquals(subIds, result.getSubIds()); + } + + private NetworkRequest getRequestWithSubIds() { + return new NetworkRequest.Builder() + .setSubIds(Collections.singleton(Process.myUid())) + .build(); + } + + @Test + public void testNetworkRequestWithSubIdsWithNetworkFactoryPermission() throws Exception { + mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_GRANTED); + final PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE); + final NetworkCallback networkCallback1 = new NetworkCallback(); + final NetworkCallback networkCallback2 = new NetworkCallback(); + + mCm.requestNetwork(getRequestWithSubIds(), networkCallback1); + mCm.requestNetwork(getRequestWithSubIds(), pendingIntent); + mCm.registerNetworkCallback(getRequestWithSubIds(), networkCallback2); + + mCm.unregisterNetworkCallback(networkCallback1); + mCm.releaseNetworkRequest(pendingIntent); + mCm.unregisterNetworkCallback(networkCallback2); + } + + @Test + public void testNetworkRequestWithSubIdsWithoutNetworkFactoryPermission() throws Exception { + mServiceContext.setPermission(NETWORK_FACTORY, PERMISSION_DENIED); + final PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE); + + final Class<SecurityException> expected = SecurityException.class; + assertThrows( + expected, () -> mCm.requestNetwork(getRequestWithSubIds(), new NetworkCallback())); + assertThrows(expected, () -> mCm.requestNetwork(getRequestWithSubIds(), pendingIntent)); + assertThrows( + expected, + () -> mCm.registerNetworkCallback(getRequestWithSubIds(), new NetworkCallback())); + } } |