Allow carrier service UIDs to access their own WiFi networks.
Bug: 236669534
Test: New tests in this patch
Change-Id: If312b8f8359888558969c022811d6b203be602a0
diff --git a/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java b/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
index 8edceb0..ebf6193 100644
--- a/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
+++ b/service/src/com/android/server/connectivity/CarrierPrivilegeAuthenticator.java
@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.server.connectivity.ConnectivityFlags.CARRIER_SERVICE_CHANGED_USE_CALLBACK;
@@ -31,6 +32,8 @@
import android.net.NetworkCapabilities;
import android.net.NetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
+import android.net.TransportInfo;
+import android.net.wifi.WifiInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
@@ -196,12 +199,13 @@
*
* This returns whether the passed UID is the carrier service package for the subscription ID
* stored in the telephony network specifier in the passed network capabilities.
- * If the capabilities don't code for a cellular network, or if they don't have the
+ * If the capabilities don't code for a cellular or Wi-Fi network, or if they don't have the
* subscription ID in their specifier, this returns false.
*
- * This method can be used to check that a network request for {@link NET_CAPABILITY_CBS} is
- * allowed for the UID of a caller, which must hold carrier privilege and provide the carrier
- * config.
+ * This method can be used to check that a network request that requires the UID to be
+ * the carrier service UID is indeed called by such a UID. An example of such a network could
+ * be a network with the {@link android.net.NetworkCapabilities#NET_CAPABILITY_CBS}
+ * capability.
* It can also be used to check that a factory is entitled to grant access to a given network
* to a given UID on grounds that it is the carrier service package.
*
@@ -212,10 +216,14 @@
public boolean hasCarrierPrivilegeForNetworkCapabilities(int callingUid,
@NonNull NetworkCapabilities networkCapabilities) {
if (callingUid == Process.INVALID_UID) return false;
- if (!networkCapabilities.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)) {
- return false;
+ final int subId;
+ if (networkCapabilities.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)) {
+ subId = getSubIdFromTelephonySpecifier(networkCapabilities.getNetworkSpecifier());
+ } else if (networkCapabilities.hasSingleTransportBesidesTest(TRANSPORT_WIFI)) {
+ subId = getSubIdFromWifiTransportInfo(networkCapabilities.getTransportInfo());
+ } else {
+ subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
- final int subId = getSubIdFromNetworkSpecifier(networkCapabilities.getNetworkSpecifier());
if (SubscriptionManager.INVALID_SUBSCRIPTION_ID == subId) return false;
return callingUid == getCarrierServiceUidForSubId(subId);
}
@@ -244,14 +252,6 @@
}
@VisibleForTesting
- int getSubIdFromNetworkSpecifier(NetworkSpecifier specifier) {
- if (specifier instanceof TelephonyNetworkSpecifier) {
- return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
- }
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- }
-
- @VisibleForTesting
int getUidForPackage(String pkgName) {
if (pkgName == null) {
return Process.INVALID_UID;
@@ -276,8 +276,22 @@
return getUidForPackage(getCarrierServicePackageNameForLogicalSlot(slotId));
}
- // Helper methods to avoid having to deal with UnsupportedApiLevelException.
+ @VisibleForTesting
+ int getSubIdFromTelephonySpecifier(@Nullable final NetworkSpecifier specifier) {
+ if (specifier instanceof TelephonyNetworkSpecifier) {
+ return ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
+ }
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+ int getSubIdFromWifiTransportInfo(@Nullable final TransportInfo info) {
+ if (info instanceof WifiInfo) {
+ return ((WifiInfo) info).getSubscriptionId();
+ }
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ // Helper methods to avoid having to deal with UnsupportedApiLevelException.
private void addCarrierPrivilegesListener(@NonNull final Executor executor,
@NonNull final PrivilegeListener listener) {
try {
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 567fd41..23556cb 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -23,6 +23,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.transportNamesOf;
import android.annotation.NonNull;
@@ -1591,10 +1592,11 @@
return false;
}
- // Factories that make cell networks can allow the UID for the carrier service package.
+ // Factories that make cell/wifi networks can allow the UID for the carrier service package.
// This can only work in T where there is support for CarrierPrivilegeAuthenticator
if (null != carrierPrivilegeAuthenticator
- && nc.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)
+ && (nc.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)
+ || nc.hasSingleTransportBesidesTest(TRANSPORT_WIFI))
&& (1 == nc.getAllowedUidsNoCopy().size())
&& (carrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
nc.getAllowedUidsNoCopy().valueAt(0), nc))) {
diff --git a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 3b6607f..225408c 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -757,8 +757,8 @@
val timeout = SystemClock.elapsedRealtime() + DEFAULT_TIMEOUT_MS
while (true) {
if (SystemClock.elapsedRealtime() > timeout) {
- fail("Couldn't make $servicePackage the service package for $defaultSubId: "
- + "dumpsys connectivity".execute().split("\n")
+ fail("Couldn't make $servicePackage the service package for $defaultSubId: " +
+ "dumpsys connectivity".execute().split("\n")
.filter { it.contains("Logical slot = $defaultSlotIndex.*") })
}
if ("dumpsys connectivity"
@@ -772,10 +772,14 @@
Thread.sleep(500)
}
- // Cell is allowed to set UIDs, but not WIFI/BLUETOOTH or agents with multiple
+ // Cell and WiFi are allowed to set UIDs, but not Bluetooth or agents with multiple
// transports.
doTestAllowedUids(defaultSubId, TRANSPORT_CELLULAR, uid, expectUidsPresent = true)
- doTestAllowedUids(defaultSubId, TRANSPORT_WIFI, uid, expectUidsPresent = false)
+ if (SdkLevel.isAtLeastV()) {
+ // Cannot be tested before V because WifiInfo.Builder#setSubscriptionId doesn't
+ // exist
+ doTestAllowedUids(defaultSubId, TRANSPORT_WIFI, uid, expectUidsPresent = true)
+ }
doTestAllowedUids(defaultSubId, TRANSPORT_BLUETOOTH, uid, expectUidsPresent = false)
doTestAllowedUids(defaultSubId, intArrayOf(TRANSPORT_CELLULAR, TRANSPORT_WIFI), uid,
expectUidsPresent = false)
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 125707f..20b0801 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -17596,17 +17596,18 @@
// TODO : fix the builder
ncb.setNetworkSpecifier(null);
ncb.removeTransportType(TRANSPORT_CELLULAR);
- ncb.addTransportType(TRANSPORT_WIFI);
+ ncb.addTransportType(TRANSPORT_BLUETOOTH);
// Wifi does not get to set access UID, even to the correct UID
mCm.requestNetwork(new NetworkRequest.Builder()
- .addTransportType(TRANSPORT_WIFI)
+ .addTransportType(TRANSPORT_BLUETOOTH)
.removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
.build(), cb);
- mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, new LinkProperties(), ncb.build());
- mWiFiAgent.connect(true);
- cb.expectAvailableThenValidatedCallbacks(mWiFiAgent);
+ final TestNetworkAgentWrapper bluetoothAgent = new TestNetworkAgentWrapper(
+ TRANSPORT_BLUETOOTH, new LinkProperties(), ncb.build());
+ bluetoothAgent.connect(true);
+ cb.expectAvailableThenValidatedCallbacks(bluetoothAgent);
ncb.setAllowedUids(serviceUidSet);
- mWiFiAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
+ bluetoothAgent.setNetworkCapabilities(ncb.build(), true /* sendToCS */);
cb.assertNoCallback(TEST_CALLBACK_TIMEOUT_MS);
mCm.unregisterNetworkCallback(cb);
}