Merge changes I30f8814c,Ifdf67318,If312b8f8 into main

* changes:
  Rename hasCarrierPrivilege... to isCarrierServiceUid...
  Detect discrepancies in subIds
  Allow carrier service UIDs to access their own WiFi networks.
This commit is contained in:
Jean Chalard
2023-11-20 06:55:04 +00:00
committed by Gerrit Code Review
6 changed files with 73 additions and 42 deletions

View File

@@ -5263,7 +5263,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean hasCarrierPrivilegeForNetworkCaps(final int callingUid,
@NonNull final NetworkCapabilities caps) {
if (mCarrierPrivilegeAuthenticator != null) {
return mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
return mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
callingUid, caps);
}
return false;

View File

@@ -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.content.pm.PackageManager;
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;
@@ -211,12 +214,13 @@ public class CarrierPrivilegeAuthenticator {
*
* 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.
*
@@ -224,13 +228,28 @@ public class CarrierPrivilegeAuthenticator {
* @param networkCapabilities the network capabilities for which carrier privilege is checked.
* @return true if uid provides the relevant carrier config else false.
*/
public boolean hasCarrierPrivilegeForNetworkCapabilities(int callingUid,
public boolean isCarrierServiceUidForNetworkCapabilities(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;
}
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
&& !networkCapabilities.getSubscriptionIds().contains(subId)) {
// Ideally, the code above should just use networkCapabilities.getSubscriptionIds()
// for simplicity and future-proofing. However, this is not the historical behavior,
// and there is no enforcement that they do not differ, so log a terrible failure if
// they do not match to gain confidence this never happens.
// TODO : when there is confidence that this never happens, rewrite the code above
// with NetworkCapabilities#getSubscriptionIds.
Log.wtf(TAG, "NetworkCapabilities subIds are inconsistent between "
+ "specifier/transportInfo and mSubIds : " + networkCapabilities);
}
final int subId = getSubIdFromNetworkSpecifier(networkCapabilities.getNetworkSpecifier());
if (SubscriptionManager.INVALID_SUBSCRIPTION_ID == subId) return false;
return callingUid == getCarrierServiceUidForSubId(subId);
}
@@ -258,14 +277,6 @@ public class CarrierPrivilegeAuthenticator {
return SubscriptionManager.getSlotIndex(subId);
}
@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) {
@@ -291,8 +302,22 @@ public class CarrierPrivilegeAuthenticator {
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 {

View File

@@ -23,6 +23,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
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,12 +1592,13 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
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(
&& (carrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
nc.getAllowedUidsNoCopy().valueAt(0), nc))) {
return true;
}

View File

@@ -757,8 +757,8 @@ class NetworkAgentTest {
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 @@ class NetworkAgentTest {
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)

View File

@@ -79,7 +79,6 @@ import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPR
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OFF;
@@ -17531,7 +17530,7 @@ public class ConnectivityServiceTest {
// In this test TEST_PACKAGE_UID will be the UID of the carrier service UID.
doReturn(true).when(mCarrierPrivilegeAuthenticator)
.hasCarrierPrivilegeForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
.isCarrierServiceUidForNetworkCapabilities(eq(TEST_PACKAGE_UID), any());
// Simulate a restricted telephony network. The telephony factory is entitled to set
// the access UID to the service package on any of its restricted networks.
@@ -17596,17 +17595,18 @@ public class ConnectivityServiceTest {
// 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);
}

View File

@@ -174,9 +174,9 @@ public class CarrierPrivilegeAuthenticatorTest {
.addTransportType(TRANSPORT_CELLULAR)
.setNetworkSpecifier(new TelephonyNetworkSpecifier(0));
assertTrue(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertTrue(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
assertFalse(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid + 1, ncBuilder.build()));
}
@@ -213,9 +213,9 @@ public class CarrierPrivilegeAuthenticatorTest {
.addTransportType(TRANSPORT_CELLULAR)
.setNetworkSpecifier(specifier)
.build();
assertTrue(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertTrue(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, nc));
assertFalse(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid + 1, nc));
}
@@ -235,9 +235,9 @@ public class CarrierPrivilegeAuthenticatorTest {
listener.onCarrierPrivilegesChanged(Collections.emptyList(), new int[] {});
listener.onCarrierServiceChanged(null, applicationInfo.uid);
assertFalse(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, nc));
assertTrue(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertTrue(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid + 1, nc));
}
@@ -248,11 +248,11 @@ public class CarrierPrivilegeAuthenticatorTest {
final NetworkCapabilities.Builder ncBuilder = new NetworkCapabilities.Builder();
ncBuilder.addTransportType(TRANSPORT_CELLULAR);
assertFalse(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
ncBuilder.setNetworkSpecifier(new TelephonyNetworkSpecifier(0));
assertTrue(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertTrue(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
// The builder for NetworkCapabilities doesn't allow removing the transport as long as a
@@ -261,7 +261,7 @@ public class CarrierPrivilegeAuthenticatorTest {
ncBuilder.removeTransportType(TRANSPORT_CELLULAR);
ncBuilder.addTransportType(TRANSPORT_WIFI);
ncBuilder.setNetworkSpecifier(new TelephonyNetworkSpecifier(0));
assertFalse(mCarrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
assertFalse(mCarrierPrivilegeAuthenticator.isCarrierServiceUidForNetworkCapabilities(
mCarrierConfigPkgUid, ncBuilder.build()));
}
}