Merge "Add more powerful CTS for allowedUids" into main
This commit is contained in:
commit
51c80a72d8
12 changed files with 455 additions and 41 deletions
|
|
@ -1457,6 +1457,18 @@ public final class NetworkCapabilities implements Parcelable {
|
|||
return mTransportTypes == (1 << transportType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff this NC has the specified transport and no other, ignoring TRANSPORT_TEST.
|
||||
*
|
||||
* If this NC has the passed transport and no other, this method returns true.
|
||||
* If this NC has the passed transport, TRANSPORT_TEST and no other, this method returns true.
|
||||
* Otherwise, this method returns false.
|
||||
* @hide
|
||||
*/
|
||||
public boolean hasSingleTransportBesidesTest(@Transport int transportType) {
|
||||
return (mTransportTypes & ~(1 << TRANSPORT_TEST)) == (1 << transportType);
|
||||
}
|
||||
|
||||
private boolean satisfiedByTransportTypes(NetworkCapabilities nc) {
|
||||
return ((this.mTransportTypes == 0)
|
||||
|| ((this.mTransportTypes & nc.mTransportTypes) != 0));
|
||||
|
|
|
|||
|
|
@ -2649,6 +2649,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
}
|
||||
}
|
||||
|
||||
private boolean canSeeAllowedUids(final int pid, final int uid, final int netOwnerUid) {
|
||||
return Process.SYSTEM_UID == uid
|
||||
|| netOwnerUid == uid
|
||||
|| checkAnyPermissionOf(mContext, pid, uid,
|
||||
android.Manifest.permission.NETWORK_FACTORY);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
|
||||
NetworkCapabilities nc, int callerPid, int callerUid) {
|
||||
|
|
@ -2670,8 +2677,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)) {
|
||||
newNc.setAdministratorUids(new int[0]);
|
||||
}
|
||||
if (!checkAnyPermissionOf(mContext,
|
||||
callerPid, callerUid, android.Manifest.permission.NETWORK_FACTORY)) {
|
||||
if (!canSeeAllowedUids(callerPid, callerUid, newNc.getOwnerUid())) {
|
||||
newNc.setAllowedUids(new ArraySet<>());
|
||||
newNc.setSubscriptionIds(Collections.emptySet());
|
||||
}
|
||||
|
|
@ -3944,6 +3950,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||
pw.println();
|
||||
dumpBpfProgramStatus(pw);
|
||||
|
||||
if (null != mCarrierPrivilegeAuthenticator) {
|
||||
pw.println();
|
||||
mCarrierPrivilegeAuthenticator.dump(pw);
|
||||
}
|
||||
|
||||
pw.println();
|
||||
|
||||
if (!CollectionUtils.contains(args, SHORT_ARG)) {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import android.util.SparseIntArray;
|
|||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.modules.utils.HandlerExecutor;
|
||||
import com.android.networkstack.apishim.TelephonyManagerShimImpl;
|
||||
import com.android.networkstack.apishim.common.TelephonyManagerShim;
|
||||
|
|
@ -125,11 +126,13 @@ public class CarrierPrivilegeAuthenticator {
|
|||
|
||||
private class PrivilegeListener implements CarrierPrivilegesListenerShim {
|
||||
public final int mLogicalSlot;
|
||||
|
||||
PrivilegeListener(final int logicalSlot) {
|
||||
mLogicalSlot = logicalSlot;
|
||||
}
|
||||
|
||||
@Override public void onCarrierPrivilegesChanged(
|
||||
@Override
|
||||
public void onCarrierPrivilegesChanged(
|
||||
@NonNull List<String> privilegedPackageNames,
|
||||
@NonNull int[] privilegedUids) {
|
||||
if (mUseCallbacksForServiceChanged) return;
|
||||
|
|
@ -209,7 +212,9 @@ public class CarrierPrivilegeAuthenticator {
|
|||
public boolean hasCarrierPrivilegeForNetworkCapabilities(int callingUid,
|
||||
@NonNull NetworkCapabilities networkCapabilities) {
|
||||
if (callingUid == Process.INVALID_UID) return false;
|
||||
if (!networkCapabilities.hasSingleTransport(TRANSPORT_CELLULAR)) return false;
|
||||
if (!networkCapabilities.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)) {
|
||||
return false;
|
||||
}
|
||||
final int subId = getSubIdFromNetworkSpecifier(networkCapabilities.getNetworkSpecifier());
|
||||
if (SubscriptionManager.INVALID_SUBSCRIPTION_ID == subId) return false;
|
||||
return callingUid == getCarrierServiceUidForSubId(subId);
|
||||
|
|
@ -292,4 +297,16 @@ public class CarrierPrivilegeAuthenticator {
|
|||
Log.e(TAG, "removeCarrierPrivilegesListener API is not available");
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(IndentingPrintWriter pw) {
|
||||
pw.println("CarrierPrivilegeAuthenticator:");
|
||||
synchronized (mLock) {
|
||||
final int size = mCarrierServiceUid.size();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
final int logicalSlot = mCarrierServiceUid.keyAt(i);
|
||||
final int serviceUid = mCarrierServiceUid.valueAt(i);
|
||||
pw.println("Logical slot = " + logicalSlot + " : uid = " + serviceUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package com.android.server.connectivity;
|
||||
|
||||
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||
|
|
@ -1549,7 +1550,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
* @param hasAutomotiveFeature true if this device has the automotive feature, false otherwise
|
||||
* @param authenticator the carrier privilege authenticator to check for telephony constraints
|
||||
*/
|
||||
public static void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
|
||||
public void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
|
||||
final int creatorUid, final boolean hasAutomotiveFeature,
|
||||
@NonNull final ConnectivityService.Dependencies deps,
|
||||
@Nullable final CarrierPrivilegeAuthenticator authenticator) {
|
||||
|
|
@ -1562,7 +1563,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean areAllowedUidsAcceptableFromNetworkAgent(
|
||||
private boolean areAllowedUidsAcceptableFromNetworkAgent(
|
||||
@NonNull final NetworkCapabilities nc, final boolean hasAutomotiveFeature,
|
||||
@NonNull final ConnectivityService.Dependencies deps,
|
||||
@Nullable final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {
|
||||
|
|
@ -1575,19 +1576,25 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
|||
// On a non-restricted network, access UIDs make no sense
|
||||
if (nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) return false;
|
||||
|
||||
// If this network has TRANSPORT_TEST, then the caller can do whatever they want to
|
||||
// access UIDs
|
||||
if (nc.hasTransport(TRANSPORT_TEST)) return true;
|
||||
// If this network has TRANSPORT_TEST and nothing else, then the caller can do whatever
|
||||
// they want to access UIDs
|
||||
if (nc.hasSingleTransport(TRANSPORT_TEST)) return true;
|
||||
|
||||
// Factories that make ethernet networks can allow UIDs for automotive devices.
|
||||
if (nc.hasSingleTransport(TRANSPORT_ETHERNET) && hasAutomotiveFeature) {
|
||||
return true;
|
||||
if (nc.hasTransport(TRANSPORT_ETHERNET)) {
|
||||
// Factories that make ethernet networks can allow UIDs for automotive devices.
|
||||
if (hasAutomotiveFeature) return true;
|
||||
// It's also admissible if the ethernet network has TRANSPORT_TEST, as long as it
|
||||
// doesn't have NET_CAPABILITY_INTERNET so it can't become the default network.
|
||||
if (nc.hasTransport(TRANSPORT_TEST) && !nc.hasCapability(NET_CAPABILITY_INTERNET)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Factories that make cell 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.hasSingleTransport(TRANSPORT_CELLULAR)
|
||||
&& nc.hasSingleTransportBesidesTest(TRANSPORT_CELLULAR)
|
||||
&& (1 == nc.getAllowedUidsNoCopy().size())
|
||||
&& (carrierPrivilegeAuthenticator.hasCarrierPrivilegeForNetworkCapabilities(
|
||||
nc.getAllowedUidsNoCopy().valueAt(0), nc))) {
|
||||
|
|
|
|||
|
|
@ -62,10 +62,13 @@ java_defaults {
|
|||
// uncomment when b/13249961 is fixed
|
||||
// sdk_version: "current",
|
||||
platform_apis: true,
|
||||
data: [":ConnectivityTestPreparer"],
|
||||
per_testcase_directory: true,
|
||||
host_required: ["net-tests-utils-host-common"],
|
||||
test_config_template: "AndroidTestTemplate.xml",
|
||||
data: [
|
||||
":ConnectivityTestPreparer",
|
||||
":CtsCarrierServicePackage",
|
||||
]
|
||||
}
|
||||
|
||||
// Networking CTS tests for development and release. These tests always target the platform SDK
|
||||
|
|
@ -154,3 +157,17 @@ android_test {
|
|||
package_name: "android.net.cts.maxtargetsdk30", // CTS package names must be unique.
|
||||
instrumentation_target_package: "android.net.cts.maxtargetsdk30",
|
||||
}
|
||||
|
||||
android_test_helper_app {
|
||||
name: "CtsCarrierServicePackage",
|
||||
defaults: ["cts_defaults"],
|
||||
package_name: "android.net.cts.carrierservicepackage",
|
||||
manifest: "carrierservicepackage/AndroidManifest.xml",
|
||||
srcs: ["carrierservicepackage/src/**/*.java"],
|
||||
min_sdk_version: "30",
|
||||
// Tag this module as a cts test artifact
|
||||
test_suites: [
|
||||
"cts",
|
||||
"general-tests",
|
||||
],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||
|
||||
<!-- This test also uses signature permissions through adopting the shell identity.
|
||||
The permissions acquired that way include (probably not exhaustive) :
|
||||
|
|
@ -46,6 +47,7 @@
|
|||
android:usesCleartextTraffic="true">
|
||||
<uses-library android:name="android.test.runner" />
|
||||
<uses-library android:name="org.apache.http.legacy" android:required="false" />
|
||||
|
||||
</application>
|
||||
|
||||
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||
|
|
@ -54,4 +56,3 @@
|
|||
</instrumentation>
|
||||
|
||||
</manifest>
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
|
||||
<option name="cleanup-apks" value="true" />
|
||||
<option name="test-file-name" value="{MODULE}.apk" />
|
||||
<option name="test-file-name" value="CtsCarrierServicePackage.apk" />
|
||||
</target_preparer>
|
||||
<target_preparer class="com.android.testutils.ConnectivityTestTargetPreparer">
|
||||
</target_preparer>
|
||||
|
|
|
|||
36
tests/cts/net/carrierservicepackage/AndroidManifest.xml
Normal file
36
tests/cts/net/carrierservicepackage/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0.0"
|
||||
package="android.net.cts.carrierservicepackage">
|
||||
<uses-sdk android:minSdkVersion="30"
|
||||
android:targetSdkVersion="33" />
|
||||
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
|
||||
<application android:allowBackup="false"
|
||||
android:directBootAware="true">
|
||||
<service android:name=".DummyCarrierConfigService"
|
||||
android:permission="android.permission.BIND_CARRIER_SERVICES"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.carrier.CarrierService"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net.cts.carrierservicepackage;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.PersistableBundle;
|
||||
import android.service.carrier.CarrierIdentifier;
|
||||
import android.service.carrier.CarrierService;
|
||||
|
||||
public class DummyCarrierConfigService extends CarrierService {
|
||||
private static final String TAG = "DummyCarrierConfigService";
|
||||
|
||||
public DummyCarrierConfigService() {}
|
||||
|
||||
@Override
|
||||
public PersistableBundle onLoadConfig(CarrierIdentifier id) {
|
||||
return new PersistableBundle(); // Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return super.onBind(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnbind(Intent intent) {
|
||||
return super.onUnbind(intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -796,14 +796,15 @@ public class ConnectivityManagerTest {
|
|||
// Make sure that the NC is null if the package doesn't hold ACCESS_NETWORK_STATE.
|
||||
assertNull(redactNc(nc, groundedUid, groundedPkg));
|
||||
|
||||
// Uids, ssid, underlying networks & subscriptionIds will be redacted if the given uid
|
||||
// Uids, ssid & underlying networks will be redacted if the given uid
|
||||
// doesn't hold the associated permissions. The wifi transport info is also suitably
|
||||
// redacted.
|
||||
final NetworkCapabilities redactedNormal = redactNc(nc, normalUid, normalPkg);
|
||||
assertNull(redactedNormal.getUids());
|
||||
assertNull(redactedNormal.getSsid());
|
||||
assertNull(redactedNormal.getUnderlyingNetworks());
|
||||
assertEquals(0, redactedNormal.getSubscriptionIds().size());
|
||||
// Owner UID is allowed to see the subscription IDs.
|
||||
assertEquals(2, redactedNormal.getSubscriptionIds().size());
|
||||
assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS,
|
||||
((WifiInfo) redactedNormal.getTransportInfo()).getBSSID());
|
||||
assertEquals(rssi, ((WifiInfo) redactedNormal.getTransportInfo()).getRssi());
|
||||
|
|
|
|||
|
|
@ -15,9 +15,12 @@
|
|||
*/
|
||||
package android.net.cts
|
||||
|
||||
import android.Manifest.permission.MODIFY_PHONE_STATE
|
||||
import android.Manifest.permission.NETWORK_SETTINGS
|
||||
import android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
|
||||
import android.app.Instrumentation
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.EthernetNetworkSpecifier
|
||||
import android.net.INetworkAgent
|
||||
|
|
@ -44,7 +47,9 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN
|
|||
import android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
|
||||
import android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH
|
||||
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
||||
import android.net.NetworkCapabilities.TRANSPORT_ETHERNET
|
||||
import android.net.NetworkCapabilities.TRANSPORT_TEST
|
||||
import android.net.NetworkCapabilities.TRANSPORT_VPN
|
||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||
|
|
@ -53,6 +58,7 @@ import android.net.NetworkProvider
|
|||
import android.net.NetworkReleasedException
|
||||
import android.net.NetworkRequest
|
||||
import android.net.NetworkScore
|
||||
import android.net.NetworkSpecifier
|
||||
import android.net.QosCallback
|
||||
import android.net.QosCallback.QosCallbackRegistrationException
|
||||
import android.net.QosCallbackException
|
||||
|
|
@ -61,6 +67,7 @@ import android.net.QosSessionAttributes
|
|||
import android.net.QosSocketInfo
|
||||
import android.net.RouteInfo
|
||||
import android.net.SocketKeepalive
|
||||
import android.net.TelephonyNetworkSpecifier
|
||||
import android.net.TestNetworkInterface
|
||||
import android.net.TestNetworkManager
|
||||
import android.net.Uri
|
||||
|
|
@ -69,21 +76,31 @@ import android.net.VpnTransportInfo
|
|||
import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnError
|
||||
import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionAvailable
|
||||
import android.net.cts.NetworkAgentTest.TestableQosCallback.CallbackEntry.OnQosSessionLost
|
||||
import android.net.wifi.WifiInfo
|
||||
import android.os.Build
|
||||
import android.os.ConditionVariable
|
||||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.Message
|
||||
import android.os.PersistableBundle
|
||||
import android.os.Process
|
||||
import android.os.SystemClock
|
||||
import android.platform.test.annotations.AppModeFull
|
||||
import android.system.OsConstants.IPPROTO_TCP
|
||||
import android.system.OsConstants.IPPROTO_UDP
|
||||
import android.telephony.CarrierConfigManager
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.TelephonyManager.CarrierPrivilegesCallback
|
||||
import android.telephony.data.EpsBearerQosSessionAttributes
|
||||
import android.util.ArraySet
|
||||
import android.util.DebugUtils.valueToString
|
||||
import android.util.Log
|
||||
import androidx.test.InstrumentationRegistry
|
||||
import com.android.compatibility.common.util.SystemUtil.runShellCommand
|
||||
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
|
||||
import com.android.compatibility.common.util.ThrowingSupplier
|
||||
import com.android.compatibility.common.util.UiccUtil
|
||||
import com.android.modules.utils.build.SdkLevel
|
||||
import com.android.net.module.util.ArrayTrackRecord
|
||||
import com.android.testutils.CompatUtil
|
||||
|
|
@ -112,23 +129,8 @@ import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnUnregisterQosC
|
|||
import com.android.testutils.TestableNetworkAgent.CallbackEntry.OnValidationStatus
|
||||
import com.android.testutils.TestableNetworkCallback
|
||||
import com.android.testutils.assertThrows
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
import java.net.DatagramSocket
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Socket
|
||||
import java.time.Duration
|
||||
import java.util.Arrays
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
import com.android.testutils.runAsShell
|
||||
import com.android.testutils.tryTest
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
|
@ -140,7 +142,26 @@ import org.mockito.Mockito.doReturn
|
|||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.timeout
|
||||
import org.mockito.Mockito.verify
|
||||
import java.io.Closeable
|
||||
import java.io.IOException
|
||||
import java.net.DatagramSocket
|
||||
import java.net.InetAddress
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Socket
|
||||
import java.security.MessageDigest
|
||||
import java.time.Duration
|
||||
import java.util.Arrays
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
private const val TAG = "NetworkAgentTest"
|
||||
// This test doesn't really have a constraint on how fast the methods should return. If it's
|
||||
// going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio
|
||||
// without affecting the run time of successful runs. Thus, set a very high timeout.
|
||||
|
|
@ -261,17 +282,18 @@ class NetworkAgentTest {
|
|||
callbacksToCleanUp.add(callback)
|
||||
}
|
||||
|
||||
private fun makeTestNetworkRequest(specifier: String? = null): NetworkRequest {
|
||||
return NetworkRequest.Builder()
|
||||
.clearCapabilities()
|
||||
.addTransportType(TRANSPORT_TEST)
|
||||
.also {
|
||||
if (specifier != null) {
|
||||
it.setNetworkSpecifier(CompatUtil.makeEthernetNetworkSpecifier(specifier))
|
||||
}
|
||||
}
|
||||
.build()
|
||||
}
|
||||
private fun String?.asEthSpecifier(): NetworkSpecifier? =
|
||||
if (null == this) null else CompatUtil.makeEthernetNetworkSpecifier(this)
|
||||
private fun makeTestNetworkRequest(specifier: NetworkSpecifier? = null) =
|
||||
NetworkRequest.Builder().run {
|
||||
clearCapabilities()
|
||||
addTransportType(TRANSPORT_TEST)
|
||||
if (specifier != null) setNetworkSpecifier(specifier)
|
||||
build()
|
||||
}
|
||||
|
||||
private fun makeTestNetworkRequest(specifier: String?) =
|
||||
makeTestNetworkRequest(specifier.asEthSpecifier())
|
||||
|
||||
private fun makeTestNetworkCapabilities(
|
||||
specifier: String? = null,
|
||||
|
|
@ -322,7 +344,7 @@ class NetworkAgentTest {
|
|||
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
|
||||
val callback = TestableNetworkCallback()
|
||||
// Ensure this NetworkAgent is never unneeded by filing a request with its specifier.
|
||||
requestNetwork(makeTestNetworkRequest(specifier = specifier), callback)
|
||||
requestNetwork(makeTestNetworkRequest(specifier), callback)
|
||||
val nc = makeTestNetworkCapabilities(specifier, transports)
|
||||
val agent = createNetworkAgent(context, initialConfig = initialConfig, initialNc = nc)
|
||||
agent.setTeardownDelayMillis(0)
|
||||
|
|
@ -543,6 +565,227 @@ class NetworkAgentTest {
|
|||
.addTransportType(TRANSPORT_TEST)
|
||||
.setAllowedUids(uids.toSet()).build()
|
||||
|
||||
/**
|
||||
* Get the single element from this ArraySet, or fail() if doesn't contain exactly 1 element.
|
||||
*/
|
||||
fun <T> ArraySet<T>.getSingleElement(): T {
|
||||
if (size != 1) fail("Expected exactly one element, contained $size")
|
||||
return iterator().next()
|
||||
}
|
||||
|
||||
private fun doTestAllowedUids(
|
||||
subId: Int,
|
||||
transport: Int,
|
||||
uid: Int,
|
||||
expectUidsPresent: Boolean
|
||||
) {
|
||||
doTestAllowedUids(subId, intArrayOf(transport), uid, expectUidsPresent)
|
||||
}
|
||||
|
||||
private fun doTestAllowedUids(
|
||||
subId: Int,
|
||||
transports: IntArray,
|
||||
uid: Int,
|
||||
expectUidsPresent: Boolean
|
||||
) {
|
||||
val callback = TestableNetworkCallback(DEFAULT_TIMEOUT_MS)
|
||||
val specifier = when {
|
||||
transports.size != 1 -> null
|
||||
TRANSPORT_ETHERNET in transports -> EthernetNetworkSpecifier("testInterface")
|
||||
TRANSPORT_CELLULAR in transports -> TelephonyNetworkSpecifier(subId)
|
||||
else -> null
|
||||
}
|
||||
val agent = createNetworkAgent(initialNc = NetworkCapabilities.Builder().run {
|
||||
addTransportType(TRANSPORT_TEST)
|
||||
transports.forEach { addTransportType(it) }
|
||||
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
||||
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||
removeCapability(NET_CAPABILITY_NOT_RESTRICTED)
|
||||
setNetworkSpecifier(specifier)
|
||||
if (TRANSPORT_WIFI in transports && SdkLevel.isAtLeastV()) {
|
||||
// setSubscriptionId only exists in V+
|
||||
setTransportInfo(WifiInfo.Builder().setSubscriptionId(subId).build())
|
||||
}
|
||||
setAllowedUids(setOf(uid))
|
||||
setOwnerUid(Process.myUid())
|
||||
setAdministratorUids(intArrayOf(Process.myUid()))
|
||||
build()
|
||||
})
|
||||
runWithShellPermissionIdentity {
|
||||
agent.register()
|
||||
}
|
||||
agent.markConnected()
|
||||
|
||||
registerNetworkCallback(makeTestNetworkRequest(specifier), callback)
|
||||
callback.expect<Available>(agent.network!!)
|
||||
callback.expect<CapabilitiesChanged>(agent.network!!) {
|
||||
if (expectUidsPresent) {
|
||||
it.caps.allowedUidsNoCopy.getSingleElement() == uid
|
||||
} else {
|
||||
it.caps.allowedUidsNoCopy.isEmpty()
|
||||
}
|
||||
}
|
||||
agent.unregister()
|
||||
// callback will be unregistered in tearDown()
|
||||
}
|
||||
|
||||
private fun setHoldCarrierPrivilege(hold: Boolean, subId: Int) {
|
||||
fun getCertHash(): String {
|
||||
val pkgInfo = realContext.packageManager.getPackageInfo(realContext.opPackageName,
|
||||
PackageManager.GET_SIGNATURES)
|
||||
val digest = MessageDigest.getInstance("SHA-256")
|
||||
val certHash = digest.digest(pkgInfo.signatures!![0]!!.toByteArray())
|
||||
return UiccUtil.bytesToHexString(certHash)!!
|
||||
}
|
||||
|
||||
val tm = realContext.getSystemService(TelephonyManager::class.java)!!
|
||||
val ccm = realContext.getSystemService(CarrierConfigManager::class.java)!!
|
||||
|
||||
val cv = ConditionVariable()
|
||||
val cpb = PrivilegeWaiterCallback(cv)
|
||||
tryTest {
|
||||
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
|
||||
}
|
||||
// Wait for the callback to be registered
|
||||
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't register CarrierPrivilegesCallback")
|
||||
if (cpb.hasPrivilege == hold) {
|
||||
if (hold) {
|
||||
Log.w(TAG, "Package ${realContext.opPackageName} already is privileged")
|
||||
} else {
|
||||
Log.w(TAG, "Package ${realContext.opPackageName} already isn't privileged")
|
||||
}
|
||||
return@tryTest
|
||||
}
|
||||
cv.close()
|
||||
runAsShell(MODIFY_PHONE_STATE) {
|
||||
val carrierConfigs = if (hold) {
|
||||
PersistableBundle().also {
|
||||
it.putStringArray(CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY,
|
||||
arrayOf(getCertHash()))
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
ccm.overrideConfig(subId, carrierConfigs)
|
||||
}
|
||||
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't change carrier privilege")
|
||||
} cleanup {
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.unregisterCarrierPrivilegesCallback(cpb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun acquireCarrierPrivilege(subId: Int) = setHoldCarrierPrivilege(true, subId)
|
||||
private fun dropCarrierPrivilege(subId: Int) = setHoldCarrierPrivilege(false, subId)
|
||||
|
||||
private fun setCarrierServicePackageOverride(subId: Int, pkg: String?) {
|
||||
val tm = realContext.getSystemService(TelephonyManager::class.java)!!
|
||||
|
||||
val cv = ConditionVariable()
|
||||
val cpb = CarrierServiceChangedWaiterCallback(cv)
|
||||
tryTest {
|
||||
val slotIndex = SubscriptionManager.getSlotIndex(subId)!!
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.registerCarrierPrivilegesCallback(slotIndex, { it.run() }, cpb)
|
||||
}
|
||||
// Wait for the callback to be registered
|
||||
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't register CarrierPrivilegesCallback")
|
||||
if (cpb.pkgName == pkg) {
|
||||
Log.w(TAG, "Carrier service package was already $pkg")
|
||||
return@tryTest
|
||||
}
|
||||
cv.close()
|
||||
runAsShell(MODIFY_PHONE_STATE) {
|
||||
if (null == pkg) {
|
||||
// There is a bug is clear-carrier-service-package-override where not adding
|
||||
// the -s argument will use the wrong slot index : b/299604822
|
||||
runShellCommand("cmd phone clear-carrier-service-package-override" +
|
||||
" -s $subId")
|
||||
} else {
|
||||
// -s could set the subId, but this test works with the default subId.
|
||||
runShellCommand("cmd phone set-carrier-service-package-override $pkg")
|
||||
}
|
||||
}
|
||||
assertTrue(cv.block(DEFAULT_TIMEOUT_MS), "Can't modify carrier service package")
|
||||
} cleanup {
|
||||
runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.unregisterCarrierPrivilegesCallback(cpb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.execute() = runShellCommand(this).trim()
|
||||
|
||||
@Test
|
||||
@IgnoreUpTo(Build.VERSION_CODES.S)
|
||||
fun testAllowedUids() {
|
||||
// Use a different package than this one to make sure that a package that doesn't hold
|
||||
// carrier service permission can be set as an allowed UID.
|
||||
val servicePackage = "android.net.cts.carrierservicepackage"
|
||||
val uid = try {
|
||||
realContext.packageManager.getApplicationInfo(servicePackage, 0).uid
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
fail("$servicePackage could not be installed, please check the SuiteApkInstaller" +
|
||||
" installed CtsCarrierServicePackage.apk", e)
|
||||
}
|
||||
|
||||
val tm = realContext.getSystemService(TelephonyManager::class.java)!!
|
||||
val defaultSubId = SubscriptionManager.getDefaultSubscriptionId()
|
||||
tryTest {
|
||||
// This process is not the carrier service UID, so allowedUids should be ignored in all
|
||||
// the following cases.
|
||||
doTestAllowedUids(defaultSubId, TRANSPORT_CELLULAR, uid, expectUidsPresent = false)
|
||||
doTestAllowedUids(defaultSubId, TRANSPORT_WIFI, uid, expectUidsPresent = false)
|
||||
doTestAllowedUids(defaultSubId, TRANSPORT_BLUETOOTH, uid, expectUidsPresent = false)
|
||||
|
||||
// The tools to set the carrier service package override do not exist before U,
|
||||
// so there is no way to test the rest of this test on < U.
|
||||
if (!SdkLevel.isAtLeastU()) return@tryTest
|
||||
// Acquiring carrier privilege is necessary to override the carrier service package.
|
||||
val defaultSlotIndex = SubscriptionManager.getSlotIndex(defaultSubId)
|
||||
acquireCarrierPrivilege(defaultSubId)
|
||||
setCarrierServicePackageOverride(defaultSubId, servicePackage)
|
||||
val actualServicePackage: String? = runAsShell(READ_PRIVILEGED_PHONE_STATE) {
|
||||
tm.getCarrierServicePackageNameForLogicalSlot(defaultSlotIndex)
|
||||
}
|
||||
assertEquals(servicePackage, actualServicePackage)
|
||||
|
||||
// Wait for CarrierServiceAuthenticator to have seen the update of the service package
|
||||
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")
|
||||
.filter { it.contains("Logical slot = $defaultSlotIndex.*") })
|
||||
}
|
||||
if ("dumpsys connectivity"
|
||||
.execute()
|
||||
.split("\n")
|
||||
.filter { it.contains("Logical slot = $defaultSlotIndex : uid = $uid") }
|
||||
.isNotEmpty()) {
|
||||
// Found the configuration
|
||||
break
|
||||
}
|
||||
Thread.sleep(500)
|
||||
}
|
||||
|
||||
// Cell is allowed to set UIDs, but not WIFI/BLUETOOTH or agents with multiple
|
||||
// transports.
|
||||
doTestAllowedUids(defaultSubId, TRANSPORT_CELLULAR, uid, expectUidsPresent = true)
|
||||
doTestAllowedUids(defaultSubId, TRANSPORT_WIFI, uid, expectUidsPresent = false)
|
||||
doTestAllowedUids(defaultSubId, TRANSPORT_BLUETOOTH, uid, expectUidsPresent = false)
|
||||
doTestAllowedUids(defaultSubId, intArrayOf(TRANSPORT_CELLULAR, TRANSPORT_WIFI), uid,
|
||||
expectUidsPresent = false)
|
||||
} cleanupStep {
|
||||
if (SdkLevel.isAtLeastU()) setCarrierServicePackageOverride(defaultSubId, null)
|
||||
} cleanup {
|
||||
if (SdkLevel.isAtLeastU()) dropCarrierPrivilege(defaultSubId)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRejectedUpdates() {
|
||||
val callback = TestableNetworkCallback(DEFAULT_TIMEOUT_MS)
|
||||
|
|
@ -1497,3 +1740,25 @@ class NetworkAgentTest {
|
|||
doTestNativeNetworkCreation(expectCreatedImmediately = true, intArrayOf(TRANSPORT_VPN))
|
||||
}
|
||||
}
|
||||
|
||||
// Subclasses of CarrierPrivilegesCallback can't be inline, or they'll be compiled as
|
||||
// inner classes of the test class and will fail resolution on R as the test harness
|
||||
// uses reflection to list all methods and classes
|
||||
class PrivilegeWaiterCallback(private val cv: ConditionVariable) :
|
||||
CarrierPrivilegesCallback {
|
||||
var hasPrivilege = false
|
||||
override fun onCarrierPrivilegesChanged(p: MutableSet<String>, uids: MutableSet<Int>) {
|
||||
hasPrivilege = uids.contains(Process.myUid())
|
||||
cv.open()
|
||||
}
|
||||
}
|
||||
|
||||
class CarrierServiceChangedWaiterCallback(private val cv: ConditionVariable) :
|
||||
CarrierPrivilegesCallback {
|
||||
var pkgName: String? = null
|
||||
override fun onCarrierPrivilegesChanged(p: MutableSet<String>, u: MutableSet<Int>) {}
|
||||
override fun onCarrierServiceChanged(pkgName: String?, uid: Int) {
|
||||
this.pkgName = pkgName
|
||||
cv.open()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17385,6 +17385,7 @@ public class ConnectivityServiceTest {
|
|||
mCm.requestNetwork(new NetworkRequest.Builder()
|
||||
.clearCapabilities()
|
||||
.addTransportType(TRANSPORT_TEST)
|
||||
.addTransportType(TRANSPORT_CELLULAR)
|
||||
.build(),
|
||||
cb);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue